Add EVMS FSIM plugin to e2fsprogs.

diff --git a/ChangeLog b/ChangeLog
index da51af7..9506d93 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2002-05-24    <tytso@snap.thunk.org>
+
+	* configure.in: Add makefile for lib/evms for the EVMS FSIM
+		plugin.  Add --enable-old-evms configure option which uses
+		the EVMS 1.0.0 ABI, instead of the ABI used by EVMS 1.1.0.
+
 2002-05-21  Theodore Ts'o  <tytso@mit.edu>
 
 	* configure.in: On Linux systems, if the prefix is defaulted to
diff --git a/configure b/configure
index 30d0d1e..57d1348 100644
--- a/configure
+++ b/configure
@@ -24,6 +24,8 @@
 ac_help="$ac_help
   --enable-compression	  enable EXPERIMENTAL compression support"
 ac_help="$ac_help
+  --enable-old-evms	  use EVMS 1.0 ABI (instead of EVMS 1.1)"
+ac_help="$ac_help
   --enable-dll-shlibs	  select DLL libraries"
 ac_help="$ac_help
   --enable-elf-shlibs	  select ELF shared libraries"
@@ -632,7 +634,7 @@
 fi
 
 echo $ac_n "checking host system type""... $ac_c" 1>&6
-echo "configure:636: checking host system type" >&5
+echo "configure:638: checking host system type" >&5
 
 host_alias=$host
 case "$host_alias" in
@@ -666,7 +668,7 @@
 # Extract the first word of "gcc", so it can be a program name with args.
 set dummy gcc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:670: checking for $ac_word" >&5
+echo "configure:672: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -696,7 +698,7 @@
   # Extract the first word of "cc", so it can be a program name with args.
 set dummy cc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:700: checking for $ac_word" >&5
+echo "configure:702: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -747,7 +749,7 @@
       # Extract the first word of "cl", so it can be a program name with args.
 set dummy cl; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:751: checking for $ac_word" >&5
+echo "configure:753: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -779,7 +781,7 @@
 fi
 
 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:783: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:785: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
 
 ac_ext=c
 # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@@ -790,12 +792,12 @@
 
 cat > conftest.$ac_ext << EOF
 
-#line 794 "configure"
+#line 796 "configure"
 #include "confdefs.h"
 
 main(){return(0);}
 EOF
-if { (eval echo configure:799: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:801: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   ac_cv_prog_cc_works=yes
   # If we can't run a trivial program, we are probably using a cross compiler.
   if (./conftest; exit) 2>/dev/null; then
@@ -821,12 +823,12 @@
   { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
 fi
 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:825: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:827: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
 cross_compiling=$ac_cv_prog_cc_cross
 
 echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:830: checking whether we are using GNU C" >&5
+echo "configure:832: checking whether we are using GNU C" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -835,7 +837,7 @@
   yes;
 #endif
 EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:839: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:841: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
   ac_cv_prog_gcc=yes
 else
   ac_cv_prog_gcc=no
@@ -854,7 +856,7 @@
 ac_save_CFLAGS="$CFLAGS"
 CFLAGS=
 echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:858: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:860: checking whether ${CC-cc} accepts -g" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -903,7 +905,7 @@
 CFLAGS=$withval
 fi
 echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:907: checking how to run the C preprocessor" >&5
+echo "configure:909: checking how to run the C preprocessor" >&5
 # On Suns, sometimes $CPP names a directory.
 if test -n "$CPP" && test -d "$CPP"; then
   CPP=
@@ -918,13 +920,13 @@
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp.
   cat > conftest.$ac_ext <<EOF
-#line 922 "configure"
+#line 924 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:928: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:930: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
@@ -935,13 +937,13 @@
   rm -rf conftest*
   CPP="${CC-cc} -E -traditional-cpp"
   cat > conftest.$ac_ext <<EOF
-#line 939 "configure"
+#line 941 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:945: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:947: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
@@ -952,13 +954,13 @@
   rm -rf conftest*
   CPP="${CC-cc} -nologo -E"
   cat > conftest.$ac_ext <<EOF
-#line 956 "configure"
+#line 958 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:962: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:964: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
@@ -984,17 +986,17 @@
 
 ac_safe=`echo "linux/fs.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for linux/fs.h""... $ac_c" 1>&6
-echo "configure:988: checking for linux/fs.h" >&5
+echo "configure:990: checking for linux/fs.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 993 "configure"
+#line 995 "configure"
 #include "confdefs.h"
 #include <linux/fs.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:998: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1000: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -1059,6 +1061,25 @@
 
 fi
 
+# Check whether --enable-old-evms or --disable-old-evms was given.
+if test "${enable_old_evms+set}" = set; then
+  enableval="$enable_old_evms"
+  if test "$enableval" = "no"
+then
+	echo "Using EVMS 1.1.0 ABI"
+else
+	cat >> confdefs.h <<\EOF
+#define ABI_EVMS_1_0 1
+EOF
+
+	echo "Enabling EVMS 1.0.0 ABI"
+fi
+
+else
+  echo "Using EVMS 1.1.0 ABI by default"
+
+fi
+
 # Check whether --enable-dll-shlibs or --disable-dll-shlibs was given.
 if test "${enable_dll_shlibs+set}" = set; then
   enableval="$enable_dll_shlibs"
@@ -1370,7 +1391,7 @@
 
 ALL_LINGUAS="it nyc tr"
 echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:1374: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "configure:1395: checking whether ${MAKE-make} sets \${MAKE}" >&5
 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1399,7 +1420,7 @@
 # Extract the first word of "ranlib", so it can be a program name with args.
 set dummy ranlib; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1403: checking for $ac_word" >&5
+echo "configure:1424: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1427,7 +1448,7 @@
 fi
 
 echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6
-echo "configure:1431: checking for POSIXized ISC" >&5
+echo "configure:1452: checking for POSIXized ISC" >&5
 if test -d /etc/conf/kconfig.d &&
   grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
 then
@@ -1448,12 +1469,12 @@
 fi
 
 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:1452: checking for ANSI C header files" >&5
+echo "configure:1473: checking for ANSI C header files" >&5
 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1457 "configure"
+#line 1478 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -1461,7 +1482,7 @@
 #include <float.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1465: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1486: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -1478,7 +1499,7 @@
 if test $ac_cv_header_stdc = yes; then
   # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 1482 "configure"
+#line 1503 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -1496,7 +1517,7 @@
 if test $ac_cv_header_stdc = yes; then
   # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 1500 "configure"
+#line 1521 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -1517,7 +1538,7 @@
   :
 else
   cat > conftest.$ac_ext <<EOF
-#line 1521 "configure"
+#line 1542 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -1528,7 +1549,7 @@
 exit (0); }
 
 EOF
-if { (eval echo configure:1532: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1553: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   :
 else
@@ -1552,12 +1573,12 @@
 fi
 
 echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:1556: checking for working const" >&5
+echo "configure:1577: checking for working const" >&5
 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1561 "configure"
+#line 1582 "configure"
 #include "confdefs.h"
 
 int main() {
@@ -1606,7 +1627,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:1610: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1631: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_const=yes
 else
@@ -1627,21 +1648,21 @@
 fi
 
 echo $ac_n "checking for inline""... $ac_c" 1>&6
-echo "configure:1631: checking for inline" >&5
+echo "configure:1652: checking for inline" >&5
 if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_cv_c_inline=no
 for ac_kw in inline __inline__ __inline; do
   cat > conftest.$ac_ext <<EOF
-#line 1638 "configure"
+#line 1659 "configure"
 #include "confdefs.h"
 
 int main() {
 } $ac_kw foo() {
 ; return 0; }
 EOF
-if { (eval echo configure:1645: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1666: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_inline=$ac_kw; break
 else
@@ -1667,12 +1688,12 @@
 esac
 
 echo $ac_n "checking for off_t""... $ac_c" 1>&6
-echo "configure:1671: checking for off_t" >&5
+echo "configure:1692: checking for off_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1676 "configure"
+#line 1697 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -1700,12 +1721,12 @@
 fi
 
 echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:1704: checking for size_t" >&5
+echo "configure:1725: checking for size_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1709 "configure"
+#line 1730 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -1735,19 +1756,19 @@
 # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
 # for constant arguments.  Useless!
 echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
-echo "configure:1739: checking for working alloca.h" >&5
+echo "configure:1760: checking for working alloca.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1744 "configure"
+#line 1765 "configure"
 #include "confdefs.h"
 #include <alloca.h>
 int main() {
 char *p = alloca(2 * sizeof(int));
 ; return 0; }
 EOF
-if { (eval echo configure:1751: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1772: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_header_alloca_h=yes
 else
@@ -1768,12 +1789,12 @@
 fi
 
 echo $ac_n "checking for alloca""... $ac_c" 1>&6
-echo "configure:1772: checking for alloca" >&5
+echo "configure:1793: checking for alloca" >&5
 if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1777 "configure"
+#line 1798 "configure"
 #include "confdefs.h"
 
 #ifdef __GNUC__
@@ -1801,7 +1822,7 @@
 char *p = (char *) alloca(1);
 ; return 0; }
 EOF
-if { (eval echo configure:1805: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1826: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_func_alloca_works=yes
 else
@@ -1833,12 +1854,12 @@
 
 
 echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
-echo "configure:1837: checking whether alloca needs Cray hooks" >&5
+echo "configure:1858: checking whether alloca needs Cray hooks" >&5
 if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1842 "configure"
+#line 1863 "configure"
 #include "confdefs.h"
 #if defined(CRAY) && ! defined(CRAY2)
 webecray
@@ -1863,12 +1884,12 @@
 if test $ac_cv_os_cray = yes; then
 for ac_func in _getb67 GETB67 getb67; do
   echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1867: checking for $ac_func" >&5
+echo "configure:1888: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1872 "configure"
+#line 1893 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -1891,7 +1912,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:1895: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1916: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -1918,7 +1939,7 @@
 fi
 
 echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
-echo "configure:1922: checking stack direction for C alloca" >&5
+echo "configure:1943: checking stack direction for C alloca" >&5
 if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1926,7 +1947,7 @@
   ac_cv_c_stack_direction=0
 else
   cat > conftest.$ac_ext <<EOF
-#line 1930 "configure"
+#line 1951 "configure"
 #include "confdefs.h"
 find_stack_direction ()
 {
@@ -1945,7 +1966,7 @@
   exit (find_stack_direction() < 0);
 }
 EOF
-if { (eval echo configure:1949: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1970: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_c_stack_direction=1
 else
@@ -1970,17 +1991,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1974: checking for $ac_hdr" >&5
+echo "configure:1995: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1979 "configure"
+#line 2000 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1984: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2005: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2009,12 +2030,12 @@
 for ac_func in getpagesize
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2013: checking for $ac_func" >&5
+echo "configure:2034: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2018 "configure"
+#line 2039 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2037,7 +2058,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:2041: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2062: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -2062,7 +2083,7 @@
 done
 
 echo $ac_n "checking for working mmap""... $ac_c" 1>&6
-echo "configure:2066: checking for working mmap" >&5
+echo "configure:2087: checking for working mmap" >&5
 if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -2070,7 +2091,7 @@
   ac_cv_func_mmap_fixed_mapped=no
 else
   cat > conftest.$ac_ext <<EOF
-#line 2074 "configure"
+#line 2095 "configure"
 #include "confdefs.h"
 
 /* Thanks to Mike Haertel and Jim Avera for this test.
@@ -2210,7 +2231,7 @@
 }
 
 EOF
-if { (eval echo configure:2214: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2235: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_func_mmap_fixed_mapped=yes
 else
@@ -2238,17 +2259,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2242: checking for $ac_hdr" >&5
+echo "configure:2263: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2247 "configure"
+#line 2268 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2252: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2273: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2278,12 +2299,12 @@
 strdup __argz_count __argz_stringify __argz_next
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2282: checking for $ac_func" >&5
+echo "configure:2303: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2287 "configure"
+#line 2308 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2306,7 +2327,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:2310: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2331: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -2335,12 +2356,12 @@
      for ac_func in stpcpy
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2339: checking for $ac_func" >&5
+echo "configure:2360: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2344 "configure"
+#line 2365 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2363,7 +2384,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:2367: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2388: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -2397,19 +2418,19 @@
 
    if test $ac_cv_header_locale_h = yes; then
     echo $ac_n "checking for LC_MESSAGES""... $ac_c" 1>&6
-echo "configure:2401: checking for LC_MESSAGES" >&5
+echo "configure:2422: checking for LC_MESSAGES" >&5
 if eval "test \"`echo '$''{'am_cv_val_LC_MESSAGES'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2406 "configure"
+#line 2427 "configure"
 #include "confdefs.h"
 #include <locale.h>
 int main() {
 return LC_MESSAGES
 ; return 0; }
 EOF
-if { (eval echo configure:2413: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2434: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   am_cv_val_LC_MESSAGES=yes
 else
@@ -2430,7 +2451,7 @@
     fi
   fi
    echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6
-echo "configure:2434: checking whether NLS is requested" >&5
+echo "configure:2455: checking whether NLS is requested" >&5
         # Check whether --enable-nls or --disable-nls was given.
 if test "${enable_nls+set}" = set; then
   enableval="$enable_nls"
@@ -2450,7 +2471,7 @@
 EOF
 
       echo $ac_n "checking whether included gettext is requested""... $ac_c" 1>&6
-echo "configure:2454: checking whether included gettext is requested" >&5
+echo "configure:2475: checking whether included gettext is requested" >&5
       # Check whether --with-included-gettext or --without-included-gettext was given.
 if test "${with_included_gettext+set}" = set; then
   withval="$with_included_gettext"
@@ -2469,17 +2490,17 @@
 
 	ac_safe=`echo "libintl.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for libintl.h""... $ac_c" 1>&6
-echo "configure:2473: checking for libintl.h" >&5
+echo "configure:2494: checking for libintl.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2478 "configure"
+#line 2499 "configure"
 #include "confdefs.h"
 #include <libintl.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2483: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2504: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2496,19 +2517,19 @@
 if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
   echo "$ac_t""yes" 1>&6
   echo $ac_n "checking for gettext in libc""... $ac_c" 1>&6
-echo "configure:2500: checking for gettext in libc" >&5
+echo "configure:2521: checking for gettext in libc" >&5
 if eval "test \"`echo '$''{'gt_cv_func_gettext_libc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2505 "configure"
+#line 2526 "configure"
 #include "confdefs.h"
 #include <libintl.h>
 int main() {
 return (int) gettext ("")
 ; return 0; }
 EOF
-if { (eval echo configure:2512: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2533: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   gt_cv_func_gettext_libc=yes
 else
@@ -2524,7 +2545,7 @@
 
 	   if test "$gt_cv_func_gettext_libc" != "yes"; then
 	     echo $ac_n "checking for bindtextdomain in -lintl""... $ac_c" 1>&6
-echo "configure:2528: checking for bindtextdomain in -lintl" >&5
+echo "configure:2549: checking for bindtextdomain in -lintl" >&5
 ac_lib_var=`echo intl'_'bindtextdomain | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -2532,7 +2553,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lintl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 2536 "configure"
+#line 2557 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -2543,7 +2564,7 @@
 bindtextdomain()
 ; return 0; }
 EOF
-if { (eval echo configure:2547: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2568: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -2559,12 +2580,12 @@
 if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
   echo "$ac_t""yes" 1>&6
   echo $ac_n "checking for gettext in libintl""... $ac_c" 1>&6
-echo "configure:2563: checking for gettext in libintl" >&5
+echo "configure:2584: checking for gettext in libintl" >&5
 if eval "test \"`echo '$''{'gt_cv_func_gettext_libintl'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   echo $ac_n "checking for gettext in -lintl""... $ac_c" 1>&6
-echo "configure:2568: checking for gettext in -lintl" >&5
+echo "configure:2589: checking for gettext in -lintl" >&5
 ac_lib_var=`echo intl'_'gettext | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -2572,7 +2593,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lintl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 2576 "configure"
+#line 2597 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -2583,7 +2604,7 @@
 gettext()
 ; return 0; }
 EOF
-if { (eval echo configure:2587: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2608: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -2622,7 +2643,7 @@
 	      # Extract the first word of "msgfmt", so it can be a program name with args.
 set dummy msgfmt; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2626: checking for $ac_word" >&5
+echo "configure:2647: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -2656,12 +2677,12 @@
 		for ac_func in dcgettext
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2660: checking for $ac_func" >&5
+echo "configure:2681: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2665 "configure"
+#line 2686 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2684,7 +2705,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:2688: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2709: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -2711,7 +2732,7 @@
 		# Extract the first word of "gmsgfmt", so it can be a program name with args.
 set dummy gmsgfmt; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2715: checking for $ac_word" >&5
+echo "configure:2736: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -2747,7 +2768,7 @@
 		# Extract the first word of "xgettext", so it can be a program name with args.
 set dummy xgettext; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2751: checking for $ac_word" >&5
+echo "configure:2772: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -2779,7 +2800,7 @@
 fi
 
 		cat > conftest.$ac_ext <<EOF
-#line 2783 "configure"
+#line 2804 "configure"
 #include "confdefs.h"
 
 int main() {
@@ -2787,7 +2808,7 @@
 			       return _nl_msg_cat_cntr
 ; return 0; }
 EOF
-if { (eval echo configure:2791: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2812: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   CATOBJEXT=.gmo
 		   DATADIRNAME=share
@@ -2810,7 +2831,7 @@
 
         if test "$CATOBJEXT" = "NONE"; then
 	  echo $ac_n "checking whether catgets can be used""... $ac_c" 1>&6
-echo "configure:2814: checking whether catgets can be used" >&5
+echo "configure:2835: checking whether catgets can be used" >&5
 	  # Check whether --with-catgets or --without-catgets was given.
 if test "${with_catgets+set}" = set; then
   withval="$with_catgets"
@@ -2823,7 +2844,7 @@
 
 	  if test "$nls_cv_use_catgets" = "yes"; then
 	    	    echo $ac_n "checking for main in -li""... $ac_c" 1>&6
-echo "configure:2827: checking for main in -li" >&5
+echo "configure:2848: checking for main in -li" >&5
 ac_lib_var=`echo i'_'main | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -2831,14 +2852,14 @@
   ac_save_LIBS="$LIBS"
 LIBS="-li  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 2835 "configure"
+#line 2856 "configure"
 #include "confdefs.h"
 
 int main() {
 main()
 ; return 0; }
 EOF
-if { (eval echo configure:2842: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2863: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -2866,12 +2887,12 @@
 fi
 
 	    echo $ac_n "checking for catgets""... $ac_c" 1>&6
-echo "configure:2870: checking for catgets" >&5
+echo "configure:2891: checking for catgets" >&5
 if eval "test \"`echo '$''{'ac_cv_func_catgets'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2875 "configure"
+#line 2896 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char catgets(); below.  */
@@ -2894,7 +2915,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:2898: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2919: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_catgets=yes"
 else
@@ -2916,7 +2937,7 @@
 	       # Extract the first word of "gencat", so it can be a program name with args.
 set dummy gencat; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2920: checking for $ac_word" >&5
+echo "configure:2941: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_GENCAT'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -2952,7 +2973,7 @@
 		 # Extract the first word of "gmsgfmt", so it can be a program name with args.
 set dummy gmsgfmt; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2956: checking for $ac_word" >&5
+echo "configure:2977: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -2989,7 +3010,7 @@
 		   # Extract the first word of "msgfmt", so it can be a program name with args.
 set dummy msgfmt; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2993: checking for $ac_word" >&5
+echo "configure:3014: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3024,7 +3045,7 @@
 		 # Extract the first word of "xgettext", so it can be a program name with args.
 set dummy xgettext; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3028: checking for $ac_word" >&5
+echo "configure:3049: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3082,7 +3103,7 @@
         # Extract the first word of "msgfmt", so it can be a program name with args.
 set dummy msgfmt; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3086: checking for $ac_word" >&5
+echo "configure:3107: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3116,7 +3137,7 @@
         # Extract the first word of "gmsgfmt", so it can be a program name with args.
 set dummy gmsgfmt; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3120: checking for $ac_word" >&5
+echo "configure:3141: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3152,7 +3173,7 @@
         # Extract the first word of "xgettext", so it can be a program name with args.
 set dummy xgettext; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3156: checking for $ac_word" >&5
+echo "configure:3177: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3245,7 +3266,7 @@
        LINGUAS=
      else
        echo $ac_n "checking for catalogs to be installed""... $ac_c" 1>&6
-echo "configure:3249: checking for catalogs to be installed" >&5
+echo "configure:3270: checking for catalogs to be installed" >&5
        NEW_LINGUAS=
        for lang in ${LINGUAS=$ALL_LINGUAS}; do
          case "$ALL_LINGUAS" in
@@ -3273,17 +3294,17 @@
    if test "$CATOBJEXT" = ".cat"; then
      ac_safe=`echo "linux/version.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for linux/version.h""... $ac_c" 1>&6
-echo "configure:3277: checking for linux/version.h" >&5
+echo "configure:3298: checking for linux/version.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3282 "configure"
+#line 3303 "configure"
 #include "confdefs.h"
 #include <linux/version.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3287: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3308: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -3349,7 +3370,7 @@
   
 
 echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:3353: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "configure:3374: checking whether ${MAKE-make} sets \${MAKE}" >&5
 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -3378,7 +3399,7 @@
 # Extract the first word of "ln", so it can be a program name with args.
 set dummy ln; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3382: checking for $ac_word" >&5
+echo "configure:3403: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_LN'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3412,7 +3433,7 @@
 fi
 
 echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
-echo "configure:3416: checking whether ln -s works" >&5
+echo "configure:3437: checking whether ln -s works" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3435,7 +3456,7 @@
 # Extract the first word of "mv", so it can be a program name with args.
 set dummy mv; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3439: checking for $ac_word" >&5
+echo "configure:3460: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_MV'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3471,7 +3492,7 @@
 # Extract the first word of "cp", so it can be a program name with args.
 set dummy cp; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3475: checking for $ac_word" >&5
+echo "configure:3496: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_CP'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3507,7 +3528,7 @@
 # Extract the first word of "rm", so it can be a program name with args.
 set dummy rm; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3511: checking for $ac_word" >&5
+echo "configure:3532: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_RM'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3543,7 +3564,7 @@
 # Extract the first word of "chmod", so it can be a program name with args.
 set dummy chmod; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3547: checking for $ac_word" >&5
+echo "configure:3568: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_CHMOD'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3579,7 +3600,7 @@
 # Extract the first word of "awk", so it can be a program name with args.
 set dummy awk; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3583: checking for $ac_word" >&5
+echo "configure:3604: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_AWK'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3615,7 +3636,7 @@
 # Extract the first word of "sed", so it can be a program name with args.
 set dummy sed; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3619: checking for $ac_word" >&5
+echo "configure:3640: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_SED'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3651,7 +3672,7 @@
 # Extract the first word of "perl", so it can be a program name with args.
 set dummy perl; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3655: checking for $ac_word" >&5
+echo "configure:3676: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3687,7 +3708,7 @@
 # Extract the first word of "ldconfig", so it can be a program name with args.
 set dummy ldconfig; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3691: checking for $ac_word" >&5
+echo "configure:3712: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_LDCONFIG'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3721,7 +3742,7 @@
 fi
 
 echo $ac_n "checking build system type""... $ac_c" 1>&6
-echo "configure:3725: checking build system type" >&5
+echo "configure:3746: checking build system type" >&5
 
 build_alias=$build
 case "$build_alias" in
@@ -3747,7 +3768,7 @@
 # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
 set dummy ${ac_tool_prefix}ar; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3751: checking for $ac_word" >&5
+echo "configure:3772: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3779,7 +3800,7 @@
   # Extract the first word of "ar", so it can be a program name with args.
 set dummy ar; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3783: checking for $ac_word" >&5
+echo "configure:3804: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3814,7 +3835,7 @@
 # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
 set dummy ${ac_tool_prefix}ranlib; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3818: checking for $ac_word" >&5
+echo "configure:3839: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3846,7 +3867,7 @@
   # Extract the first word of "ranlib", so it can be a program name with args.
 set dummy ranlib; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3850: checking for $ac_word" >&5
+echo "configure:3871: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3881,7 +3902,7 @@
 # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
 set dummy ${ac_tool_prefix}strip; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3885: checking for $ac_word" >&5
+echo "configure:3906: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3913,7 +3934,7 @@
   # Extract the first word of "strip", so it can be a program name with args.
 set dummy strip; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3917: checking for $ac_word" >&5
+echo "configure:3938: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3957,7 +3978,7 @@
 # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
 # ./install, which can be erroneously created by make from ./install.sh.
 echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:3961: checking for a BSD compatible install" >&5
+echo "configure:3982: checking for a BSD compatible install" >&5
 if test -z "$INSTALL"; then
 if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -4019,7 +4040,7 @@
 # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:4023: checking for $ac_word" >&5
+echo "configure:4044: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_BUILD_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -4053,17 +4074,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:4057: checking for $ac_hdr" >&5
+echo "configure:4078: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4062 "configure"
+#line 4083 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4067: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4088: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -4090,12 +4111,12 @@
 done
 
 echo $ac_n "checking for vprintf""... $ac_c" 1>&6
-echo "configure:4094: checking for vprintf" >&5
+echo "configure:4115: checking for vprintf" >&5
 if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4099 "configure"
+#line 4120 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char vprintf(); below.  */
@@ -4118,7 +4139,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:4122: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4143: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_vprintf=yes"
 else
@@ -4142,12 +4163,12 @@
 
 if test "$ac_cv_func_vprintf" != yes; then
 echo $ac_n "checking for _doprnt""... $ac_c" 1>&6
-echo "configure:4146: checking for _doprnt" >&5
+echo "configure:4167: checking for _doprnt" >&5
 if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4151 "configure"
+#line 4172 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char _doprnt(); below.  */
@@ -4170,7 +4191,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:4174: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4195: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func__doprnt=yes"
 else
@@ -4195,12 +4216,12 @@
 fi
 
 echo $ac_n "checking whether struct dirent has a d_namlen field""... $ac_c" 1>&6
-echo "configure:4199: checking whether struct dirent has a d_namlen field" >&5
+echo "configure:4220: checking whether struct dirent has a d_namlen field" >&5
 if eval "test \"`echo '$''{'e2fsprogs_cv_struct_d_namlen'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4204 "configure"
+#line 4225 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <dirent.h>
@@ -4208,7 +4229,7 @@
 struct dirent de; de.d_namlen = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:4212: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4233: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   e2fsprogs_cv_struct_d_namlen=yes
 else
@@ -4228,19 +4249,19 @@
 
 fi
 echo $ac_n "checking whether llseek declared in unistd.h""... $ac_c" 1>&6
-echo "configure:4232: checking whether llseek declared in unistd.h" >&5
+echo "configure:4253: checking whether llseek declared in unistd.h" >&5
 if eval "test \"`echo '$''{'e2fsprogs_cv_have_llseek_prototype'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4237 "configure"
+#line 4258 "configure"
 #include "confdefs.h"
 #include <unistd.h>
 int main() {
 extern int llseek(int);
 ; return 0; }
 EOF
-if { (eval echo configure:4244: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4265: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   e2fsprogs_cv_have_llseek_prototype=no
 else
@@ -4260,12 +4281,12 @@
 
 fi
 echo $ac_n "checking whether lseek64 declared in unistd.h""... $ac_c" 1>&6
-echo "configure:4264: checking whether lseek64 declared in unistd.h" >&5
+echo "configure:4285: checking whether lseek64 declared in unistd.h" >&5
 if eval "test \"`echo '$''{'e2fsprogs_cv_have_lseek64_prototype'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4269 "configure"
+#line 4290 "configure"
 #include "confdefs.h"
 #define _LARGEFILE_SOURCE
 #define _LARGEFILE64_SOURCE
@@ -4274,7 +4295,7 @@
 extern int lseek64(int);
 ; return 0; }
 EOF
-if { (eval echo configure:4278: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4299: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   e2fsprogs_cv_have_lseek64_prototype=no
 else
@@ -4302,7 +4323,7 @@
   echo "configure: warning: Cross-compiling, so cannot check type sizes; assuming short=2, int=4, long=4, long long=8" 1>&2
 fi
 echo $ac_n "checking size of short""... $ac_c" 1>&6
-echo "configure:4306: checking size of short" >&5
+echo "configure:4327: checking size of short" >&5
 if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -4310,7 +4331,7 @@
     { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
 else
   cat > conftest.$ac_ext <<EOF
-#line 4314 "configure"
+#line 4335 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 #include <sys/types.h>
@@ -4322,7 +4343,7 @@
   exit(0);
 }
 EOF
-if { (eval echo configure:4326: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:4347: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_sizeof_short=`cat conftestval`
 else
@@ -4342,7 +4363,7 @@
 
 
 echo $ac_n "checking size of int""... $ac_c" 1>&6
-echo "configure:4346: checking size of int" >&5
+echo "configure:4367: checking size of int" >&5
 if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -4350,7 +4371,7 @@
     { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
 else
   cat > conftest.$ac_ext <<EOF
-#line 4354 "configure"
+#line 4375 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 #include <sys/types.h>
@@ -4362,7 +4383,7 @@
   exit(0);
 }
 EOF
-if { (eval echo configure:4366: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:4387: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_sizeof_int=`cat conftestval`
 else
@@ -4382,7 +4403,7 @@
 
 
 echo $ac_n "checking size of long""... $ac_c" 1>&6
-echo "configure:4386: checking size of long" >&5
+echo "configure:4407: checking size of long" >&5
 if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -4390,7 +4411,7 @@
     { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
 else
   cat > conftest.$ac_ext <<EOF
-#line 4394 "configure"
+#line 4415 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 #include <sys/types.h>
@@ -4402,7 +4423,7 @@
   exit(0);
 }
 EOF
-if { (eval echo configure:4406: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:4427: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_sizeof_long=`cat conftestval`
 else
@@ -4422,7 +4443,7 @@
 
 
 echo $ac_n "checking size of long long""... $ac_c" 1>&6
-echo "configure:4426: checking size of long long" >&5
+echo "configure:4447: checking size of long long" >&5
 if eval "test \"`echo '$''{'ac_cv_sizeof_long_long'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -4430,7 +4451,7 @@
     { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
 else
   cat > conftest.$ac_ext <<EOF
-#line 4434 "configure"
+#line 4455 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 #include <sys/types.h>
@@ -4442,7 +4463,7 @@
   exit(0);
 }
 EOF
-if { (eval echo configure:4446: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:4467: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_sizeof_long_long=`cat conftestval`
 else
@@ -4470,14 +4491,14 @@
 
 
 echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
-echo "configure:4474: checking whether byte ordering is bigendian" >&5
+echo "configure:4495: checking whether byte ordering is bigendian" >&5
 if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_cv_c_bigendian=unknown
 # See if sys/param.h defines the BYTE_ORDER macro.
 cat > conftest.$ac_ext <<EOF
-#line 4481 "configure"
+#line 4502 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/param.h>
@@ -4488,11 +4509,11 @@
 #endif
 ; return 0; }
 EOF
-if { (eval echo configure:4492: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4513: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   # It does; now see whether it defined to BIG_ENDIAN or not.
 cat > conftest.$ac_ext <<EOF
-#line 4496 "configure"
+#line 4517 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/param.h>
@@ -4503,7 +4524,7 @@
 #endif
 ; return 0; }
 EOF
-if { (eval echo configure:4507: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4528: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_bigendian=yes
 else
@@ -4523,7 +4544,7 @@
     { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
 else
   cat > conftest.$ac_ext <<EOF
-#line 4527 "configure"
+#line 4548 "configure"
 #include "confdefs.h"
 main () {
   /* Are we little or big endian?  From Harbison&Steele.  */
@@ -4536,7 +4557,7 @@
   exit (u.c[sizeof (long) - 1] == 1);
 }
 EOF
-if { (eval echo configure:4540: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:4561: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_c_bigendian=no
 else
@@ -4560,19 +4581,19 @@
 fi
 
 echo $ac_n "checking whether struct stat has a st_flags field""... $ac_c" 1>&6
-echo "configure:4564: checking whether struct stat has a st_flags field" >&5
+echo "configure:4585: checking whether struct stat has a st_flags field" >&5
 if eval "test \"`echo '$''{'e2fsprogs_cv_struct_st_flags'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4569 "configure"
+#line 4590 "configure"
 #include "confdefs.h"
 #include <sys/stat.h>
 int main() {
 struct stat stat; stat.st_flags = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:4576: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4597: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   e2fsprogs_cv_struct_st_flags=yes
 else
@@ -4587,19 +4608,19 @@
 echo "$ac_t""$e2fsprogs_cv_struct_st_flags" 1>&6
 if test "$e2fsprogs_cv_struct_st_flags" = yes; then
   echo $ac_n "checking whether st_flags field is useful""... $ac_c" 1>&6
-echo "configure:4591: checking whether st_flags field is useful" >&5
+echo "configure:4612: checking whether st_flags field is useful" >&5
   if eval "test \"`echo '$''{'e2fsprogs_cv_struct_st_flags_immut'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4596 "configure"
+#line 4617 "configure"
 #include "confdefs.h"
 #include <sys/stat.h>
 int main() {
 struct stat stat; stat.st_flags |= UF_IMMUTABLE;
 ; return 0; }
 EOF
-if { (eval echo configure:4603: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4624: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   e2fsprogs_cv_struct_st_flags_immut=yes
 else
@@ -4622,12 +4643,12 @@
 for ac_func in chflags getrusage llseek lseek64 open64 getmntinfo strcasecmp srandom fchown mallinfo fdatasync strnlen sysconf
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:4626: checking for $ac_func" >&5
+echo "configure:4647: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4631 "configure"
+#line 4652 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -4650,7 +4671,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:4654: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4675: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -4676,7 +4697,7 @@
 
 SOCKET_LIB=''
 echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6
-echo "configure:4680: checking for socket in -lsocket" >&5
+echo "configure:4701: checking for socket in -lsocket" >&5
 ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -4684,7 +4705,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lsocket  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 4688 "configure"
+#line 4709 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -4695,7 +4716,7 @@
 socket()
 ; return 0; }
 EOF
-if { (eval echo configure:4699: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4720: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -4717,12 +4738,12 @@
 
 
 echo $ac_n "checking for optreset""... $ac_c" 1>&6
-echo "configure:4721: checking for optreset" >&5
+echo "configure:4742: checking for optreset" >&5
 if eval "test \"`echo '$''{'ac_cv_have_optreset'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4726 "configure"
+#line 4747 "configure"
 #include "confdefs.h"
 #include <unistd.h>
 EOF
@@ -4794,20 +4815,20 @@
 
 
 echo $ac_n "checking whether linker accepts -static""... $ac_c" 1>&6
-echo "configure:4798: checking whether linker accepts -static" >&5
+echo "configure:4819: checking whether linker accepts -static" >&5
 if eval "test \"`echo '$''{'ac_cv_e2fsprogs_use_static'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   SAVE_LDFLAGS=$LDFLAGS; LDFLAGS="$LDFLAGS -static"
 cat > conftest.$ac_ext <<EOF
-#line 4804 "configure"
+#line 4825 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 int main() {
 fflush(stdout);
 ; return 0; }
 EOF
-if { (eval echo configure:4811: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4832: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_e2fsprogs_use_static=yes
 else
@@ -4964,6 +4985,7 @@
 
 trap 'rm -fr `echo "MCONFIG Makefile util/Makefile util/subst.conf lib/et/Makefile 
 	lib/ss/Makefile lib/ext2fs/Makefile lib/e2p/Makefile lib/uuid/Makefile
+	lib/evms/Makefile
 	misc/Makefile ext2ed/Makefile e2fsck/Makefile debugfs/Makefile \
 	tests/Makefile tests/progs/Makefile $rmakefile doc/Makefile 
 	intl/Makefile po/Makefile.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
@@ -5143,6 +5165,7 @@
 
 CONFIG_FILES=\${CONFIG_FILES-"MCONFIG Makefile util/Makefile util/subst.conf lib/et/Makefile 
 	lib/ss/Makefile lib/ext2fs/Makefile lib/e2p/Makefile lib/uuid/Makefile
+	lib/evms/Makefile
 	misc/Makefile ext2ed/Makefile e2fsck/Makefile debugfs/Makefile \
 	tests/Makefile tests/progs/Makefile $rmakefile doc/Makefile 
 	intl/Makefile po/Makefile.in"}
diff --git a/configure.in b/configure.in
index 04f9248..cc8d585 100644
--- a/configure.in
+++ b/configure.in
@@ -125,6 +125,21 @@
 echo "Disabling compression support by default"
 )
 dnl
+dnl handle --enable-old-evms
+dnl
+AC_ARG_ENABLE([old-evms],
+[  --enable-old-evms	  use EVMS 1.0 ABI (instead of EVMS 1.1)],
+if test "$enableval" = "no"
+then
+	echo "Using EVMS 1.1.0 ABI"
+else
+	AC_DEFINE(ABI_EVMS_1_0)
+	echo "Enabling EVMS 1.0.0 ABI"
+fi
+,
+echo "Using EVMS 1.1.0 ABI by default"
+)
+dnl
 dnl handle --enable-dll-shlibs
 dnl
 AC_ARG_ENABLE([dll-shlibs],
@@ -672,6 +687,7 @@
 fi
 AC_OUTPUT(MCONFIG Makefile util/Makefile util/subst.conf lib/et/Makefile 
 	lib/ss/Makefile lib/ext2fs/Makefile lib/e2p/Makefile lib/uuid/Makefile
+	lib/evms/Makefile
 	misc/Makefile ext2ed/Makefile e2fsck/Makefile debugfs/Makefile \
 	tests/Makefile tests/progs/Makefile $rmakefile doc/Makefile 
 	intl/Makefile po/Makefile.in)
diff --git a/lib/evms/Makefile.in b/lib/evms/Makefile.in
new file mode 100644
index 0000000..5ea517f
--- /dev/null
+++ b/lib/evms/Makefile.in
@@ -0,0 +1,53 @@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+top_builddir = ../..
+my_dir = lib/evms
+INSTALL = @INSTALL@
+
+XTRA_CFLAGS= -I@srcdir@
+
+@MCONFIG@
+
+OBJS= fs_ext2.o fsimext2.o
+
+SRCS= $(srcdir)/fs_ext2.c $(srcdir)/fsimext2.c
+
+
+LIBRARY= libext2fsim
+LIBDIR= evms
+
+ELF_VERSION = 1.0.0
+ELF_SO_VERSION = 1
+ELF_IMAGE = libe2fsim
+ELF_MYDIR = evms
+ELF_INSTALL_DIR = $(root_libdir)
+#ELF_OTHER_LIBS = -L../.. -lcom_err
+
+@MAKEFILE_LIBRARY@
+@MAKEFILE_ELF@
+
+.c.o:
+	$(CC) $(ALL_CFLAGS) -c $< -o $@
+@ELF_CMT@	$(CC) $(ALL_CFLAGS) -fPIC -o elfshared/$*.o -c $<
+
+clean::
+	$(RM) -f \#* *.s *.o *.a *~ *.bak core profiled/* checker/* 
+
+mostlyclean:: clean
+distclean:: clean
+	$(RM) -f .depend Makefile $(srcdir)/TAGS $(srcdir)/Makefile.in.old
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+fs_ext2.o: $(srcdir)/fs_ext2.c $(srcdir)/plugin.h $(srcdir)/dlist.h \
+ $(srcdir)/common.h $(srcdir)/evms_user.h $(srcdir)/evms_common.h \
+ $(srcdir)/evms_ioctl.h $(srcdir)/options.h $(srcdir)/enginestructs.h \
+ $(srcdir)/plugfuncs.h $(srcdir)/fsimext2.h
+fsimext2.o: $(srcdir)/fsimext2.c $(srcdir)/plugin.h $(srcdir)/dlist.h \
+ $(srcdir)/common.h $(srcdir)/evms_user.h $(srcdir)/evms_common.h \
+ $(srcdir)/evms_ioctl.h $(srcdir)/options.h $(srcdir)/enginestructs.h \
+ $(srcdir)/plugfuncs.h $(srcdir)/fsimext2.h
diff --git a/lib/evms/common.h b/lib/evms/common.h
new file mode 100644
index 0000000..bf3af43
--- /dev/null
+++ b/lib/evms/common.h
@@ -0,0 +1,287 @@
+/*
+ *
+ *   Copyright (c) International Business Machines  Corp., 2001
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Module: common.h
+ */
+
+#ifndef EVMS_COMMON_H_INCLUDED
+#define EVMS_COMMON_H_INCLUDED 1
+
+#include <linux/types.h>  /* will pull in platform specific data type info from linux/include/asm */
+
+/* Need these to satisfy dependencies in evms_user.h
+ * on systems running a 2.5.8 or newer kernel.
+ */
+typedef __u8	u8;
+typedef __u16	u16;
+typedef __u32	u32;
+typedef __u64	u64;
+
+#include <evms/evms_user.h>
+
+/* Defines for storage object names */
+#define EVMS_NAME_SIZE          EVMS_VOLUME_NAME_SIZE
+
+/* Defines for the flags in the storage_object_t structure */
+#define SOFLAG_DIRTY                (1<<0)
+#define SOFLAG_NEW                  (1<<1)
+#define SOFLAG_READ_ONLY            (1<<2)
+#define SOFLAG_FEATURE_HEADER_DIRTY (1<<3)
+#define SOFLAG_MUST_BE_TOP          (1<<4)
+#define SOFLAG_IO_ERROR             (1<<5)
+#define SOFLAG_CORRUPT              (1<<6)
+#define SOFLAG_BIOS_READABLE        (1<<7)
+#define SOFLAG_MUST_BE_VOLUME       (1<<8)
+#define SOFLAG_NOT_CLAIMED          (1<<9)
+
+/* Defines for flags in the storage_container_t structure */
+#define SCFLAG_DIRTY                (1<<0)
+#define SCFLAG_NEW                  (1<<1)
+
+/* Defines for the flags in the logical_volume_t structure */
+#define VOLFLAG_DIRTY               (1<<0)
+#define VOLFLAG_NEW                 (1<<1)
+#define VOLFLAG_READ_ONLY           (1<<2)
+#define VOLFLAG_NEEDS_DEV_NODE      (1<<3)
+#define VOLFLAG_COMPATIBILITY       (1<<4)
+#define VOLFLAG_FOREIGN             (1<<5)
+#define VOLFLAG_MKFS                (1<<6)
+#define VOLFLAG_UNMKFS              (1<<7)
+#define VOLFLAG_FSCK                (1<<8)
+#define VOLFLAG_DEFRAG              (1<<9)
+#define VOLFLAG_EXPAND_FS           (1<<10)
+#define VOLFLAG_SHRINK_FS           (1<<11)
+#define VOLFLAG_SYNC_FS             (1<<12)
+
+/* A BOOLEAN variable is one which is either TRUE or FALSE. */
+#ifndef BOOLEAN_DEFINED
+  #define BOOLEAN_DEFINED 1
+  typedef u_int8_t  BOOLEAN;
+#endif
+
+#ifndef TRUE
+  #define TRUE  1
+#endif
+#ifndef FALSE
+  #define FALSE 0
+#endif
+
+/*
+ * Logical Sector Number:  This is a physical sector address on a
+ * system drive.
+ */
+typedef u_int64_t       lsn_t;
+
+/*
+ * Logical Block Address:  This is a sector address on a volume which
+ * will be translated to a Logical Sector Number.
+ */
+typedef u_int64_t       lba_t;
+
+/*
+ * A sector_count_t is a count of sectors.  It is mainly used to hold the size
+ * of a disk, segment, region, etc.
+ */
+typedef u_int64_t       sector_count_t;
+
+/*
+ * A module_handle_t variable is one which holds a handle (or descriptor)
+ * referencing a loaded module.
+ */
+typedef void          * module_handle_t;
+
+/*
+ * The standard data type for Engine handles.
+ */
+typedef u_int32_t       engine_handle_t;
+
+/*
+ * An object_handle_t holds a handle for an EVMS Engine object.
+ */
+typedef engine_handle_t object_handle_t;
+
+/*
+ * A plugin_handle_t holds a handle for an EVMS Engine plug-in.
+ */
+typedef engine_handle_t plugin_handle_t;
+
+/*
+ * A plugin_ID_t holds a unique ID for a plug-in.
+ */
+typedef u_int32_t       plugin_id_t;
+
+/*
+ * A plugin_type_t holds the type field of a plug-in's ID.
+ */
+typedef u_int8_t        plugin_type_t;
+
+/*
+ * The various modes in which the Engine can be.
+ */
+typedef enum {
+    ENGINE_CLOSED = 0,
+    ENGINE_READONLY,
+    ENGINE_READWRITE
+} engine_mode_t;
+
+/*
+ * The geometry of a disk, segment, region, etc.
+ */
+typedef struct geometry_s {
+    u_int64_t   cylinders;
+    u_int32_t   heads;
+    u_int32_t   sectors_per_track;
+    u_int32_t   bytes_per_sector;
+    u_int64_t   boot_cylinder_limit;
+    u_int64_t   block_size;
+} geometry_t;
+
+/*
+ * The data types which a storage object can be.
+ */
+typedef enum {
+    META_DATA_TYPE  = (1<<0),
+    DATA_TYPE       = (1<<1),
+    FREE_SPACE_TYPE = (1<<2)
+} data_type_t;
+
+/*
+ * The types of structures the Engine exports
+ */
+typedef enum {
+    PLUGIN      = (1<<0),
+    DISK        = (1<<1),
+    SEGMENT     = (1<<2),
+    REGION      = (1<<3),
+    EVMS_OBJECT = (1<<4),
+    CONTAINER   = (1<<5),
+    VOLUME      = (1<<6)
+} object_type_t;
+
+/*
+ * Flags that can be used for filtering plug-ins on the evms_get_plugin_list API
+ */
+typedef enum {
+    SUPPORTS_CONTAINERS = (1<<0)
+} plugin_search_flags_t;
+
+/*
+ * Flags that can be used for filtering objects on the evms_get_object_list API
+ */
+typedef enum {
+    TOPMOST =           (1<<0),
+    NOT_MUST_BE_TOP =   (1<<1),
+    WRITEABLE =         (1<<2)
+} object_search_flags_t;
+
+#define VALID_INPUT_OBJECT      (TOPMOST | NOT_MUST_BE_TOP | WRITEABLE)
+
+/*
+ * Debug levels
+ * These levels should be kept in sync with the debug levels defined for the
+ * EVMS kernel in linux/evms/evms.h.
+ */
+typedef enum {
+    /*
+     * Use CRITICAL for messages that indicate that the health of the
+     * system/Engine is in jeopardy.  Something _really_ bad happened,
+     * such as failure to allocate memory or control structures are
+     * corrupted.
+     */
+    CRITICAL = 0,
+
+    /*
+     * Use SERIOUS for messages that something bad has happened, but not
+     * as bad a CRITICAL.
+     */
+    SERIOUS = 1,
+
+    /*
+     * Use ERROR for messages that indicate the user caused an error,
+     * such as passing a bad parameter.  The message should help the
+     * user correct the problem.
+     */
+    ERROR = 2,
+
+    /*
+     * Use WARNING for messages that indicate that something is not quite
+     * right and the user should know about it.  You may or may not be able
+     * to work around the problem.
+     */
+    WARNING = 3,
+
+    /*
+     * Use DEFAULT for informational messages that do not indicate problems, or
+     * that a problem occurred but there was a work-around.  DEFAULT messages
+     * should be things that the user would usually want to know during any run
+     * of the Engine, such as how many volumes were discovered on the system,
+     * and not necessarily what a developer would want to know (use DETAILS or
+     * DEBUG for that).  Since DEFAULT is the default debug level, be careful
+     * not to put DEFAULT messages in loops or frequently executed code as they
+     * will bloat the log file.
+     */
+    DEFAULT = 5,
+
+    /*
+     * Use DETAILS to provide more detailed information about the system.  The
+     * message may provide additional information about the progress of the
+     * system.  It may contain more information about a DEFAULT message or more
+     * information about an error condition.
+     */
+    DETAILS = 6,
+
+    /*
+     * Use DEBUG for messages that would help debug a problem, such as tracing
+     * code paths or dumping the contents of variables.
+     */
+    DEBUG = 7,
+
+    /*
+     * Use EXTRA to provided more information than your standard debug messages
+     * provide.
+     */
+
+    EXTRA = 8,
+
+    /*
+     * Use ENTRY_EXIT to trace entries and exits from functions.
+     */
+    ENTRY_EXIT = 9,
+
+    /*
+     * Use EVERYTHING for all manner of verbose output.  Feel free to bloat the
+     * log file with any messages that would help you debug a problem.
+     */
+    EVERYTHING = 10
+
+} debug_level_t;
+
+
+/*
+ * Handy macros for finding the min and max of two numbers.
+ */
+#ifndef min
+    #define min(a,b) (((a)<(b))?(a):(b))
+#endif
+#ifndef max
+    #define max(a,b) (((a)>(b))?(a):(b))
+#endif
+
+
+#endif
+
diff --git a/lib/evms/dlist.h b/lib/evms/dlist.h
new file mode 100644
index 0000000..fd20a72
--- /dev/null
+++ b/lib/evms/dlist.h
@@ -0,0 +1,2357 @@
+/*
+ *
+ *   Copyright (c) International Business Machines  Corp., 2000
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Module: dlist.h
+ *
+ * Functions: dlist_t     CreateList
+ *            int         InsertItem
+ *            int         InsertObject
+ *            int         DeleteItem
+ *            int         DeleteAllItems
+ *            int         GetItem
+ *            int         GetNextItem
+ *            int         GetPreviousItem
+ *            int         GetObject
+ *            int         BlindGetObject
+ *            int         GetNextObject
+ *            int         GetPreviousObject
+ *            int         ExtractItem
+ *            int         ExtractObject
+ *            int         BlindExtractObject
+ *            int         ReplaceItem
+ *            int         ReplaceObject
+ *            int         GetTag
+ *            int         GetHandle
+ *            int         GetListSize
+ *            BOOLEAN     ListEmpty
+ *            BOOLEAN     AtEndOfList
+ *            BOOLEAN     AtStartOfList
+ *            int         DestroyList
+ *            int         NextItem
+ *            int         PreviousItem
+ *            int         GoToStartOfList
+ *            int         GoToEndOfList
+ *            int         GoToSpecifiedItem
+ *            int         SortList
+ *            int         ForEachItem
+ *            int         PruneList
+ *            int         AppendList
+ *            int         TransferItem
+ *            int         CopyList
+ *            BOOLEAN     CheckListIntegrity
+ *
+ * Description:  This module implements a simple, generic, doubly linked list.
+ *               Data objects of any type can be placed into a linked list
+ *               created by this module.  Furthermore, data objects of different
+ *               types may be placed into the same linked list.
+ *
+ * Notes:  This linked list implementation makes use of the concept of the
+ *         current item.  In any non-empty list, one item in the list will
+ *         be designated as the current item.  When any of the following
+ *         functions are called, they will operate upon the current item
+ *         only: GetItem, ReplaceItem, DeleteItem, GetTag, NextItem,
+ *         PreviousItem, GetObject, ExtractItem, and ExtractObject.  The
+ *         user of this module may set the current item through the use of
+ *         the GoToStartOfList, GoToEndOfList, NextItem, PreviousItem,
+ *         and GoToSpecifiedItem functions.
+ *
+ *         Since a linked list created by this module may contain items
+ *         of different types, the user will need a way to identify items
+ *         of different types which may be in the same list.  To allow users
+ *         to do this, the concept of an item tag is used.  When an item is
+ *         added to the list, the user must enter an item tag.  The item
+ *         tag is merely some identifier that the user wishes to associate
+ *         with the item being placed into the list.  When used as intended,
+ *         each type of data item will have a unique tag associated with it.
+ *         This way, all data items of the same type will have the same tag
+ *         while data items of different types will have different tags.
+ *         Thus, by using the GetTag function, the user can get the item
+ *         tag for the current item without having to get the item from the
+ *         list.  This allows the user to differentiate between items of
+ *         different types which reside in the same list.
+ *
+ *         This module is single threaded.  If used in a multi-threaded
+ *         environment, the user must implement appropriate access controls.
+ *
+ *         When an item is inserted or appended to a list, this module
+ *         allocates memory on the heap to hold the item and then copies
+ *         the item to the memory that it allocated.  This allows local
+ *         variables to be safely inserted or appended to a list.  However,
+ *         it should be noted that under certain circumstances a copy of the
+ *         entire data item will NOT be made.  Specifically, if the data item
+ *         is a structure or array containing pointers, then the data pointed
+ *         to by the pointers will NOT be copied even though the structure or
+ *         array is!  This results from the fact that, when an item is being
+ *         inserted or appended to a list, the user provides just an address
+ *         and size.  This module assumes that the item to inserted or append
+ *         lies in a contiguous block of memory at the address provided by the
+ *         user.  This module has no way of knowing the structure of the data
+ *         at the specified address, and therefore can not know about any
+ *         embedded pointers which may lie within that block of memory.
+ *
+ *         This module now employs the concept of a handle.  A handle is a
+ *         reference to a specific item in a list which allows that item to
+ *         be made the current item in the list quickly.  Example:  If you
+ *         use the GetHandle function to get a handle for the current item
+ *         (lets call the item B1), then, regardless of where you are in the
+ *         list (or any reodering of the items in the list), you can make item
+ *         B1 the current item by passing its handle to the GoToSpecifiedItem
+ *         function.  Alternatively, you could operate directly on B1 using
+ *         the other handle based functions, such as GetItem_By_Handle, for
+ *         example.  GetItem_By_Handle gets the item associated with the
+ *         specified handle without changing which item in the list is the
+ *         current item in the list.
+ *
+ *         The functions of this module refer to user data as either items or
+ *         objects.  The difference between the two is simple, yet subtle.  It
+ *         deals with who is responsible for the memory used to hold the data.
+ *         In the case of an item, this module is responsible for the memory
+ *         used to hold the user data.  In the case of an object, the user
+ *         is responsible for the memory used to hold the data.
+ *
+ *         What this means is that, for functions adding ITEMS to a list,
+ *         this module will be responsible for allocating memory to hold
+ *         the user data and then copying the user data into the memory
+ *         that was allocated.  For functions which return items, this
+ *         module will COPY the user data from the LIST into a buffer
+ *         specified by the user.  For functions which add objects to a
+ *         list, the user provides a pointer to a block of memory holding
+ *         user data.  This block of memory was allocated by the user, and
+ *         becomes the "property" of this module once it has been added to
+ *         a LIST.  For functions which return objects, a pointer to the
+ *         memory where the data is stored is returned.  As long as an item/object
+ *         is in a LIST, this module will be responsible for the memory that
+ *         is used to store the data associated with that item.  This means that
+ *         users of this module should not call free on an object returned by this
+ *         module as long as that object is still within a list.
+ *
+ *
+ */
+
+#ifndef DLISTHANDLER
+
+#define DLISTHANDLER  1
+
+#include <linux/types.h>  /* will pull in platform specific data type info from linux/include/asm */
+#include <errno.h>
+
+#ifndef BOOLEAN_DEFINED
+  #define BOOLEAN_DEFINED 1
+  typedef u_int8_t      BOOLEAN;
+#endif
+
+typedef void *          ADDRESS;
+typedef ulong           TAG;
+
+struct LinkNodeRecord
+{
+  ADDRESS                   DataLocation;        /* Where the data associated with this LinkNode is */
+  uint                      DataSize;            /* The size of the data associated with this LinkNode. */
+  TAG                       DataTag;             /* The item tag the user gave to the data. */
+  struct MasterListRecord * ControlNodeLocation; /* The control node of the list containing this item. */
+  struct LinkNodeRecord *   NextLinkNode;        /* The LinkNode of the next item in the list. */
+  struct LinkNodeRecord *   PreviousLinkNode;    /* The LinkNode of the item preceding this one in the list. */
+};
+
+typedef struct LinkNodeRecord LinkNode;
+
+struct MasterListRecord
+{
+  uint            ItemCount;             /* The number of items in the list. */
+  LinkNode *      StartOfList;           /* The address of the LinkNode of the first item in the list. */
+  LinkNode *      EndOfList;             /* The address of the LinkNode of the last item in the list. */
+  LinkNode *      CurrentItem;           /* The address of the LinkNode of the current item in the list. */
+#ifdef USE_POOLMAN
+  POOL            NodePool;              /* The pool of LinkNodes for this dlist_t. */
+#endif
+  uint            Verify;                /* A field to contain the VerifyValue which marks this as a list created by this module. */
+};
+
+typedef struct MasterListRecord ControlNode;
+
+
+typedef ControlNode *   dlist_t;
+
+
+#ifndef TRUE
+  #define TRUE 1
+#endif
+#ifndef FALSE
+  #define FALSE 0
+#endif
+
+
+typedef enum _Insertion_Modes {
+                                InsertAtStart,
+                                InsertBefore,
+                                InsertAfter,
+                                AppendToList,
+                              } Insertion_Modes;
+
+/* Update the IS_DLIST_ERROR() macro below if you add, remove, or change */
+/* error codes.                                                          */
+
+#define DLIST_SUCCESS                    0
+#define DLIST_OUT_OF_MEMORY              ENOMEM
+
+#define DLIST_CORRUPTED                  201
+#define DLIST_BAD                        202
+#define DLIST_NOT_INITIALIZED            203
+#define DLIST_EMPTY                      204
+#define DLIST_ITEM_SIZE_WRONG            205
+#define DLIST_BAD_ITEM_POINTER           206
+#define DLIST_ITEM_SIZE_ZERO             207
+#define DLIST_ITEM_TAG_WRONG             208
+#define DLIST_END_OF_LIST                209
+#define DLIST_ALREADY_AT_START           210
+#define DLIST_BAD_HANDLE                 211
+#define DLIST_INVALID_INSERTION_MODE     212
+#define DLIST_OBJECT_NOT_FOUND           213
+#define DLIST_OBJECT_ALREADY_IN_LIST     214
+
+/* Macro to determine if an error code is a dlist error code. */
+
+#define IS_DLIST_ERROR(rc) ((abs(rc) >= DLIST_CORRUPTED) && (abs(rc) <= DLIST_OBJECT_ALREADY_IN_LIST))
+
+/* The following code is special.  It is for use with the PruneList and ForEachItem functions.  Basically, these functions
+   can be thought of as "searching" a list.  They present each item in the list to a user supplied function which can then
+   operate on the items.  If the user supplied function returns a non-zero error code, ForEachItem and PruneList abort and
+   return an error to the caller.  This may be undesirable.  If the user supplied function used with PruneList and ForEachItem
+   returns the code below, PruneList/ForEachItem will abort and return DLIST_SUCCESS.  This allows PruneList and ForEachItem
+   to be used to search a list and terminate the search when the desired item is found without having to traverse the
+   remaining items in the list.                                                                                                  */
+
+#define DLIST_SEARCH_COMPLETE  0xFF
+
+#ifdef USE_POOLMAN
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  CreateList                                      */
+/*                                                                   */
+/*   Descriptive Name: This function allocates and initializes the   */
+/*                     data structures associated with a list and    */
+/*                     then returns a pointer to these structures.   */
+/*                                                                   */
+/*   Input: uint       InitialPoolSize - Each List gets a pool of    */
+/*                                     link nodes.  When items are   */
+/*                                     added to the List, a link node*/
+/*                                     is removed from the pool.     */
+/*                                     When an item is removed from  */
+/*                                     the List, the link node used  */
+/*                                     for that item is returned to  */
+/*                                     the pool.  InitialPoolSize is */
+/*                                     the number of link nodes to   */
+/*                                     place in the pool when the    */
+/*                                     pool is created.              */
+/*          uint       MaximumPoolSize - When the pool runs out of   */
+/*                                     link nodes, new nodes are     */
+/*                                     allocated by the pool.  When  */
+/*                                     these links start being       */
+/*                                     returned to the pool, the pool*/
+/*                                     will grow.  This parameter    */
+/*                                     puts a limit on how big the   */
+/*                                     pool may grow to.  Once the   */
+/*                                     pool reaches this size, any   */
+/*                                     link nodes being returned to  */
+/*                                     the pool will be deallocated. */
+/*          uint       PoolIncrement - When the pool runs out of link*/
+/*                                   nodes and more are required,    */
+/*                                   the pool will allocate one or   */
+/*                                   more link nodes.  This tells the*/
+/*                                   pool how many link nodes to     */
+/*                                   allocate at one time.           */
+/*                                                                   */
+/*   Output: If Success : The function return value will be non-NULL */
+/*                                                                   */
+/*           If Failure : The function return value will be NULL.    */
+/*                                                                   */
+/*   Error Handling:  The function will only fail if it can not      */
+/*                    allocate enough memory to create the new list  */
+/*                    and its associated pool of link nodes.         */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  None.                                                   */
+/*                                                                   */
+/*********************************************************************/
+dlist_t CreateList(uint InitialPoolSize,
+                 uint MaximumPoolSize,
+                 uint PoolIncrement);
+
+#else
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  CreateList                                      */
+/*                                                                   */
+/*   Descriptive Name: This function allocates and initializes the   */
+/*                     data structures associated with a list and    */
+/*                     then returns a pointer to these structures.   */
+/*                                                                   */
+/*   Input: None.                                                    */
+/*                                                                   */
+/*   Output: If Success : The function return value will be non-NULL */
+/*                                                                   */
+/*           If Failure : The function return value will be NULL.    */
+/*                                                                   */
+/*   Error Handling:  The function will only fail if it can not      */
+/*                    allocate enough memory to create the new list. */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  None.                                                   */
+/*                                                                   */
+/*********************************************************************/
+dlist_t       CreateList( void );
+
+#endif
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name: InsertItem                                       */
+/*                                                                   */
+/*   Descriptive Name:  This function inserts an item into a dlist_t.*/
+/*                      The item can be placed either before or      */
+/*                      after the current item in the dlist_t.       */
+/*                                                                   */
+/*   Input:  dlist_t        ListToAddTo : The list to which the      */
+/*                                        data item is to be         */
+/*                                        added.                     */
+/*           uint          ItemSize : The size of the data item, in  */
+/*                                    bytes.                         */
+/*           ADDRESS       ItemLocation : The address of the data    */
+/*                                        to append to the list      */
+/*           TAG           ItemTag : The item tag to associate with  */
+/*                                   item being appended to the list */
+/*           ADDRESS TargetHandle : The item in ListToAddTo which    */
+/*                                   is used to determine where      */
+/*                                   the item being transferred will */
+/*                                   be placed.  If this is NULL,    */
+/*                                   then the current item in        */
+/*                                   ListToAddTo will be used.       */
+/*           Insertion_Modes InsertMode : This indicates where,      */
+/*                                   relative to the item in         */
+/*                                   ListToAddTo specified by        */
+/*                                   Target_Handle, the item being   */
+/*                                   inserted can be placed.         */
+/*           BOOLEAN MakeCurrent : If TRUE, the item being inserted  */
+/*                                 into ListToAddTo becomes the      */
+/*                                 current item in ListToAddTo.      */
+/*           ADDRESS    * Handle : The address of a variable to hold */
+/*                                 the handle for the item that was  */
+/*                                 inserted into the list.           */
+/*                                                                   */
+/*   Output:  If all went well, the return value will be             */
+/*            DLIST_SUCCESS and *Handle will contain the ADDRESS of  */
+/*            the new item.  If errors were encountered, the   .     */
+/*            return value will be the error code and *Handle will   */
+/*            be NULL.                                               */
+/*                                                                   */
+/*   Error Handling: This function will fail under the following     */
+/*                   conditions:                                     */
+/*                       ListToAddTo does not point to a valid       */
+/*                           list                                    */
+/*                       ItemSize is 0                               */
+/*                       ItemLocation is NULL                        */
+/*                       The memory required to hold a copy of the   */
+/*                           item can not be allocated.              */
+/*                       The memory required to create a LINK NODE   */
+/*                           can not be allocated.                   */
+/*                       TargetHandle is invalid or is for an item   */
+/*                           in another list.                        */
+/*                   If this routine fails, an error code is returned*/
+/*                   and any memory allocated by this function is    */
+/*                   freed.                                          */
+/*                                                                   */
+/*   Side Effects: None.                                             */
+/*                                                                   */
+/*   Notes:  The item to add is copied to the heap to                */
+/*           avoid possible conflicts with the usage of              */
+/*           local variables in functions which process              */
+/*           dlist_ts.  However, a pointer to a local variable       */
+/*           should not be appended to the dlist_t.                  */
+/*                                                                   */
+/*           It is assumed that TargetHandle is valid, or is at least*/
+/*           the address of an accessible block of storage.  If      */
+/*           TargetHandle is invalid, or is not the address of an    */
+/*           accessible block of storage, then a trap or exception   */
+/*           may occur.                                              */
+/*                                                                   */
+/*           It is assumed that if ItemLocation is not NULL, then    */
+/*           it is a valid address that can be dereferenced.  If     */
+/*           this assumption is violated, an exception or trap may   */
+/*           occur.                                                  */
+/*                                                                   */
+/*********************************************************************/
+int InsertItem (dlist_t           ListToAddTo,
+                uint              ItemSize,
+                ADDRESS           ItemLocation,
+                TAG               ItemTag,
+                ADDRESS           TargetHandle,
+                Insertion_Modes   Insert_Mode,
+                BOOLEAN           MakeCurrent,
+                ADDRESS         * Handle);
+
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name: InsertObject                                     */
+/*                                                                   */
+/*   Descriptive Name:  This function inserts an object into a       */
+/*                      dlist_t.  The object can be inserted before  */
+/*                      or after the current item in the list.       */
+/*                                                                   */
+/*   Input:  dlist_t        ListToAddTo : The list to which the      */
+/*                                        data object is to be       */
+/*                                        inserted.                  */
+/*           uint          ItemSize : The size of the data item, in  */
+/*                                    bytes.                         */
+/*           ADDRESS       ItemLocation : The address of the data    */
+/*                                        to append to the list      */
+/*           TAG           ItemTag : The item tag to associate with  */
+/*                                   the item being appended to the  */
+/*                                   list                            */
+/*           ADDRESS TargetHandle : The item in ListToAddTo which    */
+/*                                   is used to determine where      */
+/*                                   the item being transferred will */
+/*                                   be placed.  If this is NULL,    */
+/*                                   then the current item in        */
+/*                                   ListToAddTo will be used.       */
+/*           Insertion_Modes Insert_Mode : This indicates where,     */
+/*                                   relative to the item in         */
+/*                                   ListToAddTo specified by        */
+/*                                   Target_Handle, the item being   */
+/*                                   inserted can be placed.         */
+/*           BOOLEAN MakeCurrent : If TRUE, the item being inserted  */
+/*                                 into ListToAddTo becomes the      */
+/*                                 current item in ListToAddTo.      */
+/*           ADDRESS    * Handle : The address of a variable to hold */
+/*                                 the handle for the item that was  */
+/*                                 inserted into the list.           */
+/*                                                                   */
+/*   Output:  If all went well, the return value will be             */
+/*            DLIST_SUCCESS and *Handle will contain the ADDRESS of  */
+/*            the new item.  If errors were encountered, the   .     */
+/*            return value will be the error code and *Handle will   */
+/*            be NULL.                                               */
+/*                                                                   */
+/*   Error Handling: This function will fail under the following     */
+/*                   conditions:                                     */
+/*                       ListToAddTo does not point to a valid       */
+/*                           list                                    */
+/*                       ItemSize is 0                               */
+/*                       ItemLocation is NULL                        */
+/*                       The memory required for a LINK NODE can not */
+/*                           be allocated.                           */
+/*                       TargetHandle is invalid or is for an item   */
+/*                           in another list.                        */
+/*                   If this routine fails, an error code is returned*/
+/*                   and any memory allocated by this function is    */
+/*                   freed.                                          */
+/*                                                                   */
+/*   Side Effects: None.                                             */
+/*                                                                   */
+/*   Notes:  The item to insert is NOT copied to the heap.  Instead, */
+/*           the location of the item is stored in the list.  This   */
+/*           is the major difference between InsertObject and        */
+/*           InsertItem.  InsertItem allocates memory on the heap,   */
+/*           copies the item to the memory it allocated, and stores  */
+/*           the address of the memory it allocated in the list.     */
+/*           InsertObject stores the address provided by the user.   */
+/*                                                                   */
+/*           It is assumed that TargetHandle is valid, or is at least*/
+/*           the address of an accessible block of storage.  If      */
+/*           TargetHandle is invalid, or is not the address of an    */
+/*           accessible block of storage, then a trap or exception   */
+/*           may occur.                                              */
+/*                                                                   */
+/*           It is assumed that if ItemLocation is not NULL, then    */
+/*           it is a valid address that can be dereferenced.  If     */
+/*           this assumption is violated, an exception or trap may   */
+/*           occur.                                                  */
+/*                                                                   */
+/*********************************************************************/
+int InsertObject (dlist_t           ListToAddTo,
+                  uint              ItemSize,
+                  ADDRESS           ItemLocation,
+                  TAG               ItemTag,
+                  ADDRESS           TargetHandle,
+                  Insertion_Modes   Insert_Mode,
+                  BOOLEAN           MakeCurrent,
+                  ADDRESS         * Handle);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name: ExclusiveInsertObject                            */
+/*                                                                   */
+/*   Descriptive Name:  This function inserts an object into a       */
+/*                      dlist_t.  The object can be inserted before  */
+/*                      or after the current item in the list. If    */
+/*                      object is already in the list, it is not     */
+/*                      added again.                                 */
+/*                                                                   */
+/*   Input:  dlist_t        ListToAddTo : The list to which the      */
+/*                                        data object is to be       */
+/*                                        inserted.                  */
+/*           uint          ItemSize : The size of the data item, in  */
+/*                                    bytes.                         */
+/*           ADDRESS       ItemLocation : The address of the data    */
+/*                                        to append to the list      */
+/*           TAG           ItemTag : The item tag to associate with  */
+/*                                   the item being appended to the  */
+/*                                   list                            */
+/*           ADDRESS TargetHandle : The item in ListToAddTo which    */
+/*                                   is used to determine where      */
+/*                                   the item being transferred will */
+/*                                   be placed.  If this is NULL,    */
+/*                                   then the current item in        */
+/*                                   ListToAddTo will be used.       */
+/*           Insertion_Modes Insert_Mode : This indicates where,     */
+/*                                   relative to the item in         */
+/*                                   ListToAddTo specified by        */
+/*                                   Target_Handle, the item being   */
+/*                                   inserted can be placed.         */
+/*           BOOLEAN MakeCurrent : If TRUE, the item being inserted  */
+/*                                 into ListToAddTo becomes the      */
+/*                                 current item in ListToAddTo.      */
+/*           ADDRESS    * Handle : The address of a variable to hold */
+/*                                 the handle for the item that was  */
+/*                                 inserted into the list.           */
+/*                                                                   */
+/*   Output:  If all went well, the return value will be             */
+/*            DLIST_SUCCESS and *Handle will contain the ADDRESS of  */
+/*            the new item.  If errors were encountered, the   .     */
+/*            return value will be the error code and *Handle will   */
+/*            be NULL.                                               */
+/*                                                                   */
+/*   Error Handling: This function will fail under the following     */
+/*                   conditions:                                     */
+/*                       ListToAddTo does not point to a valid       */
+/*                           list                                    */
+/*                       ItemSize is 0                               */
+/*                       ItemLocation is NULL                        */
+/*                       The memory required for a LINK NODE can not */
+/*                           be allocated.                           */
+/*                       TargetHandle is invalid or is for an item   */
+/*                           in another list.                        */
+/*                   If this routine fails, an error code is returned*/
+/*                   and any memory allocated by this function is    */
+/*                   freed.                                          */
+/*                                                                   */
+/*   Side Effects: None.                                             */
+/*                                                                   */
+/*   Notes:  The item to insert is NOT copied to the heap.  Instead, */
+/*           the location of the item is stored in the list.  This   */
+/*           is the major difference between InsertObject and        */
+/*           InsertItem.  InsertItem allocates memory on the heap,   */
+/*           copies the item to the memory it allocated, and stores  */
+/*           the address of the memory it allocated in the list.     */
+/*           InsertObject stores the address provided by the user.   */
+/*                                                                   */
+/*           It is assumed that TargetHandle is valid, or is at least*/
+/*           the address of an accessible block of storage.  If      */
+/*           TargetHandle is invalid, or is not the address of an    */
+/*           accessible block of storage, then a trap or exception   */
+/*           may occur.                                              */
+/*                                                                   */
+/*           It is assumed that if ItemLocation is not NULL, then    */
+/*           it is a valid address that can be dereferenced.  If     */
+/*           this assumption is violated, an exception or trap may   */
+/*           occur.                                                  */
+/*                                                                   */
+/*********************************************************************/
+int ExclusiveInsertObject (dlist_t           ListToAddTo,
+                           uint              ItemSize,
+                           ADDRESS           ItemLocation,
+                           TAG               ItemTag,
+                           ADDRESS           TargetHandle,
+                           Insertion_Modes   Insert_Mode,
+                           BOOLEAN           MakeCurrent,
+                           ADDRESS         * Handle);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  DeleteItem                                      */
+/*                                                                   */
+/*   Descriptive Name:  This function removes the specified item from*/
+/*                      the list and optionally frees the memory     */
+/*                      associated with it.                          */
+/*                                                                   */
+/*   Input:  dlist_t     ListToDeleteFrom : The list whose current   */
+/*                                         item is to be deleted.    */
+/*           BOOLEAN    FreeMemory : If TRUE, then the memory        */
+/*                                   associated with the current     */
+/*                                   item will be freed.  If FALSE   */
+/*                                   then the current item will be   */
+/*                                   removed from the list but its   */
+/*                                   memory will not be freed.       */
+/*           ADDRESS Handle : The handle of the item to get.  This   */
+/*                            handle must be of an item which resides*/
+/*                            in ListToDeleteFrom, or NULL.  If      */
+/*                            NULL is used, then the current item    */
+/*                            in ListToDeleteFrom will be deleted.   */
+/*                                                                   */
+/*   Output:  Return DLIST_SUCCESS if successful, else an error code.*/
+/*                                                                   */
+/*   Error Handling: This function will fail if ListToDeleteFrom is  */
+/*                   not a valid list, or if ListToDeleteFrom is     */
+/*                   empty, or if Handle is invalid.                 */
+/*                   If this routine fails, an error code is         */
+/*                   returned.                                       */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  Items in a list can be accessed in two ways:  A copy of */
+/*           the item can be obtained using GetItem and its related  */
+/*           calls, or a pointer to the item can be obtained using   */
+/*           GetObject and its related calls.  If you have a copy of */
+/*           the data and wish to remove the item from the list, set */
+/*           FreeMemory to TRUE.  This will remove the item from the */
+/*           list and deallocate the memory used to hold it.  If you */
+/*           have a pointer to the item in the list (from one of the */
+/*           GetObject style functions) and wish to remove the item  */
+/*           from the list, set FreeMemory to FALSE.  This removes   */
+/*           the item from the list without freeing its memory, so   */
+/*           that the pointer obtained with the GetObject style      */
+/*           functions is still useable.                             */
+/*                                                                   */
+/*           It is assumed that Handle is valid, or is at least the  */
+/*           address of an accessible block of storage.  If Handle   */
+/*           is invalid, or is not the address of an accessible block*/
+/*           of storage, then a trap or exception may occur.         */
+/*                                                                   */
+/*           This function does not alter which item is the current  */
+/*           item in the list, unless the handle specified belongs   */
+/*           to the current item in the list, in which case this     */
+/*           function behaves the same as DeleteItem.                */
+/*                                                                   */
+/*********************************************************************/
+int DeleteItem (dlist_t ListToDeleteFrom,
+                BOOLEAN FreeMemory,
+                ADDRESS Handle);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  DeleteAllItems                                  */
+/*                                                                   */
+/*   Descriptive Name:  This function deletes all of the items in the*/
+/*                      specified list and optionally frees the      */
+/*                      memory associated with each item deleted.    */
+/*                                                                   */
+/*   Input:  dlist_t     ListToDeleteFrom : The list whose items     */
+/*                                          are to be deleted.       */
+/*           BOOLEAN    FreeMemory : If TRUE, then the memory        */
+/*                                   associated with each item in the*/
+/*                                   list will be freed.  If FALSE   */
+/*                                   then the each item will be      */
+/*                                   removed from the list but its   */
+/*                                   memory will not be freed.       */
+/*                                                                   */
+/*   Output:  Return DLIST_SUCCESS if successful, else an error code.*/
+/*                                                                   */
+/*   Error Handling: This function will fail if ListToDeleteFrom is  */
+/*                   not a valid list, or if ListToDeleteFrom is     */
+/*                   empty.                                          */
+/*                   If this routine fails, an error code is         */
+/*                   returned.                                       */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  Items in a list can be accessed in two ways:  A copy of */
+/*           the item can be obtained using GetItem and its related  */
+/*           calls, or a pointer to the item can be obtained using   */
+/*           GetObject and its related calls.  If you have a copy of */
+/*           the data and wish to remove the item from the list, set */
+/*           FreeMemory to TRUE.  This will remove the item from the */
+/*           list and deallocate the memory used to hold it.  If you */
+/*           have a pointer to the item in the list (from one of the */
+/*           GetObject style functions) and wish to remove the item  */
+/*           from the list, set FreeMemory to FALSE.  This removes   */
+/*           the item from the list without freeing its memory, so   */
+/*           that the pointer obtained with the GetObject style      */
+/*           functions is still useable.                             */
+/*                                                                   */
+/*********************************************************************/
+int DeleteAllItems (dlist_t ListToDeleteFrom,
+                    BOOLEAN FreeMemory);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  DeleteObject                                    */
+/*                                                                   */
+/*   Descriptive Name:  This function removes the specified object   */
+/*                      from the list.                               */
+/*                                                                   */
+/*   Input:  dlist_t     ListToDeleteFrom : The list whose current   */
+/*                                          item is to be deleted.   */
+/*           ADDRESS Object : The address of the object to be removed*/
+/*                            from the list.                         */
+/*                                                                   */
+/*   Output:  Return DLIST_SUCCESS if successful, else an error code.*/
+/*                                                                   */
+/*   Error Handling: This function will fail if ListToDeleteFrom is  */
+/*                   not a valid list, or if ListToDeleteFrom is     */
+/*                   empty, or if Handle is invalid.                 */
+/*                   If this routine fails, an error code is         */
+/*                   returned.                                       */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  This function does not alter which item is the current  */
+/*           item in the list, unless the handle specified belongs   */
+/*           to the current item in the list, in which case this     */
+/*           function behaves the same as DeleteItem.                */
+/*                                                                   */
+/*********************************************************************/
+int DeleteObject (dlist_t ListToDeleteFrom,
+                  ADDRESS Object);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  GetItem                                         */
+/*                                                                   */
+/*   Descriptive Name:  This function copies the specified item in   */
+/*                      the list to a buffer provided by the caller. */
+/*                                                                   */
+/*   Input:  dlist_t ListToGetItemFrom : The list whose current item */
+/*                                       is to be copied and returned*/
+/*                                       to the caller.              */
+/*           uint       ItemSize : What the caller thinks the size of*/
+/*                                 the current item is.              */
+/*           ADDRESS     ItemLocation : This is the location of the  */
+/*                                      buffer into which the current*/
+/*                                      item is to be copied.        */
+/*           TAG     ItemTag : What the caller thinks the item tag   */
+/*                             of the current item is.               */
+/*           ADDRESS Handle : The handle of the item to get.  This   */
+/*                            handle must be of an item which resides*/
+/*                            in ListToGetItemFrom, or NULL.  If     */
+/*                            NULL, then the current item in the list*/
+/*                            will be used.                          */
+/*           BOOLEAN MakeCurrent : If TRUE, the item to get will     */
+/*                                 become the current item in the    */
+/*                                 list.                             */
+/*                                                                   */
+/*   Output:  If Successful :                                        */
+/*                 Return DLIST_SUCCESS.                             */
+/*                 The buffer at ItemLocation will contain a copy of */
+/*                    the current item from ListToGetItemFrom.       */
+/*            If Failure :                                           */
+/*                 Return an error code.                             */
+/*                                                                   */
+/*                                                                   */
+/*   Error Handling: This function will fail under any of the        */
+/*                   following conditions:                           */
+/*                         ListToGetItemFrom is not a valid list     */
+/*                         ItemSize does not match the size of the   */
+/*                             current item in the list              */
+/*                         ItemLocation is NULL                      */
+/*                         ItemTag does not match the item tag       */
+/*                             of the current item in the list       */
+/*                         Handle is invalid, or is for an item      */
+/*                             which is not in ListToGetItemFrom     */
+/*                   If any of these conditions occur, an error code */
+/*                   will be returned.                               */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  It is assumed that if ItemLocation is not NULL, then    */
+/*           it is a valid address that can be dereferenced.  If     */
+/*           this assumption is violated, an exception or trap may   */
+/*           occur.                                                  */
+/*                                                                   */
+/*           It is assumed that Handle is valid, or is at least the  */
+/*           address of an accessible block of storage.  If Handle   */
+/*           is invalid, or is not the address of an accessible block*/
+/*           of storage, then a trap or exception may occur.         */
+/*           NOTE: For this function, NULL is considered a valid     */
+/*                 handle corresponding to the current item in the   */
+/*                 list.                                             */
+/*                                                                   */
+/*           This function does not alter which item is the current  */
+/*           item in the list.                                       */
+/*                                                                   */
+/*********************************************************************/
+int          GetItem( dlist_t        ListToGetItemFrom,
+                      uint           ItemSize,
+                      ADDRESS        ItemLocation,
+                      TAG            ItemTag,
+                      ADDRESS        Handle,
+                      BOOLEAN        MakeCurrent);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  GetNextItem                                     */
+/*                                                                   */
+/*   Descriptive Name:  This function advances the current item      */
+/*                      pointer and then copies the current item in  */
+/*                      the list to a buffer provided by the caller. */
+/*                                                                   */
+/*   Input:  dlist_t ListToGetItemFrom : The list whose current item */
+/*                                       is to be copied and returned*/
+/*                                       to the caller.              */
+/*           uint       ItemSize : What the caller thinks the size of*/
+/*                                 the current item is.              */
+/*           ADDRESS     ItemLocation : This is the location of the  */
+/*                                      buffer into which the current*/
+/*                                      item is to be copied.        */
+/*           TAG     ItemTag : What the caller thinks the item tag   */
+/*                             of the current item is.               */
+/*                                                                   */
+/*   Output:  If Successful :                                        */
+/*                 Return DLIST_SUCCESS.                             */
+/*                 The buffer at ItemLocation will contain a copy of */
+/*                    the current item from ListToGetItemFrom.       */
+/*            If Failure :                                           */
+/*                 Return an error code.                             */
+/*                 The current item pointer will NOT be advanced.    */
+/*                     The current item in the list will be the same */
+/*                     as before the call to this function.          */
+/*                                                                   */
+/*   Error Handling: This function will fail under any of the        */
+/*                   following conditions:                           */
+/*                         ListToGetItemFrom is not a valid list     */
+/*                         ItemSize does not match the size of the   */
+/*                             current item in the list              */
+/*                         ItemLocation is NULL                      */
+/*                         ItemTag does not match the item tag       */
+/*                             of the current item in the list       */
+/*                         The current item in the list before this  */
+/*                             function is called is the last item   */
+/*                             item in the list.                     */
+/*                   If any of these conditions occur, an error      */
+/*                   code will be returned.                          */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  It is assumed that if ItemLocation is not NULL, then    */
+/*           it is a valid address that can be dereferenced.  If     */
+/*           this assumption is violated, an exception or trap may   */
+/*           occur.                                                  */
+/*                                                                   */
+/*********************************************************************/
+int GetNextItem(dlist_t ListToGetItemFrom,
+                uint    ItemSize,
+                ADDRESS ItemLocation,
+                TAG     ItemTag);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  GetPreviousItem                                 */
+/*                                                                   */
+/*   Descriptive Name:  This function makes the previous item in the */
+/*                      list the current item in the list and then   */
+/*                      copies that item to a buffer provided by the */
+/*                      user.                                        */
+/*                                                                   */
+/*   Input:  dlist_t ListToGetItemFrom : The list whose current item */
+/*                                       is to be copied and returned*/
+/*                                       to the caller.              */
+/*           uint       ItemSize : What the caller thinks the size of*/
+/*                                 the current item is.              */
+/*           ADDRESS    ItemLocation : This is the location of the   */
+/*                                     buffer into which the current */
+/*                                     item is to be copied.         */
+/*           TAG     ItemTag : What the caller thinks the item tag   */
+/*                             of the current item is.               */
+/*                                                                   */
+/*   Output:  If Successful :                                        */
+/*                 Return DLIST_SUCCESS.                             */
+/*                 The buffer at ItemLocation will contain a copy of */
+/*                    the current item from ListToGetItemFrom.       */
+/*            If Failure :                                           */
+/*                 Return an error code.                             */
+/*                 The current item pointer will NOT be advanced.    */
+/*                     The current item in the list will be the same */
+/*                     as before the call to this function.          */
+/*                                                                   */
+/*   Error Handling: This function will fail under any of the        */
+/*                   following conditions:                           */
+/*                         ListToGetItemFrom is not a valid list     */
+/*                         ItemSize does not match the size of the   */
+/*                             current item in the list              */
+/*                         ItemLocation is NULL                      */
+/*                         ItemTag does not match the item tag       */
+/*                             of the current item in the list       */
+/*                         The current item in the list before this  */
+/*                             function is called is the last item   */
+/*                             item in the list.                     */
+/*                   If any of these conditions occur, an error      */
+/*                   code will be returned.                          */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  It is assumed that if ItemLocation is not NULL, then    */
+/*           it is a valid address that can be dereferenced.  If     */
+/*           this assumption is violated, an exception or trap may   */
+/*           occur.                                                  */
+/*                                                                   */
+/*********************************************************************/
+int GetPreviousItem(dlist_t ListToGetItemFrom,
+                    uint    ItemSize,
+                    ADDRESS ItemLocation,
+                    TAG     ItemTag);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  GetObject                                       */
+/*                                                                   */
+/*   Descriptive Name:  This function returns the address of the data*/
+/*                      associated with the specified item in the    */
+/*                      list.                                        */
+/*                                                                   */
+/*   Input:  dlist_t ListToGetItemFrom : The list whose current item */
+/*                                       is to have its address      */
+/*                                       returned to the caller.     */
+/*           uint       ItemSize : What the caller thinks the size of*/
+/*                               the current item is.                */
+/*           TAG     ItemTag : What the caller thinks the item tag   */
+/*                             of the current item is.               */
+/*           ADDRESS Handle : The handle of the item to get.  This   */
+/*                            handle must be of an item which resides*/
+/*                            in ListToGetItemFrom, or NULL.  If     */
+/*                            NULL, then the current item in the list*/
+/*           BOOLEAN MakeCurrent : If TRUE, the item to get will     */
+/*                                 become the current item in the    */
+/*                                 list.                             */
+/*           ADDRESS   * Object : The address of a variable to hold  */
+/*                                the ADDRESS of data associated     */
+/*                                with the current item.             */
+/*                                                                   */
+/*   Output:  If Successful :                                        */
+/*                 Return DLIST_SUCCESS.                             */
+/*                 *Object will be the address of the data           */
+/*                 associated with the current item in the list.     */
+/*            If Failure :                                           */
+/*                 Return an error code.                             */
+/*                 *Object will be NULL.                             */
+/*                                                                   */
+/*   Error Handling: This function will fail under any of the        */
+/*                   following conditions:                           */
+/*                         ListToGetItemFrom is not a valid list     */
+/*                         ItemSize does not match the size of the   */
+/*                             current item in the list              */
+/*                         ItemTag does not match the item tag       */
+/*                             of the current item in the list       */
+/*                         Handle is invalid, or is for an item      */
+/*                             which is not in ListToGetItemFrom     */
+/*                   If any of these conditions occur, an error code */
+/*                   will be returned.                               */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  The user should not free the memory associated with     */
+/*           the address returned by this function as the object is  */
+/*           still in the list.                                      */
+/*                                                                   */
+/*           It is assumed that Handle is valid, or is at least the  */
+/*           address of an accessible block of storage.  If Handle   */
+/*           is invalid, or is not the address of an accessible block*/
+/*           of storage, then a trap or exception may occur.         */
+/*           NOTE: For this function, NULL is considered a valid     */
+/*                 handle designating the current item in the list.  */
+/*                                                                   */
+/*           It is assumed that Object is a valid address.  If not,  */
+/*           an exception or trap may occur.                         */
+/*                                                                   */
+/*           This function does not alter which item is the current  */
+/*           item in the list.                                       */
+/*                                                                   */
+/*********************************************************************/
+int GetObject(dlist_t   ListToGetItemFrom,
+              uint      ItemSize,
+              TAG       ItemTag,
+              ADDRESS   Handle,
+              BOOLEAN   MakeCurrent,
+              ADDRESS * Object);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  BlindGetObject                                  */
+/*                                                                   */
+/*   Descriptive Name:  This function returns the address of the data*/
+/*                      associated with the specified item in the    */
+/*                      list.                                        */
+/*                                                                   */
+/*   Input:  dlist_t ListToGetItemFrom : The list whose current      */
+/*                                       item is to have its address */
+/*                                       returned to the caller.     */
+/*           uint *     ItemSize : The size of the current item      */
+/*           TAG *   ItemTag : The tag of the current item           */
+/*           ADDRESS Handle : The handle of the item to get.  This   */
+/*                            handle must be of an item which resides*/
+/*                            in ListToGetItemFrom, or NULL.  If     */
+/*                            NULL, then the current item in the list*/
+/*           BOOLEAN MakeCurrent : If TRUE, the item to get will     */
+/*                                 become the current item in the    */
+/*                                 list.                             */
+/*           ADDRESS   * Object : The address of a variable to hold  */
+/*                                the ADDRESS of data associated     */
+/*                                with the current item.             */
+/*                                                                   */
+/*   Output:  If Successful :                                        */
+/*                 Return DLIST_SUCCESS.                             */
+/*                 *Object will be the address of the data           */
+/*                 associated with the current item in the list.     */
+/*            If Failure :                                           */
+/*                 Return an error code.                             */
+/*                 *Object will be NULL.                             */
+/*                                                                   */
+/*   Error Handling: This function will fail under any of the        */
+/*                   following conditions:                           */
+/*                         ListToGetItemFrom is not a valid list     */
+/*                         ItemSize does not match the size of the   */
+/*                             current item in the list              */
+/*                         ItemTag does not match the item tag       */
+/*                             of the current item in the list       */
+/*                         Handle is invalid, or is for an item      */
+/*                             which is not in ListToGetItemFrom     */
+/*                   If any of these conditions occur, an error code */
+/*                   will be returned.                               */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  The user should not free the memory associated with     */
+/*           the address returned by this function as the object is  */
+/*           still in the list.                                      */
+/*                                                                   */
+/*           It is assumed that Handle is valid, or is at least the  */
+/*           address of an accessible block of storage.  If Handle   */
+/*           is invalid, or is not the address of an accessible block*/
+/*           of storage, then a trap or exception may occur.         */
+/*           NOTE: For this function, NULL is considered a valid     */
+/*                 handle designating the current item in the list.  */
+/*                                                                   */
+/*           It is assumed that Object is a valid address.  If not,  */
+/*           an exception or trap may occur.                         */
+/*                                                                   */
+/*           This function does not alter which item is the current  */
+/*           item in the list.                                       */
+/*                                                                   */
+/*********************************************************************/
+int BlindGetObject(dlist_t ListToGetItemFrom,
+                   uint    * ItemSize,
+                   TAG     * ItemTag,
+                   ADDRESS   Handle,
+                   BOOLEAN   MakeCurrent,
+                   ADDRESS * Object);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  GetNextObject                                   */
+/*                                                                   */
+/*   Descriptive Name:  This function advances the current item      */
+/*                      pointer and then returns the address of the  */
+/*                      data associated with the current item in the */
+/*                      list.                                        */
+/*                                                                   */
+/*   Input:  dlist_t ListToGetItemFrom : The list whose current item */
+/*                                       is to be copied and returned*/
+/*                                       to the caller.              */
+/*           uint       ItemSize : What the caller thinks the size of*/
+/*                               the current item is.                */
+/*           TAG     ItemTag : What the caller thinks the item tag   */
+/*                             of the current item is.               */
+/*           ADDRESS   * Object : The address of a variable to hold  */
+/*                                the ADDRESS of data associated     */
+/*                                with the next item.                */
+/*                                                                   */
+/*   Output:  If Successful :                                        */
+/*                 Return DLIST_SUCCESS.                             */
+/*                 *Object will be the address of the data           */
+/*                 associated with the current item in the list.     */
+/*            If Failure :                                           */
+/*                 Return an error code.                             */
+/*                 *Object will be NULL.                             */
+/*                 The current item pointer will NOT be advanced.    */
+/*                     The current item in the list will be the same */
+/*                     as before the call to this function.          */
+/*                                                                   */
+/*   Error Handling: This function will fail under any of the        */
+/*                   following conditions:                           */
+/*                         ListToGetItemFrom is not a valid list     */
+/*                         ItemSize does not match the size of the   */
+/*                             current item in the list              */
+/*                         ItemTag does not match the item tag       */
+/*                             of the current item in the list       */
+/*                         The current item in the list before this  */
+/*                             function is called is the last item   */
+/*                             item in the list.                     */
+/*                   If any of these conditions occur, an error code */
+/*                   will be returned.                               */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  The user should not free the memory associated with     */
+/*           the address returned by this function as the object is  */
+/*           still in the list.                                      */
+/*                                                                   */
+/*           It is assumed that Object is a valid address.  If not,  */
+/*           an exception or trap may occur.                         */
+/*                                                                   */
+/*********************************************************************/
+int GetNextObject(dlist_t   ListToGetItemFrom,
+                  uint      ItemSize,
+                  TAG       ItemTag,
+                  ADDRESS * Object);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  GetPreviousObject                               */
+/*                                                                   */
+/*   Descriptive Name:  This function makes the previous item in the */
+/*                      list the current item and then returns the   */
+/*                      address of the data associated with the      */
+/*                      current item in the list.                    */
+/*                                                                   */
+/*   Input:  dlist_t ListToGetItemFrom : The list whose current item */
+/*                                       is to be copied and returned*/
+/*                                       to the caller.              */
+/*           uint       ItemSize : What the caller thinks the size of*/
+/*                                 the current item is.              */
+/*           TAG     ItemTag : What the caller thinks the item tag   */
+/*                             of the current item is.               */
+/*           ADDRESS   * Object : The address of a variable to hold  */
+/*                                the ADDRESS of data associated     */
+/*                                with the previous item.            */
+/*                                                                   */
+/*   Output:  If Successful :                                        */
+/*                 Return DLIST_SUCCESS.                             */
+/*                 *Object will be the address of the data           */
+/*                 associated with the current item in the list.     */
+/*            If Failure :                                           */
+/*                 Return an error code.                             */
+/*                 *Object will be NULL.                             */
+/*                 The current item pointer will NOT be advanced.    */
+/*                     The current item in the list will be the same */
+/*                     as before the call to this function.          */
+/*                                                                   */
+/*   Error Handling: This function will fail under any of the        */
+/*                   following conditions:                           */
+/*                         ListToGetItemFrom is not a valid list     */
+/*                         ItemSize does not match the size of the   */
+/*                             current item in the list              */
+/*                         ItemTag does not match the item tag       */
+/*                             of the current item in the list       */
+/*                         The current item in the list before this  */
+/*                             function is called is the last item   */
+/*                             item in the list.                     */
+/*                   If any of these conditions occur, an error code */
+/*                   will be returned.                               */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  The user should not free the memory associated with     */
+/*           the address returned by this function as the object is  */
+/*           still in the list.                                      */
+/*                                                                   */
+/*           It is assumed that Object is a valid address.  If not,  */
+/*           an exception or trap may occur.                         */
+/*                                                                   */
+/*********************************************************************/
+int GetPreviousObject(dlist_t   ListToGetItemFrom,
+                      uint      ItemSize,
+                      TAG       ItemTag,
+                      ADDRESS * Object);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  ExtractItem                                     */
+/*                                                                   */
+/*   Descriptive Name:  This function copies the specified item in   */
+/*                      the list to a buffer provided by the caller  */
+/*                      and removes the item from the list.          */
+/*                                                                   */
+/*   Input:  dlist_t ListToGetItemFrom : The list whose current item */
+/*                                       is to be copied and returned*/
+/*                                       to the caller.              */
+/*           uint       ItemSize : What the caller thinks the size of*/
+/*                                 the current item is.              */
+/*           ADDRESS     ItemLocation : This is the location of the  */
+/*                                      buffer into which the current*/
+/*                                      item is to be copied.        */
+/*           TAG     ItemTag : What the caller thinks the item tag   */
+/*                             of the current item is.               */
+/*           ADDRESS Handle : The handle of the item to get.  This   */
+/*                            handle must be of an item which resides*/
+/*                            in ListToGetItemFrom, or NULL.  If     */
+/*                            NULL, then the current item in the list*/
+/*                            will be used.                          */
+/*                                                                   */
+/*   Output:  If Successful :                                        */
+/*                 Return DLIST_SUCCESS.                             */
+/*                 The buffer at ItemLocation will contain a copy of */
+/*                    the current item from ListToGetItemFrom.       */
+/*                 The item will have been removed from the list and */
+/*                    its memory deallocated.                        */
+/*            If Failure :                                           */
+/*                 Return an error code.                             */
+/*                                                                   */
+/*   Error Handling: This function will fail under any of the        */
+/*                   following conditions:                           */
+/*                         ListToGetItemFrom is not a valid list     */
+/*                         ItemSize does not match the size of the   */
+/*                             current item in the list              */
+/*                         ItemLocation is NULL                      */
+/*                         ItemTag does not match the item tag       */
+/*                             of the current item in the list       */
+/*                         Handle is invalid, or is for an item      */
+/*                             which is not in ListToGetItemFrom     */
+/*                   If any of these conditions occur, *Error will   */
+/*                   contain a non-zero error code.                  */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  It is assumed that if ItemLocation is not NULL, then    */
+/*           it is a valid address that can be dereferenced.  If     */
+/*           these assumptions are violated, an exception or trap    */
+/*           may occur.                                              */
+/*                                                                   */
+/*           It is assumed that Handle is valid, or is at least the  */
+/*           address of an accessible block of storage.  If Handle   */
+/*           is invalid, or is not the address of an accessible block*/
+/*           of storage, then a trap or exception may occur.         */
+/*           NOTE: For this function, NULL is considered a valid     */
+/*                 handle which refers to the current item in the    */
+/*                 list.                                             */
+/*                                                                   */
+/*           This function does not alter which item is the current  */
+/*           item in the list, unless the handle specified belongs   */
+/*           to the current item in the list, in which case the      */
+/*           item following the current item becomes the current     */
+/*           item in the list.  If there is no item following the    */
+/*           current item in the list, then the item preceding the   */
+/*           current item will become the current item in the list.  */
+/*                                                                   */
+/*********************************************************************/
+int ExtractItem(dlist_t ListToGetItemFrom,
+                uint    ItemSize,
+                ADDRESS ItemLocation,
+                TAG     ItemTag,
+                ADDRESS Handle);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  ExtractObject                                   */
+/*                                                                   */
+/*   Descriptive Name:  This function returns the address of the data*/
+/*                      associated with the specified item in the    */
+/*                      list and then removes that item from the list*/
+/*                                                                   */
+/*   Input:  dlist_t ListToGetItemFrom : The list whose current item */
+/*                                       is to be copied and returned*/
+/*                                       to the caller.              */
+/*           uint       ItemSize : What the caller thinks the size of*/
+/*                                 the current item is.              */
+/*           TAG     ItemTag : What the caller thinks the item tag   */
+/*                             of the current item is.               */
+/*           ADDRESS Handle : The handle of the item to get.  This   */
+/*                            handle must be of an item which resides*/
+/*                            in ListToGetItemFrom, or NULL.  If     */
+/*                            NULL, then the current item in the     */
+/*                            list will be used.                     */
+/*           ADDRESS   * Object : The address of a variable to hold  */
+/*                                the ADDRESS of data associated     */
+/*                                with the current item.             */
+/*                                                                   */
+/*   Output:  If Successful :                                        */
+/*                 Return DLIST_SUCCESS.                             */
+/*                 *Object will be the address of the data           */
+/*                 associated with the current item in the list.     */
+/*            If Failure :                                           */
+/*                 Return an error code.                             */
+/*                 *Object will be NULL.                             */
+/*                                                                   */
+/*   Error Handling: This function will fail under any of the        */
+/*                   following conditions:                           */
+/*                         ListToGetItemFrom is not a valid list     */
+/*                         ItemSize does not match the size of the   */
+/*                             current item in the list              */
+/*                         ItemTag does not match the item tag       */
+/*                             of the current item in the list       */
+/*                         Handle is invalid, or is for an item      */
+/*                             which is not in ListToGetItemFrom     */
+/*                   If any of these conditions occur, an error code */
+/*                   will be returned.                               */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  The user is responsible for the memory associated with  */
+/*           the address returned by this function since this        */
+/*           function removes that object from the list.  This means */
+/*           that, when the user is through with the object, they    */
+/*           should free it.                                         */
+/*                                                                   */
+/*           It is assumed that Handle is valid, or is at least the  */
+/*           address of an accessible block of storage.  If Handle   */
+/*           is invalid, or is not the address of an accessible block*/
+/*           of storage, then a trap or exception may occur.         */
+/*           NOTE: For this function, NULL is considered a valid     */
+/*                 handle which refers to the current item in the    */
+/*                 list.                                             */
+/*                                                                   */
+/*           It is assumed that Object is a valid address.  If not,  */
+/*           an exception or trap may occur.                         */
+/*                                                                   */
+/*           This function does not alter which item is the current  */
+/*           item in the list, unless the handle specified belongs   */
+/*           to the current item in the list, in which case the      */
+/*           item following the current item becomes the current     */
+/*           item in the list.  If there is no item following the    */
+/*           current item in the list, then the item preceding the   */
+/*           current item will become the current item in the list.  */
+/*                                                                   */
+/*********************************************************************/
+int ExtractObject(dlist_t   ListToGetItemFrom,
+                  uint      ItemSize,
+                  TAG       ItemTag,
+                  ADDRESS   Handle,
+                  ADDRESS * Object);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  BlindExtractObject                              */
+/*                                                                   */
+/*   Descriptive Name:  This function returns the address of the data*/
+/*                      associated with the specified item in the    */
+/*                      list and then removes that item from the list*/
+/*                                                                   */
+/*   Input:  dlist_t ListToGetItemFrom : The list whose current      */
+/*                                       item is to be copied and    */
+/*                                       returned to the caller.     */
+/*           uint *     ItemSize : The size of the current item      */
+/*           TAG *   ItemTag : The tag of the current item           */
+/*           ADDRESS Handle : The handle of the item to get.  This   */
+/*                            handle must be of an item which resides*/
+/*                            in ListToGetItemFrom, or NULL.  If     */
+/*                            NULL, then the current item in the     */
+/*                            list will be used.                     */
+/*           ADDRESS   * Object : The address of a variable to hold  */
+/*                                the ADDRESS of data associated     */
+/*                                with the current item.             */
+/*                                                                   */
+/*   Output:  If Successful :                                        */
+/*                 Return DLIST_SUCCESS.                             */
+/*                 *Object will be the address of the data           */
+/*                 associated with the current item in the list.     */
+/*            If Failure :                                           */
+/*                 Return an error code.                             */
+/*                 *Object will be NULL.                             */
+/*                                                                   */
+/*   Error Handling: This function will fail under any of the        */
+/*                   following conditions:                           */
+/*                         ListToGetItemFrom is not a valid list     */
+/*                         ItemSize does not match the size of the   */
+/*                             current item in the list              */
+/*                         ItemTag does not match the item tag       */
+/*                             of the current item in the list       */
+/*                         Handle is invalid, or is for an item      */
+/*                             which is not in ListToGetItemFrom     */
+/*                   If any of these conditions occur, an error code */
+/*                   will be returned.                               */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  The user is responsible for the memory associated with  */
+/*           the address returned by this function since this        */
+/*           function removes that object from the list.  This means */
+/*           that, when the user is through with the object, they    */
+/*           should free it.                                         */
+/*                                                                   */
+/*           It is assumed that Handle is valid, or is at least the  */
+/*           address of an accessible block of storage.  If Handle   */
+/*           is invalid, or is not the address of an accessible block*/
+/*           of storage, then a trap or exception may occur.         */
+/*           NOTE: For this function, NULL is considered a valid     */
+/*                 handle which refers to the current item in the    */
+/*                 list.                                             */
+/*                                                                   */
+/*           It is assumed that Object is a valid address.  If not,  */
+/*           an exception or trap may occur.                         */
+/*                                                                   */
+/*           This function does not alter which item is the current  */
+/*           item in the list, unless the handle specified belongs   */
+/*           to the current item in the list, in which case the      */
+/*           item following the current item becomes the current     */
+/*           item in the list.  If there is no item following the    */
+/*           current item in the list, then the item preceding the   */
+/*           current item will become the current item in the list.  */
+/*                                                                   */
+/*********************************************************************/
+int BlindExtractObject(dlist_t ListToGetItemFrom,
+                       uint    * ItemSize,
+                       TAG     * ItemTag,
+                       ADDRESS   Handle,
+                       ADDRESS * Object);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  ReplaceItem                                     */
+/*                                                                   */
+/*   Descriptive Name:  This function replaces the specified item in */
+/*                      the list with the one provided as its        */
+/*                      argument.                                    */
+/*                                                                   */
+/*   Input: dlist_t ListToReplaceItemIn : The list whose current item*/
+/*                                       is to be replaced           */
+/*          uint    ItemSize : The size, in bytes, of the            */
+/*                             replacement item                      */
+/*          ADDRESS ItemLocation : The address of the replacement    */
+/*                                 item                              */
+/*          TAG     ItemTag : The item tag that the user wishes to   */
+/*                            associate with the replacement item    */
+/*          ADDRESS Handle : The handle of the item to get.  This    */
+/*                           handle must be of an item which resides */
+/*                           in ListToGetItemFrom, or NULL.  If NULL */
+/*                           then the current item in the list will  */
+/*                           used.                                   */
+/*          BOOLEAN MakeCurrent : If TRUE, the item to get will      */
+/*                                become the current item in the     */
+/*                                list.                              */
+/*                                                                   */
+/*   Output:  If Successful then return DLIST_SUCCESS.               */
+/*            If Unsuccessful, then return an error code.            */
+/*                                                                   */
+/*   Error Handling:  This function will fail under the following    */
+/*                    conditions:                                    */
+/*                         ListToReplaceItemIn is empty              */
+/*                         ItemSize is 0                             */
+/*                         ItemLocation is NULL                      */
+/*                         The memory required can not be allocated. */
+/*                         Handle is invalid, or is for an item      */
+/*                             which is not in ListToGetItemFrom     */
+/*                    If any of these conditions occurs, an error    */
+/*                    code will be returned.                         */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  It is assumed that if ItemLocation is not NULL, then    */
+/*           it is a valid address that can be dereferenced.  If     */
+/*           these assumptions are violated, an exception or trap    */
+/*           may occur.                                              */
+/*                                                                   */
+/*           It is assumed that Handle is valid, or is at least the  */
+/*           address of an accessible block of storage.  If Handle   */
+/*           is invalid, or is not the address of an accessible block*/
+/*           of storage, then a trap or exception may occur.         */
+/*           NOTE: For this function, NULL is a valid handle which   */
+/*                 refers to the current item in the list.           */
+/*                                                                   */
+/*           This function does not alter which item is the current  */
+/*           item in the list.                                       */
+/*                                                                   */
+/*********************************************************************/
+int ReplaceItem(dlist_t ListToReplaceItemIn,
+                uint    ItemSize,
+                ADDRESS ItemLocation,
+                TAG     ItemTag,
+                ADDRESS Handle,
+                BOOLEAN MakeCurrent);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name: ReplaceObject                                    */
+/*                                                                   */
+/*   Descriptive Name:  This function replaces the specified object  */
+/*                      in the list with the one provided as its     */
+/*                      argument.                                    */
+/*                                                                   */
+/*   Input: dlist_t ListToReplaceItemIn : The list whose current     */
+/*                                       object is to be replaced    */
+/*          uint    ItemSize : The size, in bytes, of the            */
+/*                             replacement object                    */
+/*          ADDRESS ItemLocation : The address of the replacement    */
+/*                                 item                              */
+/*          TAG     ItemTag : The item tag that the user wishes to   */
+/*                            associate with the replacement item    */
+/*          ADDRESS Handle : The handle of the item to get.  This    */
+/*                           handle must be of an item which resides */
+/*                           in ListToGetItemFrom, or NULL.  If NULL */
+/*                           then the current item in the list will  */
+/*                           be used.                                */
+/*          BOOLEAN MakeCurrent : If TRUE, the item to get will      */
+/*                                become the current item in the     */
+/*                                list.                              */
+/*           ADDRESS   * Object : The address of a variable to hold  */
+/*                                the ADDRESS of the object that     */
+/*                                was replaced.                      */
+/*                                                                   */
+/*   Output:  If Successful then return DLIST_SUCCESS and the        */
+/*              *Object will contain the address of the object that  */
+/*              was replaced.                                        */
+/*            If Unsuccessful, then return an error code and         */
+/*              *Object will be NULL.                                */
+/*                                                                   */
+/*   Error Handling:  This function will fail under the following    */
+/*                    conditions:                                    */
+/*                         ListToReplaceItemIn is empty              */
+/*                         ItemSize is 0                             */
+/*                         ItemLocation is NULL                      */
+/*                         The memory required can not be allocated. */
+/*                         Handle is invalid, or is for an item      */
+/*                             which is not in ListToGetItemFrom     */
+/*                    If any of these conditions occurs, an error    */
+/*                    code will be returned.                         */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  The user is responsible for the memory associated with  */
+/*           the object returned by this function as that object is  */
+/*           removed from the list.  This means that, when the user  */
+/*           is through with the object returned by this function,   */
+/*           they should free it.                                    */
+/*                                                                   */
+/*           It is assumed that if ItemLocation is not NULL, then    */
+/*           it is a valid address that can be dereferenced.  If     */
+/*           these assumptions are violated, an exception or trap    */
+/*           may occur.                                              */
+/*                                                                   */
+/*           It is assumed that Handle is valid, or is at least the  */
+/*           address of an accessible block of storage.  If Handle   */
+/*           is invalid, or is not the address of an accessible block*/
+/*           of storage, then a trap or exception may occur.         */
+/*           NOTE: For this function, NULL is a valid handle for the */
+/*                 current item in the list.                         */
+/*                                                                   */
+/*           It is assumed that Object is a valid address.  If not,  */
+/*           an exception or trap may occur.                         */
+/*                                                                   */
+/*           This function does not alter which item is the current  */
+/*           item in the list.                                       */
+/*                                                                   */
+/*********************************************************************/
+int ReplaceObject(dlist_t   ListToReplaceItemIn,
+                  uint    * ItemSize,             /* On input - size of new object.  On return = size of old object. */
+                  ADDRESS   ItemLocation,
+                  TAG     * ItemTag,              /* On input - TAG of new object.  On return = TAG of old object. */
+                  ADDRESS   Handle,
+                  BOOLEAN   MakeCurrent,
+                  ADDRESS * Object);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  GetTag                                          */
+/*                                                                   */
+/*   Descriptive Name:  This function returns the item tag associated*/
+/*                      with the current item in the list.           */
+/*                                                                   */
+/*   Input:  dlist_t ListToGetTagFrom : The list from which the item */
+/*                                      tag of the current item is to*/
+/*                                      be returned                  */
+/*           ADDRESS Handle : The handle of the item whose TAG and   */
+/*                            size we are to get.  This handle must  */
+/*                            be of an item which resides in         */
+/*                            in ListToGetTagFrom, or NULL.  If NULL */
+/*                            then the current item in the list will */
+/*                            be used.                               */
+/*           uint       * ItemSize : The size, in bytes, of the      */
+/*                                   current item in the list.       */
+/*           TAG        * Tag : The address of a variable to hold    */
+/*                              the returned tag.                    */
+/*                                                                   */
+/*   Output:  If successful, the function returns DLIST_SUCCESS.     */
+/*               *ItemSize contains the size of the item.  *Tag      */
+/*               contains the tag.                                   */
+/*            If unsuccessful, an error code is returned.            */
+/*                                                                   */
+/*   Error Handling: This function will fail if ListToGetTagFrom is  */
+/*                   not a valid list or is an empty list.  In either*/
+/*                   of these cases, an error code is returned.      */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*********************************************************************/
+int GetTag(dlist_t   ListToGetTagFrom,
+           ADDRESS   Handle,
+           uint    * ItemSize,
+           TAG     * Tag);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  GetHandle                                       */
+/*                                                                   */
+/*   Descriptive Name:  This function returns a handle for the       */
+/*                      current item in the list.  This handle is    */
+/*                      then associated with that item regardless of */
+/*                      its position in the list.  This handle can be*/
+/*                      used to make its associated item the current */
+/*                      item in the list.                            */
+/*                                                                   */
+/*   Input:  dlist_t ListToGetHandleFrom : The list from which a     */
+/*                                         handle is needed.         */
+/*           ADDRESS * Handle   : The address of a variable to hold  */
+/*                                the handle                         */
+/*                                                                   */
+/*   Output:  If successful, the function returns DLIST_SUCCESS and  */
+/*               *Handle is set to the handle for the current item   */
+/*               in ListToGetHandleFrom.                             */
+/*            If unsuccessful, an error code is returned and *Handle */
+/*               is set to 0.                                        */
+/*                                                                   */
+/*   Error Handling: This function will fail if ListToGetHandleFrom  */
+/*                   is not a valid list or is an empty list.  In    */
+/*                   either of these cases, an error code is         */
+/*                   returned.                                       */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  The handle returned is a pointer to the LinkNode of the */
+/*           current item in the list.  This allows the item to move */
+/*           around in the list without losing its associated handle.*/
+/*           However, if the item is deleted from the list, then the */
+/*           handle is invalid and its use could result in a trap.   */
+/*                                                                   */
+/*********************************************************************/
+int GetHandle (dlist_t   ListToGetHandleFrom,
+               ADDRESS * Handle);
+
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  GetListSize                                     */
+/*                                                                   */
+/*   Descriptive Name:  This function returns the number of items in */
+/*                      a list.                                      */
+/*                                                                   */
+/*   Input:  dlist_t ListToGetSizeOf : The list whose size we wish to*/
+/*                                     know                          */
+/*           uint       * Size  : The address of a variable to hold  */
+/*                                the size of the list.              */
+/*                                                                   */
+/*   Output:  If successful, the function returns DLIST_SUCCESS and  */
+/*               *Size contains the a count of the number of items   */
+/*               in the list.                                        */
+/*            If unsuccessful, an error code is returned and *Size   */
+/*               is set to 0.                                        */
+/*                                                                   */
+/*   Error Handling: This function will fail if ListToGetSizeOf is   */
+/*                   not a valid list.  If this happens, then an     */
+/*                   error code is returned.        .                */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  It is assumed that Size contains a valid address. If    */
+/*           this assumption is violated, an exception or trap       */
+/*           may occur.                                              */
+/*                                                                   */
+/*********************************************************************/
+int GetListSize(dlist_t ListToGetSizeOf,
+                uint * Size);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  ListEmpty                                       */
+/*                                                                   */
+/*   Descriptive Name:  This function returns TRUE if the            */
+/*                      specified list is empty, otherwise it returns*/
+/*                      FALSE.                                       */
+/*                                                                   */
+/*   Input:  dlist_t     ListToCheck : The list to check to see if it*/
+/*                                     is empty                      */
+/*                                                                   */
+/*   Output:  If successful, the function returns TRUE if the        */
+/*               number of items in the list is 0, otherwise it      */
+/*               returns FALSE.                                      */
+/*            If unsuccessful, the function returns TRUE.            */
+/*                                                                   */
+/*   Error Handling: This function will return TRUE if ListToCheck   */
+/*                   is not a valid list.                            */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*********************************************************************/
+BOOLEAN ListEmpty(dlist_t ListToCheck);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  AtEndOfList                                     */
+/*                                                                   */
+/*   Descriptive Name:  This function returns TRUE if the            */
+/*                      current item in the list is the last item    */
+/*                      in the list.  Returns FALSE otherwise.       */
+/*                                                                   */
+/*   Input:  dlist_t     ListToCheck : The list to check.            */
+/*                                                                   */
+/*   Output:  If successful, the function returns TRUE if the        */
+/*               current item in the list is the last item in the    */
+/*               list.  If it is not the last item in the list,      */
+/*               FALSE is returned.                                  */
+/*            If unsuccessful, the function returns FALSE.           */
+/*                                                                   */
+/*   Error Handling: This function will return FALSE ListToCheck is  */
+/*                   not a valid list.                               */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*********************************************************************/
+BOOLEAN AtEndOfList(dlist_t ListToCheck);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  AtStartOfList                                   */
+/*                                                                   */
+/*   Descriptive Name:  This function returns TRUE if the            */
+/*                      current item in the list is the first item   */
+/*                      in the list.  Returns FALSE otherwise.       */
+/*                                                                   */
+/*   Input:  dlist_t     ListToCheck : The list to check.            */
+/*                                                                   */
+/*   Output:  If successful, the function returns TRUE if the        */
+/*               current item in the list is the first item in the   */
+/*               list.  If it is not the first item in the list,     */
+/*               FALSE is returned.                                  */
+/*            If unsuccessful, the function returns FALSE            */
+/*                                                                   */
+/*   Error Handling: This function will return FALSE if ListToCheck  */
+/*                   is not a valid list.                            */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*********************************************************************/
+BOOLEAN AtStartOfList(dlist_t ListToCheck);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  DestroyList                                     */
+/*                                                                   */
+/*   Descriptive Name:  This function releases the memory associated */
+/*                      with the internal data structures of a       */
+/*                      dlist_t. Once a dlist_t has been destroyed   */
+/*                      by this function, it must be reinitialized   */
+/*                      before it can be used again.                 */
+/*                                                                   */
+/*   Input:  dlist_t     ListToDestroy : The list to be eliminated   */
+/*                                       from memory.                */
+/*           BOOLEAN FreeItemMemory : If TRUE, all items in the list */
+/*                                    will be freed.  If FALSE, all  */
+/*                                    items in the list are not      */
+/*                                    freed, only the list structures*/
+/*                                    associated with them are.      */
+/*                                                                   */
+/*   Output:  If successful, return DLIST_SUCCESS                    */
+/*            If unsuccessful, return an error code.                 */
+/*                                                                   */
+/*   Error Handling: This function will fail if ListToDestroy is not */
+/*                   a valid list.  If this happens, then an error   */
+/*                   code is returned.                               */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  If FreeItemMemory is TRUE, then this function will try  */
+/*           to delete any items which may be in the list.  However, */
+/*           since this function has no way of knowing the internal  */
+/*           structure of an item, items which contain embedded      */
+/*           pointers will not be entirely freed.  This can lead to  */
+/*           memory leaks.  The programmer should ensure that any    */
+/*           list passed to this function when the FreeItemMemory    */
+/*           parameter is TRUE is empty or does not contain any      */
+/*           items with embedded pointers.                           */
+/*                                                                   */
+/*********************************************************************/
+int DestroyList(dlist_t * ListToDestroy,
+                BOOLEAN   FreeItemMemory);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  NextItem                                        */
+/*                                                                   */
+/*   Descriptive Name:  This function makes the next item in the list*/
+/*                      the current item in the list (i.e. it        */
+/*                      advances the current item pointer).          */
+/*                                                                   */
+/*   Input:  dlist_t     ListToAdvance : The list whose current item */
+/*                                       pointer is to be advanced   */
+/*                                                                   */
+/*   Output:  If successful, return DLIST_SUCCESS.                   */
+/*            If unsuccessful, return error code.                    */
+/*                                                                   */
+/*   Error Handling: This function will fail under the following     */
+/*                   conditions:                                     */
+/*                        ListToAdvance is not a valid list          */
+/*                        ListToAdvance is empty                     */
+/*                        The current item is the last item in the   */
+/*                           list                                    */
+/*                   If any of these conditions occurs, then an      */
+/*                   error code is returned.                         */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*********************************************************************/
+int NextItem(dlist_t ListToAdvance);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  PreviousItem                                    */
+/*                                                                   */
+/*   Descriptive Name:  This function makes the previous item in the */
+/*                      list the current item in the list.           */
+/*                                                                   */
+/*   Input:  dlist_t     ListToChange : The list whose current item  */
+/*                                      pointer is to be changed     */
+/*                                                                   */
+/*   Output:  If successful, return DLIST_SUCCESS.                   */
+/*            If unsuccessful, return an error code.                 */
+/*                                                                   */
+/*   Error Handling: This function will fail under the following     */
+/*                   conditions:                                     */
+/*                        ListToChange is not a valid list           */
+/*                        ListToChange is empty                      */
+/*                        The current item is the first item in the  */
+/*                           list                                    */
+/*                   If any of these conditions occurs, then return  */
+/*                   an error code.                                  */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*********************************************************************/
+int PreviousItem(dlist_t ListToChange);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name: GoToStartOfList                                  */
+/*                                                                   */
+/*   Descriptive Name:  This function makes the first item in the    */
+/*                      list the current item in the list.           */
+/*                                                                   */
+/*   Input:  dlist_t     ListToReset : The list whose current item   */
+/*                                     is to be set to the first     */
+/*                                     item in the list              */
+/*                                                                   */
+/*   Output:  If successful, return DLIST_SUCCESS.                   */
+/*            If unsuccessful, return an error code                  */
+/*                                                                   */
+/*   Error Handling: This function will fail if ListToAdvance is not */
+/*                   a valid list.  If this occurs, then an error    */
+/*                   code is returned.                               */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*********************************************************************/
+int GoToStartOfList(dlist_t ListToReset);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name: GoToEndOfList                                    */
+/*                                                                   */
+/*   Descriptive Name:  This function makes the last item in the     */
+/*                      list the current item in the list.           */
+/*                                                                   */
+/*   Input:  dlist_t     ListToSet : The list whose current item     */
+/*                                   is to be set to the last item   */
+/*                                   in the list                     */
+/*                                                                   */
+/*   Output:  If successful, return DLIST_SUCCESS.                   */
+/*            If unsuccessful, return an error code                  */
+/*                                                                   */
+/*   Error Handling: This function will fail if ListToAdvance is not */
+/*                   a valid list.  If this occurs, then an error    */
+/*                   code is returned.                               */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*********************************************************************/
+int GoToEndOfList(dlist_t ListToSet);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name: GoToSpecifiedItem                                */
+/*                                                                   */
+/*   Descriptive Name:  This function makes the item associated with */
+/*                      Handle the current item in the list.         */
+/*                                                                   */
+/*   Input:  dlist_t ListToReposition:  The list whose current item  */
+/*                                      is to be set to the item     */
+/*                                      associated with Handle.      */
+/*           ADDRESS Handle : A handle obtained by using the         */
+/*                            GetHandle function.  This handle       */
+/*                            identifies a unique item in the list.  */
+/*                                                                   */
+/*   Output:  If successful, return DLIST_SUCCESS.                   */
+/*            If unsuccessful, return an error code                  */
+/*                                                                   */
+/*   Error Handling: This function will fail if ListToAdvance is not */
+/*                   a valid list.  If this occurs, then an error    */
+/*                   code is returned.                               */
+/*                                                                   */
+/*   Side Effects:  None.                                            */
+/*                                                                   */
+/*   Notes:  It is assumed that Handle is a valid handle and that    */
+/*           the item associated with Handle is still in the list.   */
+/*           If these conditions are not met, an exception or trap   */
+/*           may occur.                                              */
+/*                                                                   */
+/*********************************************************************/
+int GoToSpecifiedItem(dlist_t ListToReposition,
+                      ADDRESS Handle);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  SortList                                        */
+/*                                                                   */
+/*   Descriptive Name:  This function sorts the contents of a list.  */
+/*                      The sorting algorithm used is a stable sort  */
+/*                      whose performance is not dependent upon the  */
+/*                      initial order of the items in the list.      */
+/*                                                                   */
+/*   Input: dlist_t ListToSort : The dlist_t that is to be sorted.   */
+/*                                                                   */
+/*          int (*Compare) ( ... )                                   */
+/*                                                                   */
+/*              This is a pointer to a function that can compare any */
+/*              two items in the list.  It should return -1 if       */
+/*              Object1 is less than Object2, 0 if Object1 is equal  */
+/*              to Object2, and 1 if Object1 is greater than Object2.*/
+/*              This function will be called during the sort whenever*/
+/*              the sorting algorithm needs to compare two objects.  */
+/*                                                                   */
+/*              The Compare function takes the following parameters: */
+/*                                                                   */
+/*              ADDRESS Object1 : The address of the data for the    */
+/*                                first object to be compared.       */
+/*              TAG Object1Tag : The user assigned TAG value for the */
+/*                               first object to be compared.        */
+/*              ADDRESS Object2 : The address of the data for the    */
+/*                                second object to be compared.      */
+/*              TAG Object2Tag : The user assigned TAG value for the */
+/*                               second object to be compared.       */
+/*              uint * Error : The address of a variable to hold the */
+/*                             error return value.                   */
+/*                                                                   */
+/*              If this function ever sets *Error to a non-zero value*/
+/*              the sort will terminate and the error code will be   */
+/*              returned to the caller of the SortList function.     */
+/*                                                                   */
+/*                                                                   */
+/*   Output:  If successful, this function will return DLIST_SUCCESS */
+/*               and ListToSort will have been sorted.               */
+/*            If unsuccessful, an error code will be returned.       */
+/*               The order of the items in ListToSort is undefined   */
+/*               and may have changed.                               */
+/*                                                                   */
+/*   Error Handling: This function will terminate if *Compare sets   */
+/*                   *Error to a non-zero value, or if ListToSort    */
+/*                   is invalid.  If this function does terminate in */
+/*                   the middle of a sort, the order of the items in */
+/*                   ListToSort may be different than it was before  */
+/*                   the function was called.                        */
+/*                                                                   */
+/*   Side Effects: None.                                             */
+/*                                                                   */
+/*   Notes:  This function works by breaking the list into sublists  */
+/*           and merging the sublists back into one list.  The size  */
+/*           of the sublists starts at 1, and with each pass, the    */
+/*           of the sublists is doubled.  The sort ends when the size*/
+/*           of a sublist is greater than the size of the original   */
+/*           list.                                                   */
+/*                                                                   */
+/*********************************************************************/
+int SortList(dlist_t ListToSort,
+             int   (*Compare) (ADDRESS   Object1,
+                               TAG       Object1Tag,
+                               ADDRESS   Object2,
+                               TAG       Object2Tag,
+                               uint    * Error));
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  ForEachItem                                     */
+/*                                                                   */
+/*   Descriptive Name:  This function passes a pointer to each item  */
+/*                      in a list to a user provided function for    */
+/*                      processing by the user provided function.    */
+/*                                                                   */
+/*   Input:  dlist_t ListToProcess : The dlist_t whose items are to  */
+/*                                   be processed by the user        */
+/*                                   provided function.              */
+/*                                                                   */
+/*           int (*ProcessItem) (...)                                */
+/*                                                                   */
+/*               This is a pointer to the user provided function.    */
+/*               This user provided function takes the following     */
+/*                  parameters:                                      */
+/*                                                                   */
+/*                  ADDRESS Object : A pointer to an item in         */
+/*                                   ListToProcess.                  */
+/*                  TAG Object1Tag : The user assigned TAG value for */
+/*                                   the item pointed to by Object.  */
+/*                  ADDRESS Parameter : The address of a block of    */
+/*                                      memory containing any        */
+/*                                      parameters that the user     */
+/*                                      wishes to have passed to this*/
+/*                                      function.                    */
+/*                                                                   */
+/*           ADDRESS Parameters : This field is passed through to    */
+/*                                *ProcessItem.  This function does  */
+/*                                not even look at the contents of   */
+/*                                this field.  This field is here to */
+/*                                provide the user a way to pass     */
+/*                                additional data to *ProcessItem    */
+/*                                that *ProcessItem may need to      */
+/*                                function correctly.                */
+/*                                                                   */
+/*   Output:  If successful, return DLIST_SUCCESS.                   */
+/*            If unsuccessful, return an error code.                 */
+/*                                                                   */
+/*   Error Handling: This function aborts immediately when an error  */
+/*                   is detected, and any remaining items in the list*/
+/*                   will not be processed.                          */
+/*                                                                   */
+/*   Side Effects: None.                                             */
+/*                                                                   */
+/*   Notes: This function allows the user to access all of the items */
+/*          in a list and perform an operation on them.  The         */
+/*          operation performed must not free any items in the list, */
+/*          or perform any list operations on the list being         */
+/*          processed.                                               */
+/*                                                                   */
+/*          As an example of when this would be useful, consider a   */
+/*          a list of graphic objects (rectangles, triangles, circles*/
+/*          etc.)  which comprise a drawing.  To draw the picture    */
+/*          that these graphic objects represent, one could build a  */
+/*          loop which gets and draws each item.  Another way to     */
+/*          do this would be to build a drawing function which can   */
+/*          draw any of the graphic objects, and then use that       */
+/*          function as the ProcessItem function in a call to        */
+/*          ForEachItem.                                             */
+/*                                                                   */
+/*          If the ProcessItem function returns an error code        */
+/*          other than DLIST_SUCCESS, then ForEachItem will terminate*/
+/*          and return an error to whoever called it.  The single    */
+/*          exception to this is if ProcessItem returns              */
+/*          DLIST_SEARCH_COMPLETE, in which case ForEachItem         */
+/*          terminates and returns DLIST_SUCCESS.  This is           */
+/*          useful for using ForEachItem to search a list and then   */
+/*          terminating the search once the desired item is found.   */
+/*                                                                   */
+/*          A word about the Parameters parameter.  This parameter   */
+/*          is passed through to *ProcessItem and is never looked at */
+/*          by this function.  This means that the user can put any  */
+/*          value they desire into Parameters as long as it is the   */
+/*          same size (in bytes) as Parameters.  The intended use of */
+/*          Parameters is to allow the user to pass information to   */
+/*          *ProcessItem that *ProcessItem may need.  Either way,    */
+/*          how Parameters is used is literally up to the user.      */
+/*                                                                   */
+/*********************************************************************/
+int ForEachItem(dlist_t ListToProcess,
+                int     (*ProcessItem) (ADDRESS Object,
+                                        TAG     ObjectTag,
+                                        uint    ObjectSize,
+                                        ADDRESS ObjectHandle,
+                                        ADDRESS Parameters),
+                ADDRESS Parameters,
+                BOOLEAN Forward);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  PruneList                                       */
+/*                                                                   */
+/*   Descriptive Name:  This function allows the caller to examine   */
+/*                      each item in a list and optionally delete    */
+/*                      it from the list.                            */
+/*                                                                   */
+/*   Input:  dlist_t ListToProcess : The dlist_t to be pruned.       */
+/*                                                                   */
+/*           BOOLEAN (*KillItem) (...)                               */
+/*                                                                   */
+/*               This is a pointer to a user provided function.      */
+/*               This user provided function takes the following     */
+/*                  parameters:                                      */
+/*                                                                   */
+/*                  ADDRESS Object : A pointer to an item in         */
+/*                                   ListToProcess.                  */
+/*                  TAG Object1Tag : The user assigned TAG value for */
+/*                                   the item pointed to by Object.  */
+/*                  ADDRESS Parameter : The address of a block of    */
+/*                                      memory containing any        */
+/*                                      parameters that the user     */
+/*                                      wishes to have passed to this*/
+/*                                      function.                    */
+/*                  BOOLEAN * FreeMemory : The address of a BOOLEAN  */
+/*                                         variable which this       */
+/*                                         function will set to      */
+/*                                         either TRUE or FALSE.     */
+/*                                         If the function return    */
+/*                                         value is TRUE, then the   */
+/*                                         value in *FreeMemory will */
+/*                                         be examined.  If it is    */
+/*                                         TRUE, then PruneList will */
+/*                                         free the memory associated*/
+/*                                         with the item being       */
+/*                                         deleted.  If *FreeMemory  */
+/*                                         is FALSE, then the item   */
+/*                                         being removed from the    */
+/*                                         dlist_t will not be freed,*/
+/*                                         and it is up to the user  */
+/*                                         to ensure that this memory*/
+/*                                         is handled properly.      */
+/*                  uint       * Error : The address of a variable to*/
+/*                                       hold the error return value.*/
+/*                                                                   */
+/*           ADDRESS Parameters : This field is passed through to    */
+/*                                *KillItem.  This function does     */
+/*                                not even look at the contents of   */
+/*                                this field.  This field is here to */
+/*                                provide the user a way to pass     */
+/*                                additional data to *ProcessItem    */
+/*                                that *ProcessItem may need to      */
+/*                                function correctly.                */
+/*                                                                   */
+/*                                                                   */
+/*   Output:  If successful, return DLIST_SUCCESS.                   */
+/*            If unsuccessful, return an error code.                 */
+/*                                                                   */
+/*   Error Handling: This function aborts immediately when an error  */
+/*                   is detected, and any remaining items in the list*/
+/*                   will not be processed.                          */
+/*                                                                   */
+/*   Side Effects: None.                                             */
+/*                                                                   */
+/*   Notes: This function allows the user to access all of the items */
+/*          in a list, perform an operation on them, and then        */
+/*          optionally delete ("remove") them from the dlist_t.  The */
+/*          operation performed must not free any items in the list, */
+/*          or perform any list operations on the list being         */
+/*          processed.                                               */
+/*                                                                   */
+/*          If the KillItem function sets *Error to something other  */
+/*          than DLIST_SUCCESS, then PruneList will terminate and    */
+/*          return an error to whoever called it.  The single        */
+/*          exception to this is if KillItem sets *Error to          */
+/*          DLIST_SEARCH_COMPLETE, in which case KillItem            */
+/*          terminates and sets *Error to DLIST_SUCCESS.  This is    */
+/*          useful for using KillItem to search a list and then      */
+/*          terminating the search once the desired item is found.   */
+/*                                                                   */
+/*          A word about the Parameters parameter.  This parameter   */
+/*          is passed through to *ProcessItem and is never looked at */
+/*          by this function.  This means that the user can put any  */
+/*          value they desire into Parameters as long as it is the   */
+/*          same size (in bytes) as Parameters.  The intended use of */
+/*          Parameters is to allow the user to pass information to   */
+/*          *ProcessItem that *ProcessItem may need.  Either way,    */
+/*          how Parameters is used is literally up to the user.      */
+/*                                                                   */
+/*********************************************************************/
+int PruneList(dlist_t ListToProcess,
+              BOOLEAN (*KillItem) (ADDRESS   Object,
+                                   TAG       ObjectTag,
+                                   uint      ObjectSize,
+                                   ADDRESS   ObjectHandle,
+                                   ADDRESS   Parameters,
+                                   BOOLEAN * FreeMemory,
+                                   uint    * Error),
+              ADDRESS Parameters);
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  AppendList                                      */
+/*                                                                   */
+/*   Descriptive Name: Removes the items in SourceList and appends   */
+/*                     them to TargetList.                           */
+/*                                                                   */
+/*   Input:  dlist_t TargetList : The dlist_t which is to have the   */
+/*                                items from SourceList appended to  */
+/*                                it.                                */
+/*           dlist_t SourceList : The dlist_t whose items are to be  */
+/*                                removed and appended to TargetList.*/
+/*                                                                   */
+/*   Output: If successful, return DLIST_SUCCESS.                    */
+/*              SourceList will be empty, and TargetList will contain*/
+/*              all of its original items and all of the items that  */
+/*              were in SourceList.                                  */
+/*           If unsuccessful, return an error code.  SourceList and  */
+/*              TargetList will be unmodified.                       */
+/*                                                                   */
+/*   Error Handling:  This function will abort immediately upon      */
+/*                    detection of an error.  All errors that can be */
+/*                    detected are detected before the contents of   */
+/*                    SourceList are appended to TargetList, so if an*/
+/*                    error is detected and the function aborts,     */
+/*                    SourceList and TargetList are unaltered.       */
+/*                                                                   */
+/*   Side Effects: None.                                             */
+/*                                                                   */
+/*   Notes: None.                                                    */
+/*                                                                   */
+/*********************************************************************/
+int AppendList(dlist_t TargetList,
+               dlist_t SourceList);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  TransferItem                                    */
+/*                                                                   */
+/*   Descriptive Name: Removes an item in SourceList and places in   */
+/*                     TargetList.                                   */
+/*                                                                   */
+/*   Input:  dlist_t SourceList : The dlist_t containing the item    */
+/*                                which is to be transferred.        */
+/*           ADDRESS SourceHandle : The handle of the item in        */
+/*                                   SourceList which is to be       */
+/*                                   transferred to another dlist_t. */
+/*                                   If this is NULL, then the       */
+/*                                   current item in SourceList will */
+/*                                   be used.                        */
+/*           dlist_t TargetList : The dlist_t which is to receive the*/
+/*                                item being transferred.            */
+/*           ADDRESS TargetHandle : The item in TargetList which     */
+/*                                   is used to determine where      */
+/*                                   the item being transferred will */
+/*                                   be placed.  If this is NULL,    */
+/*                                   then the current item in        */
+/*                                   TargetList will be used.        */
+/*           Insertion_Modes TransferMode : This indicates where,    */
+/*                                   relative to the item in         */
+/*                                   TargetList specified by         */
+/*                                   Target_Handle, the item being   */
+/*                                   transferred can be placed.      */
+/*          BOOLEAN MakeCurrent : If TRUE, the item transferred to   */
+/*                                TargetList becomes the current     */
+/*                                item in TargetList.                */
+/*                                                                   */
+/*   Output: If successful, return DLIST_SUCCESS, SourceList will be */
+/*              empty, and TargetList will contain all of its        */
+/*              original items and all of the items that were in     */
+/*              SourceList.                                          */
+/*           If unsuccessful, an error code will be returned  and    */
+/*              SourceList and TargetList will be unmodified.        */
+/*                                                                   */
+/*   Error Handling:  This function will abort immediately upon      */
+/*                    detection of an error.  All errors that can be */
+/*                    detected are detected before the contents of   */
+/*                    SourceList are appended to TargetList, so if an*/
+/*                    error is detected and the function aborts,     */
+/*                    SourceList and TargetList are unaltered.       */
+/*                                                                   */
+/*   Side Effects: None.                                             */
+/*                                                                   */
+/*   Notes: None.                                                    */
+/*                                                                   */
+/*********************************************************************/
+int TransferItem(dlist_t         SourceList,
+                 ADDRESS         SourceHandle,
+                 dlist_t         TargetList,
+                 ADDRESS         TargetHandle,
+                 Insertion_Modes TransferMode,
+                 BOOLEAN         MakeCurrent);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  CopyList                                        */
+/*                                                                   */
+/*   Descriptive Name: Copies the items in SourceList to the         */
+/*                     TargetList.                                   */
+/*                                                                   */
+/*   Input:  dlist_t TargetList : The dlist_t which is to have the   */
+/*                                items from SourceList copied to it.*/
+/*           dlist_t SourceList : The dlist_t whose items are to be  */
+/*                                copied to TargetList.              */
+/*                                                                   */
+/*   Output: If successful, return DLIST_SUCCESS.                    */
+/*              SourceList will be unchanged and TargetList will     */
+/*              contain all of its original items and all of the     */
+/*              items that were in SourceList.                       */
+/*           If unsuccessful, return an error code.  SourceList and  */
+/*              TargetList will be unmodified.                       */
+/*                                                                   */
+/*   Error Handling:  This function will abort immediately upon      */
+/*                    detection of an error.  All errors that can be */
+/*                    detected are detected before the contents of   */
+/*                    SourceList are appended to TargetList, so if an*/
+/*                    error is detected and the function aborts,     */
+/*                    SourceList and TargetList are unaltered.       */
+/*                                                                   */
+/*   Side Effects: None.                                             */
+/*                                                                   */
+/*   Notes: None.                                                    */
+/*                                                                   */
+/*********************************************************************/
+int CopyList(dlist_t         TargetList,
+             dlist_t         SourceList,
+             Insertion_Modes Insert_Mode);
+
+
+/*********************************************************************/
+/*                                                                   */
+/*   Function Name:  CheckListIntegrity                              */
+/*                                                                   */
+/*   Descriptive Name: Checks the integrity of a dlist_t.  All link  */
+/*                     nodes in the list are checked, as are all     */
+/*                     fields in the list control block.             */
+/*                                                                   */
+/*   Input:  dlist_t ListToCheck - The list whose integrity is to be */
+/*                                 checked.                          */
+/*                                                                   */
+/*   Output: The function return value will be TRUE if all of the    */
+/*           elements in the dlist_t are correct.  If this function  */
+/*           returns FALSE, then the dlist_t being checked has been  */
+/*           corrupted!                                              */
+/*                                                                   */
+/*   Error Handling: If this function encounters an error in a       */
+/*                   dlist_t, it will return FALSE.                  */
+/*                                                                   */
+/*   Side Effects: None.                                             */
+/*                                                                   */
+/*   Notes: None.                                                    */
+/*                                                                   */
+/*********************************************************************/
+BOOLEAN CheckListIntegrity(dlist_t ListToCheck);
+
+
+#endif
+
+
diff --git a/lib/evms/enginestructs.h b/lib/evms/enginestructs.h
new file mode 100644
index 0000000..f74d5bb
--- /dev/null
+++ b/lib/evms/enginestructs.h
@@ -0,0 +1,302 @@
+/*
+ *
+ *   Copyright (c) International Business Machines  Corp., 2001
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Module: enginestructs.h
+ */
+
+#ifndef EVMS_ENGINESTRUCTS_H_INCLUDED
+#define EVMS_ENGINESTRUCTS_H_INCLUDED 1
+
+#include <byteswap.h>
+#include <dlist.h>
+#include <common.h>
+#include <options.h>
+#include <evms/evms_user.h>
+
+struct plugin_functions_s;
+struct fsim_functions_s;
+struct container_functions_s;
+
+/*
+ * The so_record_t contains information about a .so that was loaded which
+ * contains plug-in(s).
+ */
+typedef struct so_record_s {
+    char          * name;
+    module_handle_t handle;
+    dlist_t         plugin_list;
+} so_record_t;
+
+
+typedef struct plugin_record_s {
+    object_handle_t                 app_handle;            /* External API handle for this structure; */
+                                                           /* used only by the Engine */
+    plugin_id_t                     id;                    /* Plug-in's ID */
+    evms_version_t                  version;               /* Plug-in's version */
+    evms_version_t                  required_api_version;  /* Version of the Engine plug-in API */
+                                                           /* that the plug-in requires */
+    so_record_t                   * so_record;             /* Record for the shared object from */
+                                                           /* which the plug-in was loaded */
+    char                          * short_name;
+    char                          * long_name;
+    char                          * oem_name;
+    union {
+        struct plugin_functions_s * plugin;
+        struct fsim_functions_s   * fsim;
+    } functions;
+    struct container_functions_s  * container_functions;   /* Optional container functions if the */
+                                                           /* plug-in supports containers */
+} plugin_record_t;
+
+
+typedef struct storage_object_s {
+    object_handle_t              app_handle;            /* External API handle for this structure; */
+                                                        /* used only by the Engine */
+    object_type_t                object_type;           /* SEGMENT, REGION, DISK ,... */
+    data_type_t                  data_type;             /* DATA_TYPE, META_DATA_TYPE, FREE_SPACE_TYPE */
+    plugin_record_t            * plugin;                /* Plug-in record of plug-in that manages this object */
+    struct storage_container_s * producing_container;   /* storage_container that produced this object */
+    struct storage_container_s * consuming_container;   /* storage_container that consumed this object */
+    dlist_t                      parent_objects;        /* List of parent objects, filled in by parent */
+    dlist_t                      child_objects;         /* List of child objects, filled in by owner */
+    struct storage_object_s    * associated_object;     /* Object to which this object is associated */
+    u_int32_t                    flags;                 /* Defined by SOFLAG_???? in common.h */
+    lba_t                        start;                 /* Relative starting block of this object */
+    sector_count_t               size;                  /* Size of object in sectors */
+    struct logical_volume_s    * volume;                /* Volume which comprises this object */
+    evms_feature_header_t      * feature_header;        /* Copy of EVMS storage object's top feature header */
+                                                        /* read in by Engine */
+                                                        /* NULL if it does not exist */
+    geometry_t                   geometry;              /* Optional geometry of the object */
+    void                       * private_data;          /* Optional plug-in's data for the object */
+    void                       * consuming_private_data;/* Optional consuming plug-in's data for the object */
+    char                         name[EVMS_NAME_SIZE+1];/* Object's name, filled in by owner */
+} storage_object_t;
+
+
+typedef struct storage_container_s {
+    object_handle_t   app_handle;               /* External API handle for this structure; */
+                                                /* used only by the Engine */
+    plugin_record_t * plugin;                   /* Plug-in record of the plug-in that manages */
+                                                /* this container */
+                                                /* Filled in by the plug-in during discover */
+                                                /* or create_container() */
+    uint              flags;                    /* Defined by SCFLAG_???? in common.h */
+    dlist_t           objects_consumed;         /* List of objects in this container */
+                                                /* The Engine allocate_container API will create the */
+                                                /* dlist_t anchor for this list. */
+                                                /* The plug-in inserts storage_object_t structures */
+                                                /* into this list when it assigns objects to this */
+                                                /* container. */
+    dlist_t           objects_produced;         /* List of objects produced from this container, */
+                                                /* including free space objects */
+                                                /* The Engine allocate_container API will create the */
+                                                /* dlist_t anchor for this list. */
+                                                /* The plug-in inserts storage_object_t structures */
+                                                /* into this list when it produces objects from this */
+                                                /* container. */
+    sector_count_t    size;                     /* Total size of all objects on the objects_produced list */
+    void            * private_data;             /* Optional plug-in data for the container */
+    char              name[EVMS_NAME_SIZE+1];   /* Container name, filled in by the plug-in */
+} storage_container_t;
+
+
+/*
+ * The logical_volume structures are created and managed by the Engine.
+ */
+typedef struct logical_volume_s {
+    object_handle_t           app_handle;           /* External API handle for this structure; */
+                                                    /* used only by the Engine */
+    plugin_record_t         * file_system_manager;  /* Plug-in record of the File System Interface */
+                                                    /* Module that handles this volume */
+    plugin_record_t         * original_fsim;        /* Plug-in record of the File System Interface */
+                                                    /* Module that was initially discovered for this volume */
+    char                    * mount_point;          /* Dir where the volume is mounted, NULL if not mounted */
+    sector_count_t            fs_size;              /* Size of the file system */
+    sector_count_t            min_fs_size;          /* Minimum size for the file system */
+    sector_count_t            max_fs_size;          /* Maximum size for the file system */
+    sector_count_t            original_vol_size;    /* Size of the file system before expand or shrink */
+    sector_count_t            vol_size;             /* Size of the volume */
+    sector_count_t            max_vol_size;         /* Maximum size for the volume */
+#ifndef ABI_EVMS_1_0
+    sector_count_t            shrink_vol_size;      /* Size to which to shrink the volume */
+#endif
+    struct logical_volume_s * associated_volume;    /* Volume to which this volume is associated */
+                                                    /* by an associative feature */
+    option_array_t          * mkfs_options;         /* Options for mkfs */
+    option_array_t          * fsck_options;         /* Options for fsck */
+    option_array_t          * defrag_options;       /* Options for defrag */
+    storage_object_t        * object;               /* Top level storage_object_t for the volume */
+    uint                      minor_number;         /* Volume's minor number */
+    u_int64_t                 serial_number;        /* Volume's serial number */
+    u_int32_t                 flags;                /* Defined by VOLFLAG_???? defines */
+    void                    * private_data;         /* Private data pointer for FSIMs. */
+    char                      name[EVMS_VOLUME_NAME_SIZE+1];
+                                                    /* Volume name, filled in by the Engine */
+#ifndef ABI_EVMS_1_0
+    char                      dev_node[EVMS_VOLUME_NAME_SIZE+1];
+                                                    /* Device node */
+#endif
+} logical_volume_t;
+
+
+/*
+ * Structure for a declined object.  Includes a pointer to the declined object
+ * and a reason (usually an error code).
+ */
+typedef struct declined_object_s {
+    storage_object_t * object;
+    int                reason;
+} declined_object_t;
+
+
+/*
+ * Tags for objects in dlists
+ */
+typedef enum {
+    PLUGIN_TAG          = PLUGIN,
+    DISK_TAG            = DISK,
+    SEGMENT_TAG         = SEGMENT,
+    REGION_TAG          = REGION,
+    EVMS_OBJECT_TAG     = EVMS_OBJECT,
+    CONTAINER_TAG       = CONTAINER,
+    VOLUME_TAG          = VOLUME,
+    DECLINED_OBJECT_TAG = (1<<7),
+    VOLUME_DATA_TAG     = (1<<8),
+    TASK_TAG            = (1<<9),
+    KILL_SECTOR_TAG     = (1<<10),
+    BLOCK_RUN_TAG       = (1<<11),
+    EXPAND_OBJECT_TAG   = (1<<12),
+    SHRINK_OBJECT_TAG   = (1<<13)
+} dlist_tag_t;
+
+
+typedef struct chs_s {
+    u_int32_t cylinder;
+    u_int32_t head;
+    u_int32_t sector;
+} chs_t;
+
+/*
+ * The block_run_t is used to describe a run of contiguous physical sectors on
+ * a disk.
+ */
+typedef struct block_run_s {
+    storage_object_t * disk;
+    lba_t              lba;
+    u_int64_t          number_of_blocks;
+} block_run_t;
+
+/*
+ * The kill_sector_record_t structure records a run of contiguous physical
+ * sectors on a disk that are to be zeroed out as part of the committing of
+ * changes to the disk.  Kill sectors are used to wipe data off of the disk
+ * so that it will not be found on a rediscover.
+ */
+typedef struct kill_sector_record_s {
+    storage_object_t * logical_disk;
+    lsn_t              sector_offset;
+    sector_count_t     sector_count;
+} kill_sector_record_t;
+
+/*
+ * The expand_object_info_t structure contains information about an object
+ * that is a candidate for expanding.  It contains a pointer to the object
+ * and the maximum delta size by which the object can expand.
+ */
+typedef struct expand_object_info_s {
+    storage_object_t * object;
+    sector_count_t     max_expand_size;
+} expand_object_info_t;
+
+/*
+ * The shrink_object_info_t structure contains information about an object
+ * that is a candidate for shrinking.  It contains a pointer to the object
+ * and the maximum delta size by which the object can shrink.
+ */
+typedef struct shrink_object_info_s {
+    storage_object_t * object;
+    sector_count_t     max_shrink_size;
+} shrink_object_info_t;
+
+/*
+ * Option descriptor structure
+ */
+typedef struct option_desc_array_s {
+    u_int32_t           count;                  /* Number of option descriptors in the following array */
+    option_descriptor_t option[1];              /* option_descriptor_t is defined in option.h */
+} option_desc_array_t;
+
+
+/*
+ * Task context structure
+ */
+typedef struct task_context_s {
+    plugin_record_t     * plugin;               /* Plug-in being communicated with */
+    storage_object_t    * object;               /* Object upon which to do the action */
+    storage_container_t * container;            /* Container upon which to do the action */
+    logical_volume_t    * volume;               /* Volume upon which to do the action */
+    task_action_t         action;               /* API application is interested in calling */
+    option_desc_array_t * option_descriptors;   /* Array of current task option descriptors */
+    dlist_t               acceptable_objects;   /* Current list of acceptable parameters */
+    dlist_t               selected_objects;     /* Current list of selected parameters */
+    u_int32_t             min_selected_objects; /* Minimum number of objects that must be selected. */
+    u_int32_t             max_selected_objects; /* Maximum number of objects that can be selected. */
+} task_context_t;
+
+
+/* Enum for the phases of the commit process. */
+typedef enum {
+    SETUP = 0,
+    FIRST_METADATA_WRITE = 1,
+    SECOND_METADATA_WRITE = 2,
+    POST_REDISCOVER = 3
+} commit_phase_t;
+
+
+/*
+ * Macros for referencing fields in disk structures.
+ * EVMS writes all disk structures in little endian format.  These macros can
+ * be used to access the fields of structures on disk regardless of the
+ * endianness of the CPU architecture.
+ */
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define CPU_TO_DISK16(x)    (bswap_16(x))
+#define CPU_TO_DISK32(x)    (bswap_32(x))
+#define CPU_TO_DISK64(x)    (bswap_64(x))
+
+#define DISK_TO_CPU16(x)    (bswap_16(x))
+#define DISK_TO_CPU32(x)    (bswap_32(x))
+#define DISK_TO_CPU64(x)    (bswap_64(x))
+
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define CPU_TO_DISK16(x)    (x)
+#define CPU_TO_DISK32(x)    (x)
+#define CPU_TO_DISK64(x)    (x)
+
+#define DISK_TO_CPU16(x)    (x)
+#define DISK_TO_CPU32(x)    (x)
+#define DISK_TO_CPU64(x)    (x)
+
+#else
+#error "__BYTE_ORDER must be defined as __LITTLE_ENDIAN or __BIG_ENDIAN"
+
+#endif
+
+#endif
diff --git a/lib/evms/evms_common.h b/lib/evms/evms_common.h
new file mode 100644
index 0000000..28249ea
--- /dev/null
+++ b/lib/evms/evms_common.h
@@ -0,0 +1,161 @@
+/* -*- linux-c -*- */
+/*
+ *
+ *   Copyright (c) International Business Machines  Corp., 2000
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * linux/include/linux/evms/evms_common.h
+ *
+ * EVMS common (kernel and user) header file
+ *
+ */
+
+#ifndef __EVMS_COMMON_INCLUDED__
+#define __EVMS_COMMON_INCLUDED__
+
+/* version info */
+#define EVMS_MAJOR                      63      /* use experimental major 63 for now */
+#define EVMS_MAJOR_VERSION              1
+#define EVMS_MINOR_VERSION              1
+#define EVMS_PATCHLEVEL_VERSION         0
+
+#define MAX_EVMS_VOLUMES                256 /* There are 256 minors */
+#define EVMS_VOLUME_NAME_SIZE           127
+
+#define IBM_OEM_ID                      8112    // could be anything, but used
+                                                // I=8, B=1, M=12
+// this one going away as well.
+#define EVMS_OEM_IBM    IBM_OEM_ID
+
+#define EVMS_INITIAL_CRC                0xFFFFFFFF
+#define EVMS_MAGIC_CRC			0x31415926
+
+#define EVMS_VSECTOR_SIZE               512
+#define EVMS_VSECTOR_SIZE_SHIFT         9
+
+#define DEV_PATH			"/dev"
+#define EVMS_DIR_NAME			"evms"
+#define EVMS_DEV_NAME			"block_device"
+#define EVMS_DEV_NODE_PATH		DEV_PATH "/" EVMS_DIR_NAME "/"
+#define EVMS_DEVICE_NAME		DEV_PATH "/" EVMS_DIR_NAME "/" EVMS_DEV_NAME
+
+/* EVMS will always use 64-bit fields */
+typedef u_int64_t evms_sector_t;
+
+/* EVMS specific device handle type definition */
+typedef u_int64_t evms_dev_handle_t;
+
+typedef struct evms_version_s {
+        /* major changes when incompatible differences are introduced */
+        u_int32_t    major;
+        /* minor changes when additions are made */
+        u_int32_t    minor;
+        /* patchlevel changes when bugs are fixed */
+        u_int32_t    patchlevel;
+} evms_version_t;
+
+typedef enum evms_plugin_code_s {
+        EVMS_NO_PLUGIN,                                // 0
+        EVMS_DEVICE_MANAGER,                           // 1
+        EVMS_SEGMENT_MANAGER,                          // 2
+        EVMS_REGION_MANAGER,                           // 3
+        EVMS_FEATURE,                                  // 4
+        EVMS_ASSOCIATIVE_FEATURE,                      // 5
+        EVMS_FILESYSTEM_INTERFACE_MODULE,              // 6
+        EVMS_CLUSTER_MANAGER_INTERFACE_MODULE,         // 7
+        EVMS_DISTRIBUTED_LOCK_MANAGER_INTERFACE_MODULE // 8
+} evms_plugin_code_t;
+
+#define SetPluginID(oem, type, id) ((oem << 16) | (type << 12) | id)
+#define GetPluginOEM(pluginid) (pluginid >> 16)
+#define GetPluginType(pluginid) ((pluginid >> 12) & 0xf)
+#define GetPluginID(pluginid) (pluginid & 0xfff)
+
+/* bit definitions for the flags field in
+ * the EVMS LOGICAL NODE (kernel) and
+ * the EVMS LOGICAL VOLUME (user) structures.
+ */
+#define EVMS_FLAGS_WIDTH                   	32
+#define EVMS_VOLUME_FLAG                        (1<<0)
+#define EVMS_VOLUME_PARTIAL_FLAG                (1<<1)
+#define EVMS_VOLUME_PARTIAL			(1<<1)
+#define EVMS_VOLUME_SET_READ_ONLY               (1<<2)
+#define EVMS_VOLUME_READ_ONLY               	(1<<2)
+/* queued flags bits */
+#define EVMS_REQUESTED_DELETE			(1<<5)
+#define EVMS_REQUESTED_QUIESCE			(1<<6)
+#define EVMS_REQUESTED_VFS_QUIESCE		(1<<7)
+/* this bit indicates corruption */
+#define EVMS_VOLUME_CORRUPT			(1<<8)
+/* these bits define the source of the corruption */
+#define EVMS_VOLUME_SOFT_DELETED               	(1<<9)
+#define EVMS_DEVICE_UNAVAILABLE			(1<<10)
+/* these bits define volume status */
+#define EVMS_MEDIA_CHANGED			(1<<20)
+#define EVMS_DEVICE_UNPLUGGED			(1<<21)
+/* these bits used for removable status */
+#define EVMS_DEVICE_MEDIA_PRESENT		(1<<24)
+#define EVMS_DEVICE_PRESENT			(1<<25)
+#define EVMS_DEVICE_LOCKABLE			(1<<26)
+#define EVMS_DEVICE_REMOVABLE			(1<<27)
+
+/* version info for evms_feature_header_t */
+#define EVMS_FEATURE_HEADER_MAJOR	3
+#define EVMS_FEATURE_HEADER_MINOR	0
+#define EVMS_FEATURE_HEADER_PATCHLEVEL	0
+
+/* bit definitions of FEATURE HEADER bits in the FLAGS field  */
+#define EVMS_FEATURE_ACTIVE                     (1<<0)
+#define EVMS_FEATURE_VOLUME_COMPLETE            (1<<1)
+/* bit definitions for VOLUME bits in the FLAGS field */
+#define EVMS_VOLUME_DATA_OBJECT			(1<<16)
+#define EVMS_VOLUME_DATA_STOP			(1<<17)
+
+#define EVMS_FEATURE_HEADER_SIGNATURE           0x54414546 //FEAT
+typedef struct evms_feature_header_s {
+/*  0*/ u_int32_t               signature;
+/*  4*/ u_int32_t               crc;
+/*  8*/ evms_version_t          version;		/* structure version */
+/* 20*/ evms_version_t          engine_version;		/* version of the Engine that */
+							/* wrote this feature header  */
+/* 32*/ u_int32_t               flags;
+/* 36*/ u_int32_t               feature_id;
+/* 40*/ u_int64_t		sequence_number;
+/* 48*/ u_int64_t		alignment_padding;
+        //required: starting lsn to 1st copy of feature's metadata.
+/* 56*/ evms_sector_t           feature_data1_start_lsn;
+/* 64*/	evms_sector_t		feature_data1_size; //in 512 byte units
+	//optional: starting lsn to 2nd copy of feature's metadata.
+	//          if unused set size field to 0.
+/* 72*/ evms_sector_t           feature_data2_start_lsn;
+/* 80*/	evms_sector_t		feature_data2_size; //in 512 byte units
+/* 88*/ u_int64_t               volume_serial_number;
+/* 96*/ u_int32_t               volume_system_id;       /* the minor is stored here */
+/*100*/ u_int32_t               object_depth;	/* depth of object in the volume tree */
+/*104*/ char                    object_name[EVMS_VOLUME_NAME_SIZE+1];
+/*232*/ char                    volume_name[EVMS_VOLUME_NAME_SIZE+1];
+/*360*/ unsigned char		pad[152];
+/*512*/
+} evms_feature_header_t;
+
+/* EVMS specific error codes */
+#define EVMS_FEATURE_FATAL_ERROR                257
+#define EVMS_VOLUME_FATAL_ERROR                 258
+
+#define EVMS_FEATURE_INCOMPLETE_ERROR		259
+
+#endif
diff --git a/lib/evms/evms_ioctl.h b/lib/evms/evms_ioctl.h
new file mode 100644
index 0000000..1131549
--- /dev/null
+++ b/lib/evms/evms_ioctl.h
@@ -0,0 +1,297 @@
+/* -*- linux-c -*- */
+/*
+ *
+ *   Copyright (c) International Business Machines  Corp., 2000
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * linux/include/linux/evms.h
+ *
+ * EVMS public kernel header file
+ *
+ */
+
+#ifndef __EVMS_IOCTL_INCLUDED__
+#define __EVMS_IOCTL_INCLUDED__
+
+#include <linux/hdreg.h>
+
+/* IOCTL interface version definitions */
+#define EVMS_IOCTL_INTERFACE_MAJOR           10
+#define EVMS_IOCTL_INTERFACE_MINOR           0
+#define EVMS_IOCTL_INTERFACE_PATCHLEVEL      0
+
+/* IOCTL definitions */
+typedef enum evms_ioctl_cmds_s {
+	/* version commands */
+	EVMS_GET_IOCTL_VERSION_NUMBER = 0,
+	EVMS_GET_VERSION_NUMBER,
+#ifdef __KERNEL__
+	/* EVMS internal commands */
+	EVMS_GET_DISK_LIST_NUMBER = 0x40,
+	EVMS_CHECK_MEDIA_CHANGE_NUMBER,
+	EVMS_REVALIDATE_DISK_NUMBER,
+	EVMS_OPEN_VOLUME_NUMBER,
+	EVMS_CLOSE_VOLUME_NUMBER,
+	EVMS_QUIESCE_VOLUME_NUMBER,
+	EVMS_CHECK_DEVICE_STATUS_NUMBER,
+#endif
+	/* configuration commands */
+	EVMS_GET_INFO_LEVEL_NUMBER = 0x80,
+	EVMS_SET_INFO_LEVEL_NUMBER,
+	EVMS_REDISCOVER_VOLUMES_NUMBER,
+	EVMS_DELETE_VOLUME_NUMBER,
+	EVMS_PLUGIN_IOCTL_NUMBER,
+	EVMS_PROCESS_NOTIFY_EVENT_NUMBER,
+	/* query info commands */
+	EVMS_GET_LOGICAL_DISK_NUMBER = 0xC0,
+	EVMS_GET_LOGICAL_DISK_INFO_NUMBER,
+	EVMS_SECTOR_IO_NUMBER,
+	EVMS_GET_MINOR_NUMBER,
+	EVMS_GET_VOLUME_DATA_NUMBER,
+	EVMS_GET_PLUGIN_NUMBER,
+	EVMS_COMPUTE_CSUM_NUMBER,
+	EVMS_GET_BMAP_NUMBER,
+} evms_ioctl_cmds_t;
+
+/* version commands */
+#define EVMS_GET_IOCTL_VERSION_STRING   "EVMS_GET_IOCTL_VERSION"
+#define EVMS_GET_IOCTL_VERSION          _IOR(EVMS_MAJOR, EVMS_GET_IOCTL_VERSION_NUMBER, evms_version_t)
+
+#define EVMS_GET_VERSION_STRING         "EVMS_GET_VERSION"
+#define EVMS_GET_VERSION                _IOR(EVMS_MAJOR, EVMS_GET_VERSION_NUMBER, evms_version_t)
+
+#ifdef __KERNEL__
+
+/* EVMS internal commands */
+#define EVMS_GET_DISK_LIST_STRING       "EVMS_GET_DISK_LIST"
+#define EVMS_GET_DISK_LIST              _IOWR(EVMS_MAJOR, EVMS_GET_DISK_LIST_NUMBER, evms_list_node_t **)
+
+#define EVMS_CHECK_MEDIA_CHANGE_STRING  "EVMS_CHECK_MEDIA_CHANGE"
+#define EVMS_CHECK_MEDIA_CHANGE         _IO(EVMS_MAJOR, EVMS_CHECK_MEDIA_CHANGE_NUMBER)
+
+#define EVMS_REVALIDATE_DISK_STRING     "EVMS_REVALIDATE_DISK"
+#define EVMS_REVALIDATE_DISK            _IO(EVMS_MAJOR, EVMS_REVALIDATE_DISK_NUMBER)
+
+#define EVMS_OPEN_VOLUME_STRING         "EVMS_OPEN_VOLUME"
+#define EVMS_OPEN_VOLUME                _IO(EVMS_MAJOR, EVMS_OPEN_VOLUME_NUMBER)
+
+#define EVMS_CLOSE_VOLUME_STRING        "EVMS_CLOSE_VOLUME"
+#define EVMS_CLOSE_VOLUME               _IO(EVMS_MAJOR, EVMS_CLOSE_VOLUME_NUMBER)
+
+/* field: command: defines */
+#define EVMS_UNQUIESCE          0
+#define EVMS_QUIESCE            1
+
+/* field: do_vfs: defines */
+/* see evms_delete_volume */
+typedef struct evms_quiesce_volume_s {
+	int             command;		/* 0 = unquiesce, 1 = quiesce */
+	int             minor;			/* minor device number of target volume */
+	int             do_vfs;			/* 0 = do nothing, 1 = also perform equivalent VFS operation */
+	int             status;			/* 0 = success */
+} evms_quiesce_volume_t;
+
+#define EVMS_QUIESCE_VOLUME_STRING      "EVMS_QUIESCE_VOLUME"
+#define EVMS_QUIESCE_VOLUME             _IOR(EVMS_MAJOR, EVMS_QUIESCE_VOLUME_NUMBER, evms_quiesce_volume_t)
+
+#define EVMS_CHECK_DEVICE_STATUS_STRING	"EVMS_CHECK_DEVICE_STATUS"
+#define EVMS_CHECK_DEVICE_STATUS        _IOR(EVMS_MAJOR, EVMS_CHECK_DEVICE_STATUS_NUMBER, int)
+
+#endif
+
+/* configuration commands */
+#define EVMS_GET_INFO_LEVEL_STRING      "EVMS_GET_INFO_LEVEL"
+#define EVMS_GET_INFO_LEVEL             _IOR(EVMS_MAJOR, EVMS_GET_INFO_LEVEL_NUMBER, int)
+
+#define EVMS_SET_INFO_LEVEL_STRING      "EVMS_SET_INFO_LEVEL"
+#define EVMS_SET_INFO_LEVEL             _IOW(EVMS_MAJOR, EVMS_SET_INFO_LEVEL_NUMBER, int)
+
+/* field: drive_count: defines */
+#define REDISCOVER_ALL_DEVICES          0xFFFFFFFF
+typedef struct evms_rediscover_s {
+	int             status;
+	unsigned int    drive_count;		/* 0xffffffff = rediscover all known disks */
+	unsigned long  *drive_array;
+} evms_rediscover_t;
+
+#define EVMS_REDISCOVER_VOLUMES_STRING  "EVMS_REDISCOVER_VOLUMES"
+#define EVMS_REDISCOVER_VOLUMES         _IOWR(EVMS_MAJOR, EVMS_REDISCOVER_VOLUMES_NUMBER, evms_rediscover_t)
+
+/* field: command: defines */
+#define EVMS_SOFT_DELETE        0
+#define EVMS_HARD_DELETE        1
+
+/* field: do_vfs: defines */
+#define EVMS_VFS_DO_NOTHING     0
+#define EVMS_VFS_DO             1
+typedef struct evms_delete_volume_s {
+	int             command;		/* 0 = "temp", 1 = "permanent" */
+	int             minor;			/* minor device number of target volume */
+	int             do_vfs;			/* 0 = do nothing, 1 = perform VFS operations */
+	int             associative_minor;	/* optional minor of associative volume */
+						/* must be 0 when not in use */
+	int             status;			/* 0 = success, other is error */
+} evms_delete_volume_t;
+
+#define EVMS_DELETE_VOLUME_STRING       "EVMS_DELETE_VOLUME"
+#define EVMS_DELETE_VOLUME              _IOR(EVMS_MAJOR, EVMS_DELETE_VOLUME_NUMBER, evms_delete_volume_t)
+
+typedef struct evms_plugin_ioctl_s {
+	unsigned long   feature_id;		/* ID of feature to receive this ioctl */
+	int             feature_command;	/* feature specific ioctl command      */
+	int             status;			/* 0 = completed, non-0 = error        */
+	void           *feature_ioctl_data;	/* ptr to feature specific struct      */
+} evms_plugin_ioctl_t;
+
+#define EVMS_PLUGIN_IOCTL_STRING        "EVMS_PLUGIN_IOCTL"
+#define EVMS_PLUGIN_IOCTL               _IOR(EVMS_MAJOR, EVMS_PLUGIN_IOCTL_NUMBER, evms_plugin_ioctl_t)
+
+/* field: eventid: defines */
+#define EVMS_EVENT_END_OF_DISCOVERY     0
+typedef struct evms_event_s {
+	int     pid;				/* PID to act on */
+	int     eventid;			/* event id to respond to */
+	int     signo;				/* signal # to send when event occurs */
+} evms_event_t;
+
+/* field: command: defines */
+#define EVMS_EVENT_UNREGISTER   0
+#define EVMS_EVENT_REGISTER     1
+typedef struct evms_notify_s {
+	int             command;		/* 0 = unregister, 1 = register */
+	evms_event_t    eventry;		/* event structure */
+	int             status;			/* return status */
+} evms_notify_t;
+
+#define EVMS_PROCESS_NOTIFY_EVENT_STRING "EVMS_PROCESS_NOTIFY_EVENT"
+#define EVMS_PROCESS_NOTIFY_EVENT       _IOWR(EVMS_MAJOR, EVMS_PROCESS_NOTIFY_EVENT_NUMBER, evms_notify_t)
+
+/* query info commands */
+
+/* field: command: defines */
+#define EVMS_FIRST_DISK         0
+#define EVMS_NEXT_DISK          1
+
+/* field: status: defines */
+#define EVMS_DISK_INVALID       0
+#define EVMS_DISK_VALID         1
+typedef struct evms_user_disk_s {
+	int             command;		/* 0 = first disk, 1 = next disk */
+	int             status;			/* 0 = no more disks, 1 = valid disk info */
+	unsigned long   disk_handle;		/* only valid when status == 1 */
+} evms_user_disk_t;
+
+#define EVMS_GET_LOGICAL_DISK_STRING    "EVMS_GET_LOGICAL_DISK"
+#define EVMS_GET_LOGICAL_DISK           _IOWR(EVMS_MAJOR, EVMS_GET_LOGICAL_DISK_NUMBER, evms_user_disk_t)
+
+/* flags fields described in evms_common.h */
+typedef struct evms_user_disk_info_s {
+	unsigned int    status;
+	unsigned int    flags;
+	unsigned long   disk_handle;
+	unsigned int    disk_dev;
+	struct hd_geometry geometry;
+	unsigned int    block_size;
+	unsigned int    hardsect_size;
+	u_int64_t       total_sectors;
+	char            disk_name[EVMS_VOLUME_NAME_SIZE];
+} evms_user_disk_info_t;
+
+#define EVMS_GET_LOGICAL_DISK_INFO_STRING "EVMS_GET_LOGICAL_DISK_INFO"
+#define EVMS_GET_LOGICAL_DISK_INFO      _IOWR(EVMS_MAJOR, EVMS_GET_LOGICAL_DISK_INFO_NUMBER, evms_user_disk_info_t)
+
+/* field: io_flag: defines */
+#define EVMS_SECTOR_IO_READ	0
+#define EVMS_SECTOR_IO_WRITE	1
+typedef struct evms_sector_io_s {
+	unsigned long   disk_handle;		/* valid disk handle */
+	int             io_flag;		/* 0 = READ, 1 = WRITE */
+	evms_sector_t   starting_sector;	/* disk relative LBA */
+	evms_sector_t   sector_count;		/* number of sectors in IO */
+	unsigned char  *buffer_address;		/* IO address */
+	int             status;			/* 0 = success, not 0 = error */
+} evms_sector_io_t;
+
+#define EVMS_SECTOR_IO_STRING           "EVMS_SECTOR_IO"
+#define EVMS_SECTOR_IO                  _IOWR(EVMS_MAJOR, EVMS_SECTOR_IO_NUMBER, evms_sector_io_t)
+
+/* field: command: defines */
+#define EVMS_FIRST_VOLUME       0
+#define EVMS_NEXT_VOLUME        1
+
+/* field: status: defines */
+#define EVMS_VOLUME_INVALID     0
+#define EVMS_VOLUME_VALID       1
+typedef struct evms_user_minor_s {
+	int             command;		/* 0 = first volume, 1 = next volume */
+	int             status;			/* 0 = no more, 1 = valid info */
+	int             minor;			/* only valid when status == 1 */
+} evms_user_minor_t;
+
+#define EVMS_GET_MINOR_STRING           "EVMS_GET_MINOR"
+#define EVMS_GET_MINOR                  _IOWR(EVMS_MAJOR, EVMS_GET_MINOR_NUMBER, evms_user_minor_t)
+
+/* flags field described in evms_common.h */
+typedef struct evms_volume_data_s {
+	int             minor;			/* minor of target volume */
+	int             flags;
+	char            volume_name[EVMS_VOLUME_NAME_SIZE + 1];
+	int             status;
+} evms_volume_data_t;
+
+#define EVMS_GET_VOLUME_DATA_STRING     "EVMS_GET_VOLUME_DATA"
+#define EVMS_GET_VOLUME_DATA            _IOWR(EVMS_MAJOR, EVMS_GET_VOLUME_DATA_NUMBER, evms_volume_data_t)
+
+/* field: command: defines */
+#define EVMS_FIRST_PLUGIN       0
+#define EVMS_NEXT_PLUGIN        1
+
+/* field: status: defines */
+#define EVMS_PLUGIN_INVALID     0
+#define EVMS_PLUGIN_VALID       1
+typedef struct evms_kernel_plugin_s {
+	int             command;		/* 0 = first item, 1 = next item */
+	u_int32_t       id;			/* returned plugin id */
+	evms_version_t  version;		/* maj,min,patch of plugin */
+	int             status;			/* 0 = no more, 1 = valid info */
+} evms_kernel_plugin_t;
+
+#define EVMS_GET_PLUGIN_STRING          "EVMS_GET_PLUGIN"
+#define EVMS_GET_PLUGIN                 _IOWR(EVMS_MAJOR, EVMS_GET_PLUGIN_NUMBER, evms_kernel_plugin_t)
+
+typedef struct evms_compute_csum_s {
+	unsigned char  *buffer_address;		/* IO address */
+	int             buffer_size;		/* byte size of buffer */
+	unsigned int    insum;			/* previous csum to be factored in */
+	unsigned int    outsum;			/* resulting csum value of buffer */
+	int             status;			/* 0 = success, not 0 = error */
+} evms_compute_csum_t;
+
+#define EVMS_COMPUTE_CSUM_STRING        "EVMS_COMPUTE_CSUM"
+#define EVMS_COMPUTE_CSUM               _IOWR(EVMS_MAJOR, EVMS_COMPUTE_CSUM_NUMBER, evms_compute_csum_t)
+
+typedef struct evms_get_bmap_s {
+	u_int64_t       rsector;		/* input: volume relative rsector value */
+						/* output: disk relative rsector value */
+	u_int32_t       dev;			/* output = physical device */
+	int             status;			/* 0 = success, not 0 = error */
+} evms_get_bmap_t;
+
+#define EVMS_GET_BMAP_STRING            "EVMS_GET_BMAP"
+#define EVMS_GET_BMAP                   _IOWR(EVMS_MAJOR, EVMS_GET_BMAP_NUMBER, evms_get_bmap_t)
+
+#endif
diff --git a/lib/evms/evms_user.h b/lib/evms/evms_user.h
new file mode 100644
index 0000000..cd13a81
--- /dev/null
+++ b/lib/evms/evms_user.h
@@ -0,0 +1,28 @@
+/* -*- linux-c -*- */
+/*
+ *
+ *   Copyright (c) International Business Machines  Corp., 2000
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or 
+ *   (at your option) any later version.
+ * 
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software 
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * linux/include/linux/evms_user.h
+ *
+ * EVMS (master) user header file
+ *
+ */
+
+#include <evms/evms_common.h>
+#include <evms/evms_ioctl.h>
diff --git a/lib/evms/fs_ext2.c b/lib/evms/fs_ext2.c
new file mode 100644
index 0000000..baa954f
--- /dev/null
+++ b/lib/evms/fs_ext2.c
@@ -0,0 +1,1141 @@
+/*
+ *
+ *   Copyright (c) International Business Machines  Corp., 2000
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *   Module: fs_ext2.c
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <plugin.h>
+#include "fsimext2.h"
+
+static plugin_record_t    *pMyPluginRecord = &ext2_plugrec;
+
+/*-------------------------------------------------------------------------------------+
++                                                                                      +
++                            Start Of EVMS Plugin Functions                            +
++                        (exported to engine via function table)                       +
++                                                                                      +
++-------------------------------------------------------------------------------------*/
+
+
+static int fs_setup( engine_mode_t mode, engine_functions_t *engine_function_table)
+{
+    int rc = 0;
+	EngFncs = engine_function_table;
+
+	LOGENTRY();
+
+    /*
+     * We don't really care about the e2fsprogs version, but we leave
+     * this here in case we do at a later date....
+     */
+    rc = fsim_test_version();
+    if ( rc ) {
+        MESSAGE( "e2fsprogs must be version 1.XXX or later to function properly with this FSIM." );
+        MESSAGE( "Please get the current version of e2fsprogs from http://e2fsprogs.sourceforge.net" );
+        rc = ENOSYS;
+    }
+     
+	LOGEXIT();
+	return rc;
+}
+
+
+/*
+ * Free all of the private data item we have left on volumes.
+ */
+static void fs_cleanup()
+{
+	int rc = 0;
+	dlist_t global_volumes;
+	logical_volume_t * volume;
+	LOGENTRY();
+
+	rc = EngFncs->get_volume_list(pMyPluginRecord, &global_volumes);
+	if (!rc) {
+		while (ExtractObject(global_volumes, sizeof(logical_volume_t), VOLUME_TAG, NULL, (void**)&volume)==0) {
+			if (volume->private_data) {
+				EngFncs->engine_free(volume->private_data);
+			}
+		}
+	}
+	LOGEXIT();
+}
+
+
+/*
+ * Does this FSIM manage the file system on this volume?
+ * Return 0 for "yes", else a reason code.
+ */
+static int fs_probe(logical_volume_t * volume)
+{
+	int  rc = 0;
+	struct ext2_super_block *sb_ptr;
+
+	LOGENTRY();
+
+    /* allocate space for copy of superblock in private data */
+    sb_ptr = EngFncs->engine_alloc( SIZE_OF_SUPER );
+
+    if ( sb_ptr ) {
+        memset( (void *) sb_ptr, 0, SIZE_OF_SUPER );
+
+        /* get and validate ext2 superblock */
+        rc = fsim_get_ext2_superblock( volume, sb_ptr );
+
+        if ( !rc ) {
+            /* store copy of valid EXT2/3 superblock in private data */
+            volume->private_data = (void*)sb_ptr;
+        } else {
+            /* could not get valid EXT2/3 superblock */
+            volume->private_data = NULL;
+        }
+    } else {
+        rc = ENOMEM;
+    }
+
+	LOGEXITRC();
+	return rc;
+}
+
+
+/*
+ * Can mkfs this volume?
+ */
+static int fs_can_mkfs(logical_volume_t * volume)
+{
+	int  rc=0;
+
+	LOGENTRY();
+
+    /*****************************************************
+     *  FUTURE - ensure mke2fs exists                    *
+     *****************************************************/
+
+	if (EVMS_IS_MOUNTED(volume)) {
+		/* If mounted, can't format. */
+		rc = EBUSY;
+	} else if ((volume->vol_size * PBSIZE) < MINEXT2) {
+		/* voluem size must be >= MINEXT2 */
+		rc = EPERM;
+    }
+
+	LOGEXITRC();
+	return rc;
+}
+
+
+/*
+ * Can unmkfs this volume?
+ */
+static int fs_can_unmkfs(logical_volume_t * volume)
+{
+	int  rc=0;
+
+	LOGENTRY();
+
+	if (EVMS_IS_MOUNTED(volume)) {
+		/* If mounted, can't unmkfs. */
+		rc = EBUSY;
+	}
+
+	LOGEXITRC();
+	return rc;
+
+}
+
+
+/*
+ * Can fsck this volume?
+ */
+static int fs_can_fsck(logical_volume_t * volume)
+{
+	int  rc=0;
+
+	LOGENTRY();
+
+    /*****************************************************
+     *  FUTURE - ensure e2fsck exists                    *
+     *           match version with available functions  *
+     *****************************************************/
+
+	LOGEXITRC();
+	return rc;
+}
+
+
+/*
+ * Get the current size of this volume
+ */
+static int fs_get_fs_size( logical_volume_t * volume,
+            			   sector_count_t   * size    )
+{
+	int  rc = EINVAL;
+	struct ext2_super_block *sb = (struct ext2_super_block *)volume->private_data;
+
+	LOGENTRY();
+
+	if (!sb) {
+		LOGEXITRC();
+		return rc;
+	}
+
+    /* get and validate current ext2/3 superblock */
+    rc = fsim_get_ext2_superblock( volume, sb );
+
+    if (!rc && sb) {
+		*size = sb->s_blocks_count << (1 + sb->s_log_block_size);
+		rc = 0;
+	}
+
+	LOGEXITRC();
+	return rc;
+}
+
+
+/*
+ * Get the size limits for this volume.
+ */
+static int fs_get_fs_limits( logical_volume_t * volume,
+               				 sector_count_t   * min_size,
+               				 sector_count_t   * max_volume_size,
+               				 sector_count_t   * max_object_size)
+{
+	int rc = EINVAL;
+	struct ext2_super_block *sb_ptr = (struct ext2_super_block *) volume->private_data;
+
+	LOGENTRY();
+
+	if (!sb_ptr) {
+		LOGEXITRC();
+		return rc;
+	}
+
+    /* get and validate current ext2 superblock */
+    rc = fsim_get_ext2_superblock( volume, sb_ptr );
+    
+    if ( !rc ) {
+	    rc = fsim_get_volume_limits( sb_ptr, min_size, max_volume_size, max_object_size);
+	    LOG_EXTRA("volume:%s, min:%lld, max:%lld\n",EVMS_GET_DEVNAME(volume), *min_size, *max_volume_size);
+	    LOG_EXTRA("fssize:%lld, vol_size:%lld\n",volume->fs_size,volume->vol_size );
+
+	    if (*min_size > volume->vol_size) {
+		    LOG_ERROR("EXT2 FSIM returned min size > volume size, setting min size to volume size\n");
+		    *min_size = volume->vol_size;
+	    }
+    }
+
+	LOGEXITRC();
+	return rc;
+}
+
+
+/*
+ * Expand the volume to new_size.  If the volume is not expanded exactly to
+ * new_size, set new_sie to the new_size of the volume.
+ */
+static int fs_expand( logical_volume_t * volume,
+		              sector_count_t   * new_size )
+{
+    /* unsupported at this time */
+	int  rc = ENOSYS;
+
+	LOGENTRY();
+	LOGEXITRC();
+	return rc;
+}
+
+
+/*
+ * "unmkfs" the volume
+ */
+static int fs_unmkfs(logical_volume_t * volume)
+{
+	int rc = EINVAL;
+	LOGENTRY();
+
+	if (EVMS_IS_MOUNTED(volume)) {
+		/* If mounted, can't unmkfs. */
+		rc = EBUSY;
+	} else if ( (rc = fsim_unmkfs(volume)) == FSIM_SUCCESS ){
+	    volume->private_data = NULL;
+	}
+    
+	LOGEXITRC();
+	return rc;
+}
+
+
+/*
+ * Shrink the volume to new_size.  If the volume is not expanded exactly to
+ * new_size, set new_size to the new_size of the volume.
+ */
+static int fs_shrink( logical_volume_t * volume,
+        		      sector_count_t     requested_size,
+		              sector_count_t   * new_size )
+{
+    /* unsupported at this time */
+	int  rc = ENOSYS;
+
+	LOGENTRY();
+	LOGEXITRC();
+	return rc;
+}
+
+
+
+/*
+ * Format the volume.
+ */
+static int fs_mkfs(logical_volume_t * volume, option_array_t * options )
+{
+	int  rc = 0;
+
+	LOGENTRY();
+
+    /* don't format if mounted */
+	if (EVMS_IS_MOUNTED(volume)) {
+		return EBUSY;
+	}
+
+    rc = fsim_mkfs(volume, options);
+
+    /* probe to set up private data */
+    if ( !rc ) {
+        rc = fs_probe(volume);
+    }
+
+	LOGEXITRC();
+	return rc;
+}
+
+
+/*
+ * Run fsck on the volume.
+ */
+static int fs_fsck(logical_volume_t * volume, option_array_t * options )
+{
+	int rc = EINVAL;
+
+	LOGENTRY();
+
+	rc = fsim_fsck( volume, options );
+
+    /*
+     * If fsck.ext2 returns FSCK_CORRECTED, the
+     * file system is clean, so return FSCK_OK.
+     */
+    if ( rc == FSCK_CORRECTED ) {
+        rc = FSCK_OK;
+    /*
+     * The value of FSCK_CORRECTED is the same as
+     * EPERM, so fsim_fsck will return -1 for EPERM.
+     */
+    } else if (rc == -1) {
+        rc = EPERM;
+    }
+
+    /*
+     * If the volume is mounted, e2fsck checked READ ONLY 
+     * regardless of options specified.  If the check was READ ONLY
+     * and errors were found, let the user know how to fix them.
+     */
+    if (EVMS_IS_MOUNTED(volume) && rc) {
+        MESSAGE( "%s is mounted.", EVMS_GET_DEVNAME(volume) );
+        MESSAGE( "e2fsck checked the volume READ ONLY and found, but did not fix, errors." );
+        MESSAGE( "Unmount %s and run e2fsck again to repair the file system.", EVMS_GET_DEVNAME(volume) );
+    }
+
+	LOGEXITRC();
+	return rc;
+}
+
+
+/*
+ * Return the total number of supported options for the specified task.
+ */
+static int fs_get_option_count(task_context_t * context)
+{
+    int count = 0;
+
+	LOGENTRY();
+
+	switch(context->action) {
+	    case EVMS_Task_mkfs:
+		    count = MKFS_EXT2_OPTIONS_COUNT;
+		    break;
+	    case EVMS_Task_fsck:
+		    count = FSCK_EXT2_OPTIONS_COUNT;
+		    break;
+	    default:
+		    count = -1;
+		    break;
+	}
+
+	LOGEXIT();
+	return count;
+}
+
+
+/*
+ * Fill in the initial list of acceptable objects.  Fill in the minimum and
+ * maximum nuber of objects that must/can be selected.  Set up all initial
+ * values in the option_descriptors in the context record for the given
+ * task.  Some fields in the option_descriptor may be dependent on a
+ * selected object.  Leave such fields blank for now, and fill in during the
+ * set_objects call.
+ */
+static int fs_init_task( task_context_t * context )
+{
+	dlist_t global_volumes;
+	logical_volume_t * volume;
+	void* waste;
+	int size, tag;
+	int  rc = 0;
+	option_descriptor_t	*opt;
+	
+	LOGENTRY();
+
+	context->min_selected_objects = 0;
+	context->max_selected_objects = 1;
+	context->option_descriptors->count = 0;
+
+	/* Parameter check */
+	if (!context) {
+		return EFAULT;
+	}
+
+	rc = EngFncs->get_volume_list(NULL, &global_volumes);
+
+	while (!(rc = BlindExtractObject(global_volumes, &size, (TAG *)&tag, NULL, (void **)&volume))) {
+
+		switch (context->action) {
+		case EVMS_Task_mkfs:
+			/* only mkfs unformatted volumes */
+			if (volume->file_system_manager == NULL) {
+				rc = InsertObject(context->acceptable_objects, sizeof(logical_volume_t), volume, VOLUME_TAG, NULL, InsertAtStart, TRUE, (void **)&waste);
+			}
+			break;
+
+		case EVMS_Task_fsck:					 
+			/* only fsck our stuff */
+			if (volume->file_system_manager == &ext2_plugrec) {
+				rc = InsertObject(context->acceptable_objects, sizeof(logical_volume_t), volume, VOLUME_TAG, NULL, InsertAtStart, TRUE, (void **)&waste);
+			}
+			break;
+
+		default:
+			rc = ENOSYS;
+			break;
+		}
+	}
+
+	if (rc == DLIST_EMPTY || rc == DLIST_END_OF_LIST) {
+		rc = 0;
+	}
+
+	switch (context->action) {
+	
+	case EVMS_Task_mkfs:
+
+		context->option_descriptors->count = MKFS_EXT2_OPTIONS_COUNT;
+
+		/* check for bad blocks option */
+		opt = &context->option_descriptors->option[MKFS_CHECKBB_INDEX];
+		SET_STRING(opt->name, "badblocks" );
+		SET_STRING(opt->title, "Check For Bad Blocks" );
+		SET_STRING(opt->tip, "Check the volume for bad blocks before building the file system." );
+		opt->help = NULL;
+		opt->type = EVMS_Type_Boolean;
+		opt->unit = EVMS_Unit_None;
+#ifdef ABI_EVMS_1_0
+		opt->size = 0;
+#endif
+		opt->flags = EVMS_OPTION_FLAGS_NOT_REQUIRED;
+		opt->constraint_type = EVMS_Collection_None;
+		opt->value.bool = FALSE;
+
+		/* check for r/w bad blocks option */
+		opt = &context->option_descriptors->option[MKFS_CHECKRW_INDEX];
+		SET_STRING(opt->name, "badblocks_rw" );
+		SET_STRING(opt->title, "RW Check For Bad Blocks" );
+		SET_STRING(opt->tip, "Do a read/write check for bad blocks before building the file system." );
+		opt->help = NULL;
+		opt->type = EVMS_Type_Boolean;
+		opt->unit = EVMS_Unit_None;
+#ifdef ABI_EVMS_1_0
+		opt->size = 0;
+#endif
+		opt->flags = EVMS_OPTION_FLAGS_NOT_REQUIRED;
+		opt->constraint_type = EVMS_Collection_None;
+		opt->value.bool = FALSE;
+
+		/* Set Volume Label option */
+		opt = &context->option_descriptors->option[MKFS_SETVOL_INDEX];
+		SET_STRING(opt->name, "vollabel" );
+		SET_STRING(opt->title, "Volume Label" );
+		SET_STRING(opt->tip, "Set the volume label for the file system." );
+		opt->help = NULL;
+		opt->type = EVMS_Type_String;
+		opt->unit = EVMS_Unit_None;
+#ifdef ABI_EVMS_1_0
+		opt->size = 16;
+#else
+		opt->min_len = 0;
+		opt->max_len = 16;
+#endif
+		opt->flags = EVMS_OPTION_FLAGS_NOT_REQUIRED | EVMS_OPTION_FLAGS_NO_INITIAL_VALUE;
+		opt->constraint_type = EVMS_Collection_None;
+		opt->value.s = EngFncs->engine_alloc(17);
+		if (opt->value.s == NULL) {
+			LOGEXIT();
+			return ENOMEM;
+		}
+
+		/* create ext3 journal option */
+		opt = &context->option_descriptors->option[MKFS_JOURNAL_INDEX];
+		SET_STRING(opt->name, "journal" );
+		SET_STRING(opt->title, "Create Ext3 Journal" );
+		SET_STRING(opt->tip, "Create a journal for use with the ext3 file system." );
+		opt->help = NULL;
+		opt->type = EVMS_Type_Boolean;
+		opt->unit = EVMS_Unit_None;
+#ifdef ABI_EVMS_1_0
+		opt->size = 0;
+#endif
+		opt->flags = EVMS_OPTION_FLAGS_NOT_REQUIRED;
+		opt->constraint_type = EVMS_Collection_None;
+		opt->value.bool = TRUE;
+
+		break;
+
+	case EVMS_Task_fsck:
+
+		context->option_descriptors->count = FSCK_EXT2_OPTIONS_COUNT;
+
+		/* force check option */
+		opt = &context->option_descriptors->option[FSCK_FORCE_INDEX];
+		SET_STRING(opt->name, "force" );
+		SET_STRING(opt->title, "Force Check" );
+		SET_STRING(opt->tip, "Force complete file system check." );
+		opt->help = NULL;
+		opt->type = EVMS_Type_Boolean;
+		opt->unit = EVMS_Unit_None;
+#ifdef ABI_EVMS_1_0
+		opt->size = 0;
+#endif
+		opt->flags = EVMS_OPTION_FLAGS_NOT_REQUIRED;
+		opt->constraint_type = EVMS_Collection_None;
+		opt->value.bool = FALSE;
+
+		/* read-only check option */
+		opt = &context->option_descriptors->option[FSCK_READONLY_INDEX];
+		SET_STRING(opt->name, "readonly" );
+		SET_STRING(opt->title, "Check Read-Only" );
+		SET_STRING(opt->tip, "Check the file system READ ONLY.  Report but do not correct errors." );
+		opt->help = NULL;
+		opt->type = EVMS_Type_Boolean;
+		opt->unit = EVMS_Unit_None;
+#ifdef ABI_EVMS_1_0
+		opt->size = 0;
+#endif
+		opt->flags = EVMS_OPTION_FLAGS_NOT_REQUIRED;
+		opt->constraint_type = EVMS_Collection_None;
+		/* if volume is mounted, only possible fsck.ext2 options is READONLY */
+		if (EVMS_IS_MOUNTED(context->volume)) {
+			opt->value.bool = TRUE;
+		} else {
+			opt->value.bool = FALSE;
+		}
+
+		/* check for bad blocks option */
+		opt = &context->option_descriptors->option[FSCK_CHECKBB_INDEX];
+		SET_STRING(opt->name, "badblocks" );
+		SET_STRING(opt->title, "Check For Bad Blocks" );
+		SET_STRING(opt->tip, "Check for bad blocks and mark them as busy." );
+		opt->help = NULL;
+#ifdef ABI_EVMS_1_0
+		opt->size = 0;
+#endif
+		opt->type = EVMS_Type_Boolean;
+		opt->unit = EVMS_Unit_None;
+		if (EVMS_IS_MOUNTED(context->volume)) {
+			opt->flags = EVMS_OPTION_FLAGS_INACTIVE;
+		} else {
+			opt->flags = EVMS_OPTION_FLAGS_NOT_REQUIRED;
+		}
+		opt->constraint_type = EVMS_Collection_None;
+		opt->value.bool = FALSE;
+
+		/* check for r/w bad blocks option */
+		opt = &context->option_descriptors->option[FSCK_CHECKRW_INDEX];
+		SET_STRING(opt->name, "badblocks_rw" );
+		SET_STRING(opt->title, "RW Check For Bad Blocks" );
+		SET_STRING(opt->tip, "Do a read/write check for bad blocks and mark them as busy." );
+		opt->help = NULL;
+		opt->type = EVMS_Type_Boolean;
+		opt->unit = EVMS_Unit_None;
+#ifdef ABI_EVMS_1_0
+		opt->size = 0;
+#endif
+		if (EVMS_IS_MOUNTED(context->volume)) {
+			opt->flags = EVMS_OPTION_FLAGS_INACTIVE;
+		} else {
+			opt->flags = EVMS_OPTION_FLAGS_NOT_REQUIRED;
+		}
+		opt->constraint_type = EVMS_Collection_None;
+		opt->value.bool = FALSE;
+
+		/* timing option */
+		opt = &context->option_descriptors->option[FSCK_TIMING_INDEX];
+		SET_STRING(opt->name, "timing" );
+		SET_STRING(opt->title, "Timing Statistics" );
+		SET_STRING(opt->tip, "Print timing statistics." );
+		opt->help = NULL;
+		opt->type = EVMS_Type_Boolean;
+		opt->unit = EVMS_Unit_None;
+#ifdef ABI_EVMS_1_0
+		opt->size = 0;
+#endif
+		opt->flags = EVMS_OPTION_FLAGS_NOT_REQUIRED | EVMS_OPTION_FLAGS_INACTIVE;
+		opt->constraint_type = EVMS_Collection_None;
+		opt->value.bool = FALSE;
+		break;
+
+	default:
+		break;
+	}
+
+	LOGEXITRC();
+
+	return rc;
+
+}
+
+
+/*
+ * Examine the specified value, and determine if it is valid for the task
+ * and option_descriptor index. If it is acceptable, set that value in the
+ * appropriate entry in the option_descriptor. The value may be adjusted
+ * if necessary/allowed. If so, set the effect return value accordingly.
+ */
+static int fs_set_option( task_context_t * context,
+			              u_int32_t        index,
+			              value_t        * value,
+			              task_effect_t  * effect )
+{
+	int  rc= 0, other;
+
+	LOGENTRY();
+
+	/* Parameter check */
+	if (!context || !value || !effect) {
+		return EFAULT;
+	}
+
+	*effect = 0;
+
+	switch (context->action) {
+	
+	case EVMS_Task_mkfs:
+		switch (index) {
+		
+		case MKFS_CHECKBB_INDEX:
+		case MKFS_CHECKRW_INDEX:
+			/* Conflicts with each other */
+			if (index == MKFS_CHECKBB_INDEX)
+				other = MKFS_CHECKRW_INDEX;
+			else
+				other = MKFS_CHECKBB_INDEX;
+			if (context->option_descriptors->option[other].value.bool) {
+				context->option_descriptors->option[other].value.bool = FALSE;
+				*effect = EVMS_Effect_Reload_Options;
+			}
+			/* Fall through */
+			
+		case MKFS_JOURNAL_INDEX:
+			context->option_descriptors->option[index].value.bool = value->bool;
+			break;
+
+		case MKFS_SETVOL_INDEX:
+			/* 'set volume label' option set? */
+			strncpy(context->option_descriptors->option[index].value.s, value->s, 16);
+			break;
+
+		default:
+			break;
+        }
+        break;
+
+    case EVMS_Task_fsck:
+        switch (index) {
+
+        case FSCK_READONLY_INDEX:
+            /* 'check read only' option set? */
+            context->option_descriptors->option[index].value.bool = value->bool;
+
+            /* If mounted, only allow 'yes' for check read only */
+	    if (EVMS_IS_MOUNTED(context->volume) && !value->bool) {
+                context->option_descriptors->option[index].value.bool = TRUE;
+                *effect = EVMS_Effect_Reload_Options;
+            }
+
+	    /* If read-only, we can't check for bad blocks */
+	    if (context->option_descriptors->option[FSCK_CHECKBB_INDEX].value.bool ||
+		context->option_descriptors->option[FSCK_CHECKRW_INDEX].value.bool) {
+ 		    context->option_descriptors->option[FSCK_CHECKBB_INDEX].value.bool = FALSE;
+ 		    context->option_descriptors->option[FSCK_CHECKRW_INDEX].value.bool = FALSE;
+		    *effect = EVMS_Effect_Reload_Options;
+		    break;
+	    }
+	    
+	    break;
+
+	case FSCK_CHECKBB_INDEX:
+        case FSCK_CHECKRW_INDEX:
+	    if (EVMS_IS_MOUNTED(context->volume) && value->bool) {
+                MESSAGE("Can't check for bad blocks when the volume is mounted.");
+                context->option_descriptors->option[index].value.bool = FALSE;
+                *effect = EVMS_Effect_Reload_Options;
+                break;
+            }
+
+	    /* Conflicts with each other */
+	    if (index == FSCK_CHECKBB_INDEX)
+		    other = FSCK_CHECKRW_INDEX;
+	    else
+		    other = FSCK_CHECKBB_INDEX;
+	    if (context->option_descriptors->option[other].value.bool) {
+ 		    context->option_descriptors->option[other].value.bool = FALSE;
+		    *effect = EVMS_Effect_Reload_Options;
+	    }
+	    
+	    /* Conflicts with read-only option */
+	    if (context->option_descriptors->option[FSCK_READONLY_INDEX].value.bool) {
+ 		    context->option_descriptors->option[FSCK_READONLY_INDEX].value.bool = FALSE;
+		    *effect = EVMS_Effect_Reload_Options;
+	    }
+	    
+	    /* Fall Through */
+
+        case FSCK_FORCE_INDEX:
+        case FSCK_TIMING_INDEX:
+            context->option_descriptors->option[index].value.bool = value->bool;
+
+	    break;
+
+        default:
+            break;
+        }
+        break;
+
+    default:
+        break;
+    }
+
+	LOGEXITRC();
+	return rc;
+}
+
+
+/*
+ * Validate the volumes in the selected_objects dlist in the task context.
+ * Remove from the selected objects lists any volumes which are not
+ * acceptable.  For unacceptable volumes, create a declined_handle_t
+ * structure with the reason why it is not acceptable, and add it to the
+ * declined_volumes dlist.  Modify the accepatble_objects dlist in the task
+ * context as necessary based on the selected objects and the current
+ * settings of the options.  Modify any option settings as necessary based
+ * on the selected objects.  Return the appropriate task_effect_t settings
+ * if the object list(s), minimum or maximum objects selected, or option
+ * settings have changed.
+ */
+static int fs_set_volumes( task_context_t * context,
+            			   dlist_t          declined_volumes,	 /* of type declined_handle_t */
+			               task_effect_t  * effect )
+{
+	int  rc = 0;
+    int64_t  log_size;
+    unsigned int  max_log_size;
+    logical_volume_t * vol;
+
+	LOGENTRY();
+
+	if (effect)
+		*effect = 0;
+
+	if (context->action == EVMS_Task_mkfs) {
+	
+        /* get the selected volume */
+        rc = GetObject(context->selected_objects,sizeof(logical_volume_t),VOLUME_TAG,NULL,FALSE,(ADDRESS *) &vol);
+
+        if (!rc) {
+	    if (EVMS_IS_MOUNTED(vol)) {
+                /* If mounted, can't mkfs.ext2. */
+                rc = EBUSY;
+            } else {
+                if ( (vol->vol_size * PBSIZE) < MINEXT2) {
+                    
+                    /*****************************************************
+                     *  FUTURE - move this volume to unacceptable list   *
+                     *****************************************************/
+
+                    MESSAGE( "The size of volume %s is %d bytes.", EVMS_GET_DEVNAME(vol), vol->vol_size * PBSIZE );
+                    MESSAGE( "mke2fs requires a minimum of %u bytes to build the ext2/3 file system.", MINEXT2 );
+                    rc = EPERM;
+                }
+            }
+        }
+    }
+
+	LOGEXITRC();
+	return rc;
+}
+
+
+/*
+ * Return any additional information that you wish to provide about the
+ * volume.  The Engine privides an external API to get the information
+ * stored in the logical_volume_t.  This call is to get any other
+ * information about the volume that is not specified in the
+ * logical_volume_t.  Any piece of information you wish to provide must be
+ * in an extended_info_t structure.  Use the Engine's engine_alloc() to
+ * allocate the memory for the extended_info_t.  Also use engine_alloc() to
+ * allocate any strings that may go into the extended_info_t.  Then use
+ * engine_alloc() to allocate an extended_info_array_t with enough entries
+ * for the number of exteneded_info_t structures you are returning.  Fill
+ * in the array and return it in *info.
+ * If you have extended_info_t descriptors that themselves may have more
+ * extended information, set the EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE flag
+ * in the extended_info_t flags field.  If the caller wants more information
+ * about a particular extended_info_t item, this API will be called with a
+ * pointer to the sotrage_object_t and with a pointer to the name of the
+ * extended_info_t item.  In that case, return an extended_info_array_t with
+ * further information about the item.  Each of those items may have the
+ * EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE flag set if you desire.  It is your
+ * resposibility to give the items unique names so that you know which item
+ * the caller is asking additional information for.  If info_name is NULL,
+ * the caller just wants top level information about the object.
+ */
+static int fs_get_volume_info( logical_volume_t        * volume,
+            			       char                    * info_name,
+            			       extended_info_array_t * * info )
+{
+	int rc = EINVAL;
+	extended_info_array_t  *Info;
+	struct ext2_super_block      *sb_ptr = (struct ext2_super_block *)volume->private_data;
+
+
+	LOGENTRY();
+
+	if (!sb_ptr) {
+		LOGEXITRC();
+		return rc;
+	}
+
+    /* get and validate current ext2 superblock */
+	rc = fsim_get_ext2_superblock( volume, sb_ptr );
+
+	if (info_name || rc) {
+		rc = EINVAL;
+		goto errout;
+	}
+
+	/* reset limits. */
+	fs_get_fs_limits( volume, &volume->min_fs_size,
+			 &volume->max_vol_size, &volume->max_fs_size);
+
+	Info = EngFncs->engine_alloc( sizeof(extended_info_array_t) + ( 5 * sizeof(extended_info_t) ) );
+
+	if (!Info) {
+		rc = ENOMEM;
+		goto errout;
+	}
+
+	Info->count = 5;
+
+	SET_STRING_FIELD( Info->info[0].name, "Version" );
+	SET_STRING_FIELD( Info->info[0].title, "Ext2 Revision Number" );
+	SET_STRING_FIELD( Info->info[0].desc, "Ext2 Revision Number.");
+	Info->info[0].type               = EVMS_Type_Unsigned_Int32;
+	Info->info[0].unit               = EVMS_Unit_None;
+	Info->info[0].value.ui64         = sb_ptr->s_rev_level;
+	Info->info[0].collection_type    = EVMS_Collection_None;
+	memset( &Info->info[0].group, 0, sizeof(group_info_t));
+
+	SET_STRING_FIELD( Info->info[1].name, "State" );
+	SET_STRING_FIELD( Info->info[1].title, "Ext2 State" );
+	SET_STRING_FIELD( Info->info[1].desc, "The state of Ext2.");
+	Info->info[1].type               = EVMS_Type_String;
+	Info->info[1].unit               = EVMS_Unit_None;
+	if (sb_ptr->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
+                SET_STRING_FIELD(Info->info[1].value.s, "Needs journal replay");
+	} else if (sb_ptr->s_state & EXT2_ERROR_FS) {
+                SET_STRING_FIELD(Info->info[1].value.s, "Had errors");
+	} else if (sb_ptr->s_state & EXT2_VALID_FS) {
+                SET_STRING_FIELD(Info->info[1].value.s, "Clean");
+	} else {
+                SET_STRING_FIELD(Info->info[1].value.s, "Dirty");
+	}
+	Info->info[1].collection_type    = EVMS_Collection_None;
+	memset( &Info->info[1].group, 0, sizeof(group_info_t));
+
+	SET_STRING_FIELD( Info->info[2].name, "VolLabel" );
+	SET_STRING_FIELD( Info->info[2].title, "Volume Label" );
+	SET_STRING_FIELD( Info->info[2].desc, "File system volume label.");
+	Info->info[2].type               = EVMS_Type_String;
+	Info->info[2].unit               = EVMS_Unit_None;
+
+	Info->info[2].value.s = EngFncs->engine_alloc(17);
+	if (!Info->info[2].value.s)
+		return -ENOMEM;
+	Info->info[2].value.s[16] = 0;
+	memcpy(Info->info[2].value.s, sb_ptr->s_volume_name, 16);
+	Info->info[2].collection_type    = EVMS_Collection_None;
+	memset( &Info->info[2].group, 0, sizeof(group_info_t));
+
+	SET_STRING_FIELD( Info->info[3].name, "Size" );
+	SET_STRING_FIELD( Info->info[3].title, "File System Size" );
+	SET_STRING_FIELD( Info->info[3].desc, "Size of the file system.");
+	Info->info[3].type               = EVMS_Type_Unsigned_Int64;
+	Info->info[3].unit               = EVMS_Unit_Sectors;
+	Info->info[3].value.ui64         = sb_ptr->s_blocks_count <<
+		(1 + sb_ptr->s_log_block_size);
+	Info->info[3].collection_type    = EVMS_Collection_None;
+	memset( &Info->info[3].group, 0, sizeof(group_info_t));
+
+	SET_STRING_FIELD( Info->info[4].name, "FreeSpace" );
+	SET_STRING_FIELD( Info->info[4].title, "Free File System Space" );
+	SET_STRING_FIELD( Info->info[4].desc, "Amount of unused space in the file system.");
+	Info->info[4].type               = EVMS_Type_Unsigned_Int64;
+	Info->info[4].unit               = EVMS_Unit_Sectors;
+	Info->info[4].value.ui64         = sb_ptr->s_free_blocks_count <<
+		(1 + sb_ptr->s_log_block_size);
+	Info->info[3].collection_type    = EVMS_Collection_None;
+	memset( &Info->info[3].group, 0, sizeof(group_info_t));
+
+	*info = Info;
+	
+	rc = 0;
+
+errout:
+	LOGEXITRC();
+	return rc;
+}
+
+
+/*
+ *  Returns Plugin specific information ...
+ */
+static int fs_get_plugin_info( char * descriptor_name, extended_info_array_t * * info )
+{
+	int                      rc = EINVAL;
+	extended_info_array_t   *Info;
+	extended_info_t		*iptr;
+	char                     version_string[64];
+	char                     required_version_string[64];
+
+	LOGENTRY();
+
+	if (info) {
+
+		if (descriptor_name == NULL) {
+			*info = NULL;	  // init to no info returned
+
+			Info = EngFncs->engine_alloc( sizeof(extended_info_array_t) + (8*sizeof(extended_info_t))  );
+			if (Info) {
+
+				Info->count = 0;
+
+				sprintf(version_string, "%d.%d.%d",
+					MAJOR_VERSION,
+					MINOR_VERSION,
+					PATCH_LEVEL );
+
+				sprintf(required_version_string, "%d.%d.%d",
+					pMyPluginRecord->required_api_version.major,
+					pMyPluginRecord->required_api_version.minor,
+					pMyPluginRecord->required_api_version.patchlevel );
+
+				iptr = &Info->info[Info->count++];
+				SET_STRING_FIELD( iptr->name, "Short Name" );
+				SET_STRING_FIELD( iptr->title, "Short Name" );
+				SET_STRING_FIELD( iptr->desc, "A short name given to this plugin.");
+				iptr->type               = EVMS_Type_String;
+				iptr->unit               = EVMS_Unit_None;
+				SET_STRING_FIELD( iptr->value.s, pMyPluginRecord->short_name );
+				iptr->collection_type    = EVMS_Collection_None;
+				memset( &iptr->group, 0, sizeof(group_info_t));
+
+				iptr = &Info->info[Info->count++];
+				SET_STRING_FIELD( iptr->name, "Long Name" );
+				SET_STRING_FIELD( iptr->title, "Long Name" );
+				SET_STRING_FIELD( iptr->desc, "A long name given to this plugin.");
+				iptr->type               = EVMS_Type_String;
+				iptr->unit               = EVMS_Unit_None;
+				SET_STRING_FIELD( iptr->value.s, pMyPluginRecord->long_name );
+				iptr->collection_type    = EVMS_Collection_None;
+				memset( &iptr->group, 0, sizeof(group_info_t));
+
+				iptr = &Info->info[Info->count++];
+				SET_STRING_FIELD( iptr->name, "Type" );
+				SET_STRING_FIELD( iptr->title, "Plugin Type" );
+				SET_STRING_FIELD( iptr->desc, "There are various types of plugins; each responsible for some kind of storage object.");
+				iptr->type               = EVMS_Type_String;
+				iptr->unit               = EVMS_Unit_None;
+				SET_STRING_FIELD( iptr->value.s, "File System Interface Module" );
+				iptr->collection_type    = EVMS_Collection_None;
+				memset( &iptr->group, 0, sizeof(group_info_t));
+
+				iptr = &Info->info[Info->count++];
+				SET_STRING_FIELD( iptr->name, "Version" );
+				SET_STRING_FIELD( iptr->title, "Plugin Version" );
+				SET_STRING_FIELD( iptr->desc, "This is the version number of the plugin.");
+				iptr->type               = EVMS_Type_String;
+				iptr->unit               = EVMS_Unit_None;
+				SET_STRING_FIELD( iptr->value.s, version_string );
+				iptr->collection_type    = EVMS_Collection_None;
+				memset( &iptr->group, 0, sizeof(group_info_t));
+
+				iptr = &Info->info[Info->count++];
+				SET_STRING_FIELD( iptr->name, "Required Version" );
+				SET_STRING_FIELD( iptr->title, "Required Engine Version" );
+				SET_STRING_FIELD( iptr->desc, "This is the version of the engine that the plugin requires. It will not run on older versions of the Engine.");
+				iptr->type               = EVMS_Type_String;
+				iptr->unit               = EVMS_Unit_None;
+				SET_STRING_FIELD( iptr->value.s, required_version_string );
+				iptr->collection_type    = EVMS_Collection_None;
+				memset( &iptr->group, 0, sizeof(group_info_t));
+
+#ifdef VERSION
+				iptr = &Info->info[Info->count++];
+				SET_STRING_FIELD( iptr->name, "E2fsprogs Version" );
+				SET_STRING_FIELD( iptr->title, "E2fsprogs Version" );
+				SET_STRING_FIELD( iptr->desc, "This is the version of the e2fsprogs that this plugin was shipped with.");
+				iptr->type               = EVMS_Type_String;
+				iptr->unit               = EVMS_Unit_None;
+				SET_STRING_FIELD( iptr->value.s, VERSION );
+				iptr->collection_type    = EVMS_Collection_None;
+				memset( &iptr->group, 0, sizeof(group_info_t));
+#endif
+				
+				*info = Info;
+
+				rc = 0;
+			} else {
+				rc = ENOMEM;
+			}
+
+		} else {
+			/* There is no more information on any of the descriptors. */
+			rc = EINVAL;
+		}
+	}
+
+	LOGEXITRC();
+	return rc;
+}
+
+
+/*
+ * How much can file system expand?
+ */
+static int fs_can_expand_by(logical_volume_t * volume, 
+                            sector_count_t   * delta) 
+{
+    /* unsupported at this time */
+	int  rc = ENOSYS;
+
+	LOGENTRY();
+	LOGEXITRC();
+	return rc;
+
+}
+
+
+/*
+ * How much can file system shrink?
+ */
+static int fs_can_shrink_by(logical_volume_t * volume, 
+                            sector_count_t * delta) 
+{
+    /* unsupported at this time */
+	int  rc = ENOSYS;
+
+	LOGENTRY();
+	LOGEXITRC();
+	return rc;
+}
+
+
+/*-------------------------------------------------------------------------------------+
++                                                                                      +
++                                PLUGIN FUNCTION TABLE                                 +
++                                                                                      +
++--------------------------------------------------------------------------------------*/
+static fsim_functions_t  fsim_ops = {
+
+	setup_evms_plugin:  fs_setup,
+	cleanup_evms_plugin:fs_cleanup,
+	is_this_yours:      fs_probe,
+	can_mkfs:           fs_can_mkfs,
+	can_unmkfs:         fs_can_unmkfs,
+	can_fsck:           fs_can_fsck,
+	get_fs_size:        fs_get_fs_size,
+	get_fs_limits:      fs_get_fs_limits,
+	can_expand_by:      fs_can_expand_by,
+	can_shrink_by:      fs_can_shrink_by,
+	expand:             fs_expand,
+	shrink:             fs_shrink,
+	mkfs:               fs_mkfs,
+	fsck:               fs_fsck,
+	unmkfs:		        fs_unmkfs,
+	get_option_count:   fs_get_option_count,
+	init_task:          fs_init_task,
+	set_option:         fs_set_option,
+	set_volumes:        fs_set_volumes,
+	get_volume_info:    fs_get_volume_info,
+	get_plugin_info:    fs_get_plugin_info
+};
+
+
+/*-------------------------------------------------------------------------------------+
++                                                                                      +
++                         PLUGIN RECORD                                                +
++                                                                                      +
++-------------------------------------------------------------------------------------*/
+
+plugin_record_t  ext2_plugrec = {
+	id:                               SetPluginID(EVMS_OEM_IBM, EVMS_FILESYSTEM_INTERFACE_MODULE, FS_TYPE_EXT2 ),
+	version:                          {MAJOR_VERSION, MINOR_VERSION, PATCH_LEVEL},
+	required_api_version:             {ENGINE_PLUGIN_API_MAJOR_VERION, 
+					   ENGINE_PLUGIN_API_MINOR_VERION,
+					   ENGINE_PLUGIN_API_PATCH_LEVEL},
+	short_name:                       "Ext2/3",
+	long_name:                        "Ext2 File System Interface Module",
+	oem_name:                         "IBM",
+	functions:                        {fsim: &fsim_ops},
+	container_functions:              NULL
+
+};
+
diff --git a/lib/evms/fsimext2.c b/lib/evms/fsimext2.c
new file mode 100644
index 0000000..b826dd2
--- /dev/null
+++ b/lib/evms/fsimext2.c
@@ -0,0 +1,578 @@
+/*
+ *
+ *   Copyright (c) International Business Machines  Corp., 2000
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *   Module: fsimext2.c
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <plugin.h>
+#include "fsimext2.h"
+
+int fsim_rw_diskblocks( int, int64_t, int32_t, void *, int );
+void set_mkfs_options( option_array_t *, char **, logical_volume_t *, char * );
+void set_fsck_options( option_array_t *, char **, logical_volume_t * );
+
+// Vector of plugin record ptrs that we export for the EVMS Engine. 
+plugin_record_t *evms_plugin_records[] = {
+	&ext2_plugrec,
+	NULL
+};
+
+static plugin_record_t  * pMyPluginRecord = &ext2_plugrec;
+
+/*-------------------------------------------------------------------------------------+
++                                                                                      +
++                                   Common Routines                                    +
++                                                                                      +
++--------------------------------------------------------------------------------------*/
+
+
+/*
+ * Get the size limits for this volume.
+ */
+int fsim_get_volume_limits( struct ext2_super_block * sb,
+			   sector_count_t    * min_size,
+			   sector_count_t    * max_volume_size,
+			   sector_count_t    * max_object_size)
+{
+	int rc = 0;
+	sector_count_t fs_size;
+
+	/* 
+	 * Since ext2/3 does not yet support shrink or expand,
+	 * all values are actual file system size.
+	 */
+	fs_size = sb->s_blocks_count << (1 + sb->s_log_block_size);
+	*max_volume_size = fs_size;
+	*max_object_size = fs_size;
+	*min_size        = fs_size;
+
+	return rc;
+}
+
+
+/*
+ * Un-Format the volume.
+ */
+int fsim_unmkfs( logical_volume_t * volume )
+{
+    int  fd;
+    int  rc = 0;
+
+    fd = open(EVMS_GET_DEVNAME(volume), O_RDWR|O_EXCL, 0);
+    if (fd < 0) return -1;
+
+    if ( volume->private_data ) {
+        /* clear private data */
+        memset( (void *) volume->private_data, 0, SIZE_OF_SUPER );
+        /* zero primary superblock */
+        rc =  fsim_rw_diskblocks( fd, EXT2_SUPER_LOC, SIZE_OF_SUPER,
+				 volume->private_data, PUT );
+    } else {
+        rc = ERROR;
+    }
+
+    fd = close(fd);
+
+    return rc;
+}
+
+
+/*
+ * Format the volume.
+ */
+int fsim_mkfs(logical_volume_t * volume, option_array_t * options )
+{
+	int     rc = FSIM_ERROR;
+	char   *argv[MKFS_EXT2_OPTIONS_COUNT + 6];
+	char    logsize[sizeof(unsigned int) + 1];
+	pid_t	pidm;
+	int     status;
+
+	/* Fork and execute the correct program. */
+    switch (pidm = fork()) {
+        
+        /* error */
+        case -1:
+        	return EIO;
+
+        /* child */
+        case 0:  
+            set_mkfs_options( options, argv, volume, logsize );
+
+            /* close stderr, stdout to suppress mke2fs output */
+            close(1);
+            close(2);
+            open("/dev/null", O_WRONLY);
+            open("/dev/null", O_WRONLY);
+
+            (void) execvp(argv[0], argv);
+            /* using exit() can hang GUI, use _exit */
+            _exit(errno);
+
+        /* parent */
+        default:
+            /* wait for child to complete */
+            pidm = waitpid( pidm, &status, 0 );
+            if ( WIFEXITED(status) ) {
+                /* get mke2fs exit code */
+                rc = WEXITSTATUS(status);
+            }
+    }
+
+    return rc;
+}
+
+
+/*
+ * NAME: set_mkfs_options
+ *
+ * FUNCTION: Build options array (argv) for mkfs.ext2
+ *
+ * PARAMETERS:
+ *      options   - options array passed from EVMS engine
+ *      argv      - mkfs options array
+ *      vol_name  - volume name on which program will be executed
+ *
+ */                        
+void set_mkfs_options( option_array_t * options, 
+                       char ** argv, 
+                       logical_volume_t * volume, 
+                       char * logsize )
+{
+    int i, opt_count = 2;
+
+    argv[0] = "mke2fs";
+
+    /* 'quiet' option */
+    argv[1] = "-q";
+
+    for ( i=0; i<options->count; i++ ) {
+
+        if ( options->option[i].is_number_based ) {
+
+            switch (options->option[i].number) {
+                
+            case MKFS_CHECKBB_INDEX:
+                /* 'check for bad blocks' option */
+                if ( options->option[i].value.bool == TRUE ) {
+                    argv[opt_count++] = "-c";
+                }
+                break;
+
+            case MKFS_CHECKRW_INDEX:
+                /* 'check for r/w bad blocks' option */
+                if ( options->option[i].value.bool == TRUE ) {
+                    argv[opt_count++] = "-cc";
+                }
+                break;
+
+            case MKFS_JOURNAL_INDEX:
+                /* 'create ext3 journal' option */
+                if ( options->option[i].value.bool == TRUE ) {
+                    argv[opt_count++] = "-j";
+                }
+                break;
+
+            case MKFS_SETVOL_INDEX:
+                /* 'set volume name' option */
+                if ( options->option[i].value.s ) {
+                    argv[opt_count++] = "-L";
+                    argv[opt_count++] = options->option[i].value.s;
+                }
+                break;
+
+            default:
+                break;
+            }
+
+        } else {
+
+            if ( !strcmp(options->option[i].name, "badblocks") ) {
+                /* 'check for bad blocks' option */
+                if ( options->option[i].value.bool == TRUE ) {
+                    argv[opt_count++] = "-c";
+                }
+            }
+
+            if ( !strcmp(options->option[i].name, "badblocks_rw") ) {
+                /* 'check for r/w bad blocks' option */
+                if ( options->option[i].value.bool == TRUE ) {
+                    argv[opt_count++] = "-cc";
+                }
+            }
+
+            if ( !strcmp(options->option[i].name, "journal") ) {
+                /* 'create ext3 journal' option */
+                if ( options->option[i].value.bool == TRUE ) {
+                    argv[opt_count++] = "-j";
+                }
+            }
+
+            if ( !strcmp(options->option[i].name, "vollabel") ) {
+                /* 'check for bad blocks' option */
+                if ( options->option[i].value.s ) {
+                    argv[opt_count++] = "-L";
+                    argv[opt_count++] = options->option[i].value.s;
+                }
+            }
+        }
+    }
+
+    argv[opt_count++] = EVMS_GET_DEVNAME(volume);
+    argv[opt_count] = NULL;
+     
+    {
+	    FILE	*f;
+
+	    f = fopen("/var/tmp/evms-log", "a");
+	    for ( i=0; argv[i]; i++) {
+		    fprintf(f, "'%s' ", argv[i]);
+	    }
+	    fprintf(f, "\n");
+	    fclose(f);
+    }
+    
+    return;
+}
+
+
+/*
+ * Run fsck on the volume.
+ */
+int fsim_fsck(logical_volume_t * volume, option_array_t * options )
+{
+	int     rc = FSIM_ERROR;
+	char   *argv[FSCK_EXT2_OPTIONS_COUNT + 3];
+	pid_t	pidf;
+	int     status, bytes_read;
+	char    *buffer = NULL;
+	int     fds2[2];
+	int	banner = 0;
+
+	/* open pipe, alloc buffer for collecting fsck.jfs output */
+	rc = pipe(fds2);
+	if (rc) {
+	    return(rc);
+	}
+	if (!(buffer = EngFncs->engine_alloc(MAX_USER_MESSAGE_LEN))) {
+	    return(ENOMEM);
+	}
+
+	/* Fork and execute the correct program. */
+	switch (pidf = fork()) {
+        
+        /* error */
+        case -1:
+        	return EIO;
+
+        /* child */
+        case 0:  
+            set_fsck_options( options, argv, volume );
+
+            /* pipe stderr, stdout */
+		    dup2(fds2[1],1);	/* fds2[1] replaces stdout */
+		    dup2(fds2[1],2);  	/* fds2[1] replaces stderr */
+		    close(fds2[0]);	/* don't need this here */
+
+            rc = execvp( argv[0], argv );
+
+            /*
+             * The value of fsck exit code FSCK_CORRECTED is the same
+             * as errno EPERM.  Thus, if EPERM is returned from execv,
+             * exit out of the child with rc = -1 instead of EPERM.
+             */
+            if( rc && (errno == EPERM) ) {
+                /* using exit() can hang GUI, use _exit */
+                _exit(-1);
+            } else {
+                /* using exit() can hang GUI, use _exit */
+                _exit(errno);
+            }
+
+        /* parent */
+        default:
+		close(fds2[1]);
+
+		/* wait for child to complete */
+		while (!(pidf = waitpid( pidf, &status, WNOHANG ))) {
+			/* read e2fsck output */
+			bytes_read = read(fds2[0],buffer,MAX_USER_MESSAGE_LEN);
+			if (bytes_read > 0) {
+				/* display e2fsck output */
+				if (!banner)
+					MESSAGE("e2fsck output: \n\n%s",buffer);
+				else
+					banner = 1;
+				memset(buffer,0,bytes_read); //clear out message  
+			}
+			usleep(10000); /* don't hog all the cpu */
+		}
+
+		/* wait for child to complete */
+		pidf = waitpid( pidf, &status, 0 );
+		if ( WIFEXITED(status) ) {
+			/* get e2fsck exit code */
+			rc = WEXITSTATUS(status);
+			LOG("e2fsck completed with exit code %d \n", rc);
+		}
+	}
+
+	if (buffer) {
+		EngFncs->engine_free(buffer);
+	}
+
+    return rc;
+}
+
+
+/*
+ * NAME: set_fsck_options
+ *
+ * FUNCTION: Build options array (argv) for e2fsck
+ *
+ * PARAMETERS:
+ *      options   - options array passed from EVMS engine
+ *      argv      - fsck options array
+ *      volume    - volume on which program will be executed
+ *
+ */                        
+void set_fsck_options( option_array_t * options, char ** argv, logical_volume_t * volume )
+{
+    int i, opt_count = 1;
+    int do_preen = 1;
+
+    argv[0] = "e2fsck";
+
+    for ( i=0; i<options->count; i++) {
+
+        if ( options->option[i].is_number_based ) {
+
+            /* 'force check' option */
+            if ( (options->option[i].number == FSCK_FORCE_INDEX) && 
+                 (options->option[i].value.bool == TRUE) ) {
+                argv[opt_count++] = "-f";
+            }
+
+            /* 'check read only' option or mounted */
+            if ((options->option[i].number == FSCK_READONLY_INDEX) &&
+		((options->option[i].value.bool == TRUE) ||
+		 EVMS_IS_MOUNTED(volume))) {
+                argv[opt_count++] = "-n";
+		do_preen = 0;
+            }
+
+            /* 'bad blocks check' option and NOT mounted */
+            if ( (options->option[i].number == FSCK_CHECKBB_INDEX) && 
+                 (options->option[i].value.bool == TRUE)         &&
+                 !EVMS_IS_MOUNTED(volume) ) {
+                argv[opt_count++] = "-c";
+		do_preen = 0;
+            }
+
+            /* 'bad blocks check' option and NOT mounted */
+            if ( (options->option[i].number == FSCK_CHECKRW_INDEX) && 
+                 (options->option[i].value.bool == TRUE)         &&
+                 !EVMS_IS_MOUNTED(volume) ) {
+                argv[opt_count++] = "-cc";
+		do_preen = 0;
+            }
+	    
+            /* timing option */
+            if ( (options->option[i].number == FSCK_TIMING_INDEX) && 
+		 (options->option[i].value.bool == TRUE) ) {
+                argv[opt_count++] = "-tt";
+            }
+	    
+    } else {
+
+            /* 'force check' option selected and NOT mounted */
+            if ( !strcmp(options->option[i].name, "force") &&
+                 (options->option[i].value.bool == TRUE) &&
+                 !EVMS_IS_MOUNTED(volume) ) {
+                argv[opt_count++] = "-f";
+            }
+
+            /* 'check read only' option selected or mounted */
+            if ((!strcmp(options->option[i].name, "readonly")) &&
+		((options->option[i].value.bool == TRUE) ||
+                 EVMS_IS_MOUNTED(volume))) {
+                argv[opt_count++] = "-n";
+		do_preen = 0;
+            }
+
+            /* 'check badblocks' option selected and NOT mounted */
+            if (!strcmp(options->option[i].name, "badblocks") &&
+		(options->option[i].value.bool == TRUE) &&
+		!EVMS_IS_MOUNTED(volume)) {
+                argv[opt_count++] = "-c";
+		do_preen = 0;
+            }
+
+            /* 'check r/w badblocks' option selected and NOT mounted */
+            if (!strcmp(options->option[i].name, "badblocks_rw") &&
+		(options->option[i].value.bool == TRUE) &&
+		!EVMS_IS_MOUNTED(volume)) {
+                argv[opt_count++] = "-cc";
+		do_preen = 0;
+            }
+
+            /* 'timing' option selected */
+            if (!strcmp(options->option[i].name, "badblocks") &&
+		(options->option[i].value.bool == TRUE)) {
+                argv[opt_count++] = "-tt";
+            }
+        }
+    }
+
+    if (do_preen)
+	    argv[opt_count++] = "-p";
+    argv[opt_count++] = EVMS_GET_DEVNAME(volume);
+    argv[opt_count]   = NULL;
+
+    {
+	    FILE	*f;
+
+	    f = fopen("/var/tmp/evms-log", "a");
+	    for ( i=0; argv[i]; i++) {
+		    fprintf(f, "'%s' ", argv[i]);
+	    }
+	    fprintf(f, "\n");
+	    fclose(f);
+    }
+    
+    return;
+}
+
+
+/*
+ * NAME: fsim_get_ext2_superblock
+ *
+ * FUNCTION: Get and validate a ext2/3 superblock
+ *
+ * PARAMETERS:
+ *      volume   - pointer to volume from which to get the superblock
+ *      sb_ptr   - pointer to superblock
+ *
+ * RETURNS:
+ *      (0) for success
+ *      != 0 otherwise
+ *        
+ */                        
+int fsim_get_ext2_superblock( logical_volume_t *volume, struct ext2_super_block *sb_ptr )
+{
+    int  fd;
+    int  rc = 0;
+
+    fd = open(EVMS_GET_DEVNAME(volume), O_RDONLY, 0);
+    if (fd < 0) return EIO;
+
+    /* get primary superblock */
+    rc = fsim_rw_diskblocks( fd, EXT2_SUPER_LOC, SIZE_OF_SUPER, sb_ptr, GET );
+
+    if( rc == 0 ) {
+        /* see if superblock is ext2/3 */
+        if (( sb_ptr->s_magic != EXT2_SUPER_MAGIC ) ||
+	    ( sb_ptr->s_rev_level > 1 ))
+		rc = FSIM_ERROR;
+    }
+
+    close(fd);
+
+    return rc;
+}
+
+
+/*
+ * NAME: fsim_rw_diskblocks
+ *
+ * FUNCTION: Read or write specific number of bytes for an opened device.
+ *
+ * PARAMETERS:
+ *      dev_ptr         - file handle of an opened device to read/write
+ *      disk_offset     - byte offset from beginning of device for start of disk
+ *                        block read/write
+ *      disk_count      - number of bytes to read/write
+ *      data_buffer     - On read this will be filled in with data read from
+ *                        disk; on write this contains data to be written
+ *      mode            - GET (read) or PUT (write)
+ *
+ * RETURNS:
+ *      FSIM_SUCCESS (0) for success
+ *      ERROR       (-1) can't lseek
+ *      EINVAL           
+ *      EIO
+ *        
+ */                        
+int fsim_rw_diskblocks( int      dev_ptr,
+                        int64_t  disk_offset,
+                        int32_t  disk_count,
+                        void     *data_buffer,
+                        int      mode )
+{
+    off_t   Actual_Location;
+    size_t  Bytes_Transferred;
+
+    Actual_Location = lseek(dev_ptr,disk_offset, SEEK_SET);
+    if ( ( Actual_Location < 0 ) || ( Actual_Location != disk_offset ) )
+        return ERROR;
+
+    switch ( mode ) {
+        case GET:
+            Bytes_Transferred = read(dev_ptr,data_buffer,disk_count);
+            break;
+        case PUT:
+            Bytes_Transferred = write(dev_ptr,data_buffer,disk_count);
+            break;
+        default:
+            return EINVAL;
+            break;
+    }
+
+    if ( Bytes_Transferred != disk_count ) {
+        return EIO;
+    }
+
+    return FSIM_SUCCESS;
+}
+
+
+/*
+ * Test e2fsprogs version.
+ *
+ * We don't bother since we don't need any special functionality that
+ * hasn't been around for *years*
+ */	
+int fsim_test_version( )
+{
+	return 0;
+}
+
+
+
+
+
diff --git a/lib/evms/fsimext2.h b/lib/evms/fsimext2.h
new file mode 100644
index 0000000..dd7d44b
--- /dev/null
+++ b/lib/evms/fsimext2.h
@@ -0,0 +1,276 @@
+/* Version number of the ext2 plugin */
+#define MAJOR_VERSION 1
+#define MINOR_VERSION 0
+#define PATCH_LEVEL 0
+
+/*
+ *
+ *   Copyright (c) International Business Machines  Corp., 2000
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or 
+ *   (at your option) any later version.
+ * 
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software 
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *   Module: fsimext2.h
+ *
+ */
+
+/*
+ * EVMS 1.0 backwards compatibility functions
+ */
+#ifdef ABI_EVMS_1_0
+#define EVMS_IS_MOUNTED(vol)	((vol)->mount_point != 0)
+#define EVMS_GET_DEVNAME(vol)	((vol)->name)
+#else
+#define EVMS_IS_MOUNTED(vol)	(EngFncs->is_mounted((vol)->dev_node, NULL))
+#define EVMS_GET_DEVNAME(vol)	((vol)->dev_node)
+#endif
+                   
+/********************
+ ********************
+ **                **
+ **  EVMS defines  **
+ **                **
+ ********************
+ ********************/
+ 
+extern plugin_record_t ext2_plugrec;
+engine_functions_t *EngFncs;
+                 
+// file system type ... used by the SetPluginID macro
+#define FS_TYPE_EXT2     7
+                 
+// logging macros 
+#define LOGENTRY()                  EngFncs->write_log_entry(ENTRY_EXIT, pMyPluginRecord, "%s:  Enter.\n", __FUNCTION__)
+#define LOGEXIT()                   EngFncs->write_log_entry(ENTRY_EXIT, pMyPluginRecord, "%s:  Exit.\n", __FUNCTION__ )
+#define LOGEXITRC()                 EngFncs->write_log_entry(ENTRY_EXIT, pMyPluginRecord, "%s:  Exit.  RC= %d.\n", __FUNCTION__, rc)
+#define MESSAGE(msg, args...)	    EngFncs->user_message(pMyPluginRecord, NULL, NULL, msg, ##args)
+#define LOG_CRITICAL(msg, args...)	EngFncs->write_log_entry(CRITICAL,	pMyPluginRecord, __FUNCTION__ ": " msg, ## args)
+#define LOG_SERIOUS(msg, args...)	EngFncs->write_log_entry(SERIOUS,	pMyPluginRecord, __FUNCTION__ ": " msg, ## args)
+#define LOG_ERROR(msg, args...)		EngFncs->write_log_entry(ERROR,	pMyPluginRecord, __FUNCTION__ ": " msg, ## args)
+#define LOG_WARNING(msg, args...)	EngFncs->write_log_entry(WARNING,	pMyPluginRecord, __FUNCTION__ ": " msg, ## args)
+#define LOG(msg, args...)		    EngFncs->write_log_entry(DEFAULT,	pMyPluginRecord, __FUNCTION__ ": " msg, ## args)
+#define LOG_DETAILS(msg, args...)	EngFncs->write_log_entry(DETAILS,	pMyPluginRecord, __FUNCTION__ ": " msg, ## args)
+#define LOG_DEBUG(msg, args...)		EngFncs->write_log_entry(DEBUG,	pMyPluginRecord, __FUNCTION__ ": " msg, ## args)
+#define LOG_EXTRA(msg, args...)		EngFncs->write_log_entry(EXTRA,	pMyPluginRecord, __FUNCTION__ ": " msg, ## args)
+
+// useful macro for option code
+#define SET_STRING_FIELD(a,b)\
+a = EngFncs->engine_alloc( strlen(b)+1 );\
+if (a ) {\
+    strcpy(a, b);\
+}\
+else {\
+    return -ENOMEM;\
+}
+
+#define SET_STRING(a,b) a = EngFncs->engine_alloc( strlen(b)+1 );if (a ) { strcpy(a, b); } else { rc = ENOMEM; LOG_EXIT(rc);}
+#define LOG_EXIT(x)     LOG_PROC("Exiting: rc = %d\n", x)
+#define LOG_PROC(msg, args...)    EngFncs->write_log_entry(ENTRY_EXIT, pMyPluginRecord, "%s: " msg, __FUNCTION__ , ## args)
+
+
+/**********************************
+ **********************************
+ **                              **
+ **  fsck.jfs, mkfs.jfs defines  **
+ **                              **
+ **********************************
+ **********************************/
+
+/* fsck.jfs, mkfs.jfs option counts */
+
+/* fsck.jfs option array indices */
+#define FSCK_FORCE_INDEX      	0
+#define FSCK_READONLY_INDEX   	1
+#define FSCK_CHECKBB_INDEX      2
+#define FSCK_CHECKRW_INDEX      3
+#define FSCK_TIMING_INDEX	4
+#define FSCK_EXT2_OPTIONS_COUNT  5
+
+/* mkfs.jfs option array indices */
+#define MKFS_CHECKBB_INDEX      0
+#define MKFS_CHECKRW_INDEX      1
+#define MKFS_SETVOL_INDEX       2
+#define MKFS_JOURNAL_INDEX      3
+#define MKFS_EXT2_OPTIONS_COUNT 4
+
+/* fsck exit codes */
+#define FSCK_OK                    0
+#define FSCK_CORRECTED             1
+#define FSCK_REBOOT                2
+#define FSCK_ERRORS_UNCORRECTED    4
+#define FSCK_OP_ERROR              8
+#define FSCK_USAGE_ERROR          16
+
+
+/*
+ * EXT2/3 defines and structs
+ */
+
+/* generic defines */
+#define FSIM_SUCCESS            0
+#define FSIM_ERROR             -1
+#define GET                     0
+#define PUT                     1
+
+#define EXT2_SUPER_LOC		1024
+
+#define EXT2_SUPER_MAGIC	0xEF53
+
+#define EXT3_FEATURE_INCOMPAT_RECOVER		0x0004 /* Needs recovery */
+
+#define	EXT2_VALID_FS			0x0001	/* Unmounted cleanly */
+#define	EXT2_ERROR_FS			0x0002	/* Errors detected */
+
+/*
+ * Structure of the ext2 super block
+ */
+struct ext2_super_block {
+	__u32	s_inodes_count;		/* Inodes count */
+	__u32	s_blocks_count;		/* Blocks count */
+	__u32	s_r_blocks_count;	/* Reserved blocks count */
+	__u32	s_free_blocks_count;	/* Free blocks count */
+	__u32	s_free_inodes_count;	/* Free inodes count */
+	__u32	s_first_data_block;	/* First Data Block */
+	__u32	s_log_block_size;	/* Block size */
+	__s32	s_log_frag_size;	/* Fragment size */
+	__u32	s_blocks_per_group;	/* # Blocks per group */
+	__u32	s_frags_per_group;	/* # Fragments per group */
+	__u32	s_inodes_per_group;	/* # Inodes per group */
+	__u32	s_mtime;		/* Mount time */
+	__u32	s_wtime;		/* Write time */
+	__u16	s_mnt_count;		/* Mount count */
+	__s16	s_max_mnt_count;	/* Maximal mount count */
+	__u16	s_magic;		/* Magic signature */
+	__u16	s_state;		/* File system state */
+	__u16	s_errors;		/* Behaviour when detecting errors */
+	__u16	s_minor_rev_level; 	/* minor revision level */
+	__u32	s_lastcheck;		/* time of last check */
+	__u32	s_checkinterval;	/* max. time between checks */
+	__u32	s_creator_os;		/* OS */
+	__u32	s_rev_level;		/* Revision level */
+	__u16	s_def_resuid;		/* Default uid for reserved blocks */
+	__u16	s_def_resgid;		/* Default gid for reserved blocks */
+	/*
+	 * These fields are for EXT2_DYNAMIC_REV superblocks only.
+	 *
+	 * Note: the difference between the compatible feature set and
+	 * the incompatible feature set is that if there is a bit set
+	 * in the incompatible feature set that the kernel doesn't
+	 * know about, it should refuse to mount the filesystem.
+	 * 
+	 * e2fsck's requirements are more strict; if it doesn't know
+	 * about a feature in either the compatible or incompatible
+	 * feature set, it must abort and not try to meddle with
+	 * things it doesn't understand...
+	 */
+	__u32	s_first_ino; 		/* First non-reserved inode */
+	__u16   s_inode_size; 		/* size of inode structure */
+	__u16	s_block_group_nr; 	/* block group # of this superblock */
+	__u32	s_feature_compat; 	/* compatible feature set */
+	__u32	s_feature_incompat; 	/* incompatible feature set */
+	__u32	s_feature_ro_compat; 	/* readonly-compatible feature set */
+	__u8	s_uuid[16];		/* 128-bit uuid for volume */
+	char	s_volume_name[16]; 	/* volume name */
+	char	s_last_mounted[64]; 	/* directory where last mounted */
+	__u32	s_algorithm_usage_bitmap; /* For compression */
+	/*
+	 * Performance hints.  Directory preallocation should only
+	 * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
+	 */
+	__u8	s_prealloc_blocks;	/* Nr of blocks to try to preallocate*/
+	__u8	s_prealloc_dir_blocks;	/* Nr to preallocate for dirs */
+	__u16	s_padding1;
+	/* 
+	 * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
+	 */
+	__u8	s_journal_uuid[16];	/* uuid of journal superblock */
+	__u32	s_journal_inum;		/* inode number of journal file */
+	__u32	s_journal_dev;		/* device number of journal file */
+	__u32	s_last_orphan;		/* start of list of inodes to delete */
+	
+	__u32	s_reserved[197];	/* Padding to the end of the block */
+};
+
+#define L2MEGABYTE      20
+#define MEGABYTE        (1 << L2MEGABYTE)
+#define MEGABYTE32     (MEGABYTE << 5)
+#define MAX_LOG_PERCENTAGE  10              /* Log can be at most 10% of disk */
+
+/*
+ *	buffer cache configuration
+ */
+/* page size */
+#ifdef PSIZE
+#undef PSIZE
+#endif
+#define	PSIZE		4096	/* page size (in byte) */
+
+#define	PBSIZE		512	/* physical block size (in byte) */
+
+/*
+ * Minimum number of bytes supported for an ext2 partition
+ * (64k, quite small!)
+ */
+#define MINEXT2		(64*1024)
+
+/*
+ * SIZE_OF_SUPER defines the total amount of space reserved on disk for the
+ * superblock.  This is not the same as the superblock structure, since all of
+ * this space is not currently being used.
+ */
+#define SIZE_OF_SUPER	sizeof(struct ext2_super_block)
+
+/*
+ * SIZE_OF_MAP_PAGE defines the amount of disk space reserved for each page of
+ * the inode allocation map (to hold iag)
+ */
+#define SIZE_OF_MAP_PAGE	PSIZE
+
+/*
+ *	directory configuration
+ */
+#define JFS_NAME_MAX	255
+#define JFS_PATH_MAX	BPSIZE      
+
+/*
+ *	file system state (superblock state)
+ */
+#define FM_CLEAN 0x00000000	/* file system is unmounted and clean */
+#define FM_MOUNT 0x00000001	/* file system is mounted cleanly */
+#define FM_DIRTY 0x00000002	/* file system was not unmounted and clean 
+            				 * when mounted or 
+			            	 * commit failure occurred while being mounted:
+				             * fsck() must be run to repair 
+				             */
+#define	FM_LOGREDO 0x00000004	/* log based recovery (logredo()) failed:
+				                 * fsck() must be run to repair 
+				                 */
+#define	FM_EXTENDFS 0x00000008	/* file system extendfs() in progress */
+
+
+/*******************
+ *******************
+ **               **
+ **  Common code  **
+ **               **
+ *******************
+ *******************/
+
+int fsim_get_ext2_superblock( logical_volume_t *, struct ext2_super_block * );
+int fsim_unmkfs( logical_volume_t * );
+int fsim_mkfs( logical_volume_t *, option_array_t * );
+int fsim_fsck( logical_volume_t *, option_array_t * );
+int fsim_get_volume_limits( struct ext2_super_block *, sector_count_t *,
+			                   sector_count_t *, sector_count_t * );
+int fsim_test_version( void );
diff --git a/lib/evms/options.h b/lib/evms/options.h
new file mode 100644
index 0000000..b109231
--- /dev/null
+++ b/lib/evms/options.h
@@ -0,0 +1,315 @@
+/*
+ *
+ *   Copyright (c) International Business Machines  Corp., 2001
+ *   Copyright (C) 1997-1999 David Mosberger-Tang and Andreas Beck
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Module: options.h
+ */
+
+#ifndef EVMS_OPTIONS_H_INCLUDED
+#define EVMS_OPTIONS_H_INCLUDED 1
+
+#include <common.h>
+
+/*
+ * Dear Reader,
+ *
+ * Yes, some of the structures look a lot like the ones the SANE
+ * (Scanner Access Now Easy) folks use for negotiating options
+ * between a frontend and backend. In fact, some of the structures
+ * here were derived from their solution with some tweaks for EVMS.
+ *
+ * Kindest regards and most humble apologies to the SANE folks for
+ * borrowing their solution.
+ */
+
+/*
+ * Task API typedefs
+ */
+
+typedef u_int32_t task_handle_t;
+
+/*
+ * Task actions correspond to the low-level API available to frontends.
+ * The task API allows binding of action, plugin, target objects, and
+ * plugin-specific options. This allows for interaction with the backend
+ * to validate the correctness of parameters and options necessary to
+ * fulfill the requirements of the low-level API which eventually is invoked.
+ */
+
+typedef enum {
+    EVMS_Task_Create = 0,
+    EVMS_Task_Create_Container,
+    EVMS_Task_Assign_Plugin,
+    EVMS_Task_Expand_Container,
+    EVMS_Task_Set_Info,
+    EVMS_Task_Expand,
+    EVMS_Task_Shrink,
+    EVMS_Task_Slide,
+    EVMS_Task_Move,
+    EVMS_Task_mkfs,
+    EVMS_Task_fsck,
+    EVMS_Task_defrag,
+    EVMS_Task_Message,
+    EVMS_Task_Add_Feature,
+    EVMS_Task_Plugin_Function = 0x1000  /* Base number for plug-in funtions */
+} task_action_t;
+
+
+typedef struct function_info_s {
+    task_action_t   function;       /* Plugin function number */
+    char          * title;          /* Short title for the function */
+                                    /* e.g. "Add a spare" */
+                                    /* Example usage:  A UI might put this in */
+                                    /* a menu of functions to select. */
+    char          * verb;           /* One or two action words for the function */
+                                    /* e.g. "Add" */
+                                    /* Example usage:  A GUI may use this on an */
+                                    /* action button for the function. */
+    char          * help;           /* Full help text */
+                                    /* e.g. "Use this function to add a spare blah blah blah..." */
+} function_info_t;
+
+typedef struct function_info_array_s {
+    uint            count;
+    function_info_t info[1];
+} function_info_array_t;
+
+
+/*
+ * Object API typedefs
+ */
+
+typedef struct declined_handle_s {
+    object_handle_t           handle;               /* Handle of object declined */
+    int                       reason;               /* Reason for being declined */
+} declined_handle_t;
+
+typedef struct declined_handle_array_s {
+    uint                      count;
+    declined_handle_t         declined[1];
+} declined_handle_array_t;
+
+/*
+ * Option API typedefs and constants
+ */
+
+typedef enum {
+    EVMS_Type_String = 1,                           /* char*     */
+    EVMS_Type_Boolean,                              /* BOOLEAN   */
+    EVMS_Type_Char,                                 /* char      */
+    EVMS_Type_Unsigned_Char,                        /* unsigned char */
+    EVMS_Type_Real32,                               /* float     */
+    EVMS_Type_Real64,                               /* double    */
+    EVMS_Type_Int,                                  /* int       */
+    EVMS_Type_Int8,                                 /* int8_t    */
+    EVMS_Type_Int16,                                /* int16_t   */
+    EVMS_Type_Int32,                                /* int32_t   */
+    EVMS_Type_Int64,                                /* int64_t   */
+    EVMS_Type_Unsigned_Int,                         /* uint      */
+    EVMS_Type_Unsigned_Int8,                        /* u_int8_t  */
+    EVMS_Type_Unsigned_Int16,                       /* u_int16_t */
+    EVMS_Type_Unsigned_Int32,                       /* u_int32_t */
+    EVMS_Type_Unsigned_Int64                        /* u_int64_t */
+} value_type_t;
+
+typedef enum {
+    EVMS_Unit_None = 0,
+    EVMS_Unit_Disks,
+    EVMS_Unit_Sectors,
+    EVMS_Unit_Segments,
+    EVMS_Unit_Regions,
+    EVMS_Unit_Percent,
+    EVMS_Unit_Milliseconds,
+    EVMS_Unit_Microseconds,
+    EVMS_Unit_Bytes,
+    EVMS_Unit_Kilobytes,
+    EVMS_Unit_Megabytes,
+    EVMS_Unit_Gigabytes,
+    EVMS_Unit_Terabytes,
+    EVMS_Unit_Petabytes
+} value_unit_t;
+
+typedef enum {
+    EVMS_Collection_None = 0,                       /* No collection */
+    EVMS_Collection_List,                           /* Use a value_list_t structure */
+    EVMS_Collection_Range                           /* Use a value_range_t structure */
+} collection_type_t;
+
+typedef enum {
+    EVMS_Format_Normal = 0,
+    EVMS_Format_Hex,
+    EVMS_Format_Ascii,
+    EVMS_Format_Binary
+} value_format_t;
+
+typedef union {
+    char                      c;                    /* one character, e.g. 'C' */
+    char                     *s;                    /* string pointer */
+    u_char                    uc;
+    int                       bool;
+    int                       i;
+    int8_t                    i8;
+    int16_t                   i16;
+    int32_t                   i32;
+    int64_t                   i64;
+    u_int                     ui;
+    u_int8_t                  ui8;
+    u_int16_t                 ui16;
+    u_int32_t                 ui32;
+    u_int64_t                 ui64;
+    float                     r32;
+    double                    r64;
+    struct value_list_s      *list;
+} value_t;
+
+/*
+ * The struct key_value_pair_s allows some generic passing
+ * of a key/value pair for some basic data type values. The
+ * key can be a name (a string) or a number. The sending
+ * and receiving ends denote, through the is_number_based flag,
+ * which key should be looked at for identification purposes.
+ */
+
+typedef struct key_value_pair_s {
+    char           *name;                           /* Key if name-based */
+    u_int16_t       number;                         /* Key if number-based */
+    BOOLEAN         is_number_based;                /* TRUE if number-based */
+    value_type_t    type;                           /* Value type */
+    value_t         value;                          /* Union of basic data types */
+} key_value_pair_t;
+
+/*
+ * Some frontends may supply plugin-specific data as "options" through
+ * the API functions, e.g. evms_create(), available to a frontend.
+ * Options are essentially key/value pairs where the key and value types
+ * are known ahead-of-time or were interrogated through the option
+ * descriptor API.
+ */
+
+typedef struct option_array_s {
+    u_int                     count;
+    key_value_pair_t          option[1];
+} option_array_t;
+
+typedef struct value_list_s {
+    u_int                     count;
+    value_t                   value[1];
+} value_list_t;
+
+typedef struct value_range_s {
+    value_t                   min;                  /* Minimum value */
+    value_t                   max;                  /* Maximum value */
+    value_t                   increment;            /* Step or increment for changes in-between */
+} value_range_t;
+
+typedef union {
+    value_list_t             *list;                 /* Array of values of the same type */
+    value_range_t            *range;                /* Range of values for numeric types */
+} value_collection_t;
+
+typedef struct group_info_s {
+    u_int32_t                 group_number;         /* group number, 0 if not grouped */
+    u_int32_t                 group_level;          /* possibly used for indenting, or sub fields */
+    char                     *group_name;           /* name of group                              */
+} group_info_t;
+
+typedef struct option_descriptor_s {
+    char                     *name;                 /* Option name/key */
+    char                     *title;                /* One or two word description of option */
+    char                     *tip;                  /* Multi-sentence description of option for tip */
+    char                     *help;                 /* Multi-paragraph detailed option help */
+    value_type_t              type;                 /* Defines option data type */
+    value_unit_t              unit;                 /* Defines unit value */
+#ifdef ABI_EVMS_1_0
+    u_int32_t                 size;                 /* Maximum size (in bytes) of option value */
+#else
+    value_format_t            format;               /* Suggested format for display of values */
+    u_int32_t                 min_len;              /* Minimum length for string types */
+    u_int32_t                 max_len;              /* Maximum length for string types */
+#endif
+    u_int64_t                 flags;                /* Option flags (defined below) */
+    collection_type_t         constraint_type;      /* Constraint type (none, range, list) */
+    value_collection_t        constraint;           /* Either a list or range of valid input values */
+    value_t                   value;                /* Initial/current value */
+    group_info_t              group;                /* Group information for display purposes     */
+} option_descriptor_t;
+
+/*
+ * option_descriptor_t flags bitset
+ */
+
+#define EVMS_OPTION_FLAGS_NOT_REQUIRED     (1 << 0) /* A key_value_pair_t for this option can be provided */
+                                                    /* but is not absolutely required by the plug-in */
+#define EVMS_OPTION_FLAGS_NO_INITIAL_VALUE (1 << 1) /* The plug-in has not provided an initial value */
+#define EVMS_OPTION_FLAGS_AUTOMATIC        (1 << 2) /* Backend is capable of selecting reasonable value */
+#define EVMS_OPTION_FLAGS_INACTIVE         (1 << 3) /* Option exists but is neither optional or required */
+#define EVMS_OPTION_FLAGS_ADVANCED         (1 << 4) /* Option is an "advanced user option" */
+#define EVMS_OPTION_FLAGS_VALUE_IS_LIST    (1 << 5) /* Value is/is expected to be a pointer to value_list_t */
+#define EVMS_OPTION_FLAGS_NO_UNIT_CONVERSION (1 << 6) /* Don't convert unit measurements, e.g. I really mean */
+                                                      /* to have the user specify/see sectors not KB or MB */
+
+#define EVMS_OPTION_IS_ACTIVE(flags)     (((flags) & EVMS_OPTION_FLAGS_INACTIVE) == 0)
+#define EVMS_OPTION_IS_REQUIRED(flags)   (((flags) & EVMS_OPTION_FLAGS_NOT_REQUIRED) == 0)
+#define EVMS_OPTION_HAS_VALUE(flags)     (((flags) & EVMS_OPTION_FLAGS_NO_INITIAL_VALUE) == 0)
+#define EVMS_OPTION_VALUE_IS_LIST(flags) (((flags) & EVMS_OPTION_FLAGS_VALUE_IS_LIST) != 0)
+
+/*
+ * Following bitset indicating additional information of
+ * the outcome of a set_object or a set action on a option value.
+ */
+
+typedef enum {
+    EVMS_Effect_Inexact        = (1 << 0),       /* Option value was adjusted by backend */
+    EVMS_Effect_Reload_Options = (1 << 1),       /* Setting of an object or option has affected */
+                                                 /* the value or availability of other options */
+    EVMS_Effect_Reload_Objects = (1 << 2)        /* Setting of an object or option has affected */
+                                                 /* the acceptable and/or selected objects */
+                                                 /* or the limits of objects selected. */
+} task_effect_t;
+
+/*
+ * Extended information structure. Plug-ins generate an
+ * array of these to supply plugin-specific information.
+ * They are similar to option descriptors but lighter.
+ */
+
+typedef struct extended_info_s {
+    char                   *name;                   /* Info field name */
+    char                   *title;                  /* One or two word description of info field */
+    char                   *desc;                   /* Multi-sentence description of info field */
+    value_type_t            type;                   /* Defines info data type */
+    value_unit_t            unit;                   /* Defines info unit value */
+    value_format_t          format;                 /* Suggested format for display of values */
+    value_t                 value;                  /* Single value if not a collection */
+    collection_type_t       collection_type;        /* Defines if either a list or range of values */
+    value_collection_t      collection;             /* Either a list or range of values of value_type_t */
+    group_info_t            group;                  /* Group information for display purposes */
+    u_int16_t               flags;                  /* Extended info flags (defined below) */
+} extended_info_t;
+
+#define EVMS_EINFO_FLAGS_NO_UNIT_CONVERSION (1 << 0) /* Don't convert unit measurements, e.g. I really */
+                                                     /* mean the user to see sectors not KB or MB */
+#define EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE (1 << 1)/* This entry has more information if */
+                                                     /* queried by name. */
+
+typedef struct extended_info_array_s {
+    u_int                   count;                  /* Count of extended_info_t structs in array */
+    extended_info_t         info[1];                /* Info descriptors */
+} extended_info_array_t;
+
+#endif
diff --git a/lib/evms/plugfuncs.h b/lib/evms/plugfuncs.h
new file mode 100644
index 0000000..9b887ef
--- /dev/null
+++ b/lib/evms/plugfuncs.h
@@ -0,0 +1,1128 @@
+/*
+ *
+ *   Copyright (c) International Business Machines  Corp., 2001
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Module: plugfuncs.h
+ */
+
+#ifndef EVMS_PLUGFUNCS_H_INCLUDED
+#define EVMS_PLUGFUNCS_H_INCLUDED 1
+
+#include <dlist.h>
+#include <common.h>
+#include <options.h>
+#include <enginestructs.h>
+
+#ifdef ABI_EVMS_1_0
+#define ENGINE_PLUGIN_API_MAJOR_VERION  3
+#else
+#define ENGINE_PLUGIN_API_MAJOR_VERION  7
+#endif
+#define ENGINE_PLUGIN_API_MINOR_VERION  0
+#define ENGINE_PLUGIN_API_PATCH_LEVEL   0
+
+/* Maximum length of a user message. */
+#define MAX_USER_MESSAGE_LEN    10240
+
+/*
+ * For all can_????() functions, the function returns 0 if "yes", else a reason code.
+ */
+
+typedef struct engine_functions_s {
+#ifndef ABI_EVMS_1_0
+    /*
+     * Get the version of the plug-in API that this Engine provides.
+     */
+    void (*get_engine_plugin_api_version)(evms_version_t * version);
+#endif
+
+    /*
+     * Get a list of the user space plug-ins that are loaded, optionally
+     * filtering by type and flags.  If the type parameter is not 0, only
+     * plug-ins of that type will be returned.  If type is 0, all plug-ins will
+     * be returned.  See common.h for the definitions of plugin_search_flags_t.
+     */
+    int (*get_plugin_list)(plugin_type_t         type,
+                           plugin_search_flags_t flags,
+                           dlist_t             * plugins);
+
+    /*
+     * Get the plugin_record_t for a given plug-in ID.
+     */
+    int (*get_plugin_by_ID)(plugin_id_t         plugin_id,
+                            plugin_record_t * * plugin);
+
+    /*
+     * Get the plugin_record_t for a given plug-in short name.
+     */
+    int (*get_plugin_by_name)(char              * plugin_short_name,
+                              plugin_record_t * * plugin);
+
+    /*
+     * Get a list of volumes, optionally filtering by FSIM.  If FSIM is
+     * specified, only volumes managed by that FSIM will be returned.  If FSIM
+     * is NULL, all volumes will be returned.
+     */
+    int (*get_volume_list)(plugin_record_t * fsim,
+                           dlist_t         * volume_list);
+
+    /*
+     * Get a list of objects, optionally filtering by object type, data type,
+     * and plug-in.  See the object_type_t, data_type_t, and
+     * object_search_flags_t enums in common.h.  If object_type is 0, objects of
+     * any type will be returned.  If data_type is 0, objects of any data type
+     * will be returned.  If plugin is NULL, objects managed by any plug-in will
+     * be returned.
+     */
+    int (*get_object_list)(object_type_t         object_type,
+                           data_type_t           data_type,
+                           plugin_record_t     * plugin,
+                           object_search_flags_t flags,
+                           dlist_t             * objects);
+
+    /*
+     * Get a list of storage containers, optionally filtering by plug-in.
+     * If plugin is specified, only containers managed by that plug-in
+     * will be returned.  If plugin is NULL, all containers will be returned.
+     */
+    int (*get_container_list)(plugin_record_t * plugin,
+                              dlist_t *         container_list);
+
+    /*
+     * Issue an ioctl to the EVMS kernel block device.  The Engine opens
+     * and locks the EVMS kernel block device.  While the Engine is open
+     * for writing, no other application, not even Engine plug-ins, can
+     * open the EVMS kernel block device.  Plug-ins use this service
+     * to have the Engine issue an ioctl to the EVMS kernel block device
+     * on their behalf.
+     */
+    int (*ioctl_evms_kernel)(unsigned long cmd,
+                             void * arg);
+    /*
+     * Allocate a storage_object_t for a logical disk structure.
+     */
+    int (*allocate_logical_disk)(char * name,
+                                 storage_object_t * * new_disk);
+
+    /*
+     * Free a storage_object_t for a logical disk.
+     */
+    int (*free_logical_disk)(storage_object_t * disk);
+
+    /*
+     * Allocate a storage_object_t for a disk_segment.  The caller is
+     * responsible for putting the storage_object_t for the logical disk from
+     * which this segment comes into the child_objects list in the
+     * storage_object_t for the segment.  Additionally, the caller must add the
+     * storage_object_t for the disk segment to the parent_objects list in the
+     * storage_object_t for the logical disk.
+     */
+    int (*allocate_segment)(char * name,
+                            storage_object_t * * new_segment);
+
+    /*
+     * Free a storage_object_t for a disk_segment.
+     */
+    int (*free_segment)(storage_object_t * segment);
+
+    /*
+     * Allocate a storage_container_t structure.  The caller fills in the
+     * objects_consumed and objects_produced lists in the container.  The caller
+     * fills in the appropriate consuming_container and producing_container
+     * fields in the storage_object_t(s) that are consumed or produced by the
+     * container.
+     */
+    int (*allocate_container)(char * name,
+                              storage_container_t * * new_container);
+
+    /*
+     * Free a storage_container_t structure.
+     */
+    int (*free_container)(storage_container_t * container);
+
+    /*
+     * Allocate a storage_object_t for a storage_region.  The caller is
+     * responsible for putting the storage_object_t from which this region comes
+     * into the child_objects list in the storage_object_t for the region.
+     * Additionally, the caller must add the storage_object_t for the region to
+     * the parent_objects list in the storage_object_t from which this region
+     * comes.
+     */
+    int (*allocate_region)(char * name,
+                           storage_object_t * * new_region);
+
+    /*
+     * Free the storage_region structure.
+     */
+    int (*free_region)(storage_object_t * region);
+
+    /*
+     * Allocate a storage_object_t for an EVMS object.  The caller is
+     * responsible for putting the storage_object_t from which this EVMS object
+     * comes into the child_objects list in the storage_object_t for the EVMS
+     * object.  Additionally, the caller must add the storage_object_t for the
+     * EVMS object to the parent_objects list in the storage_object_t from which
+     * this EVMS object comes.
+     */
+    int (*allocate_evms_object)(char * name,
+                                storage_object_t * * new_object);
+
+    /*
+     * Free a storage_object_t for an EVMS object.
+     */
+    int (*free_evms_object)(storage_object_t * object);
+
+    /*
+     * engine_alloc is the generic memory allocation service provided by the
+     * Engine.  For any memory that plug-ins return to the Engine, the plug-in
+     * must use the same malloc() that the Engine uses so that the Engine can
+     * properly free() the memory.  To assist the plug-ins, the Engine provides
+     * a common allocation function which the plug-ins can use so that all
+     * memory allocations are managed by the same memory manager.  Memory will
+     * be zero filled.
+     */
+    void * (*engine_alloc)(u_int32_t size);
+
+    /*
+     * engine_free is the generic memory deallocation service provided by the
+     * Engine.
+     */
+    void (*engine_free)(void *);
+
+    /*
+     * Check if there are any changes pending in the Engine.
+     */
+    BOOLEAN (*changes_pending)(void);
+
+    /*
+     * Tell the Engine that there are changes pending, i.e., there is stuff to
+     * be committed to disk.
+     */
+    void (*set_changes_pending)(void);
+
+    /*
+     * Check if the Engine is in the process of committing changes.
+     */
+    BOOLEAN (*commit_in_progress)(void);
+
+    /*
+     * Write data to the Engine's log file.
+     */
+    int (*write_log_entry)(debug_level_t     level,
+                           plugin_record_t * plugin,
+                           char            * fmt,
+                           ...);
+
+    /*
+     * Calculate a 32-bit CRC for a buffer of a given size.
+     * On the first call to calculate_CRC() the CRC parameter must be
+     * 0xffffffff.
+     * calculate_CRC() can be called multiple times to get the CRC for an
+     * aggregate of buffers.  To do so, subsequent calls set the CRC parameter
+     * to the resulting CRC that was returned from the previous call.
+     * To calculate a new CRC, the CRC parameter must be set to 0xffffffff.
+     */
+    u_int32_t (*calculate_CRC)(u_int32_t crc,
+                               void    * buffer,
+                               u_int32_t buffer_size);
+
+    /*
+     * Calculate a checksum on a buffer of given size.  This Engine service
+     * actually issues an ioctl() to the EVMS kernel to use the kernel's
+     * checksum function so that checksums are consistent with the runtime
+     * code.  An error code is returned if the ioctl to the kernel fails.
+     * "insum" is the initial checksum value, useful if you are doing a
+     * single checksum on a series of multiple data blocks.
+     */
+    int (*calculate_checksum)(unsigned char * buffer,
+                              int             buffer_size,
+                              unsigned int    insum,
+                              unsigned int  * outsum);
+
+    /*
+     * Add sectors that are to be written with zeros to the Engine's Kill Sector
+     * list.  Should only be called by device managers
+     */
+    int (*add_sectors_to_kill_list)(storage_object_t * disk,     /* Disk on which the sectors reside */
+                                    lba_t              lba,      /* Sector number of the first sector */
+                                                                 /* to wipe out */
+                                    sector_count_t     count);   /* Number of sectors to wipe out */
+
+
+    /*
+     * Tell the Engine that this volume should be rediscovered when the changes
+     * are committed.  Call this function if you make changes to the volume's
+     * underlying objects, regions, etc.  that will have to be discovered by the
+     * kernel runtime code in order to build the volume correctly.
+     * Set sync_fs to TRUE if you want the file system on the volume to
+     * be synced in a safe state before the volume is rediscovered.
+     */
+    int (*rediscover_volume)(logical_volume_t * volume,
+                             BOOLEAN            sync_fs);
+
+    /*
+     * Check to make sure this name is valid and no other object has the same
+     * name.
+     */
+    int (*validate_name)(char * name);
+
+    /*
+     * Register the name for an object.  The Engine will make sure that there is
+     * no other object with the same name.  If the name is not valid (e.g., it's
+     * too long) or another object has already registered the name, an error
+     * will be returned.
+     */
+    int (*register_name)(char * name);
+
+    /*
+     * Unregister the name of an object.
+     */
+    int (*unregister_name)(char * name);
+
+    /*
+     * Ask all the parent objects of this object if they can handle this object
+     * expanding by the specified amount.  Parent plug-ins may modify the size
+     * according to any constrains they have.  If the size has not been changed
+     * by any of the parents, the Engine will return 0.  If all the parents
+     * don't return an error but the size has been updated, the Engine will
+     * return EAGAIN.
+     */
+    int (*can_expand_by)(storage_object_t * object,
+                         sector_count_t   * delta_size);
+
+    /*
+     * Ask all the parent objects of this object if they can handle this object
+     * shrinking by the specified amount.  Parent plug-ins may modify the size
+     * according to any constrains they have.  If the size has not been changed
+     * by any of the parents, the Engine will return 0.  If all the parents
+     * don't return an error but the size has been updated, the Engine will
+     * return EAGAIN.
+     */
+    int (*can_shrink_by)(storage_object_t * object,
+                         sector_count_t   * delta_size);
+
+    /*
+     * Send a message to the user interface.  This service can be used in three
+     * ways.
+     *
+     * 1) Send a notification message to the user expecting no response.
+     *
+     * user_message(plugin_record, NULL, NULL, message_fmt, ...);
+     *
+     * 2) Ask a question and get one item selected from a list of two or more
+     *    items.
+     *
+     * char * choices = {string1, string2, ..., NULL};
+     * user_message(plugin_record, &answer, choices, message_fmt, ...);
+     *
+     * The "choices" parameter is a NULL terminated array of strings that
+     * describe each of the choices.  "*answer" *must* be initialized to the
+     * default response.  The UI will present the message and the choices to
+     * the user.  On return, *answer will contain the index of the selected
+     * choice string.
+     */
+    int (*user_message)(plugin_record_t * plugin,
+                        int             * answer,
+                        char          * * choice_text,
+                        char            * message_fmt,
+                        ...);
+
+    /*
+     * user_communication() uses the option_descriptor_t structures to convey a
+     * group of choices to the user.  Use this service when you have a complex
+     * list of things to ask of the user, e.g., they are of several different
+     * types (strings, ints, etc), they have constraints on their selection, or
+     * they may have dependencies on each other.
+     *
+     * The Engine will create a EVMS_Task_Message task for the UI.  The UI will
+     * use the task when calling the evms_get_option_descriptor(),
+     * evms_set_option_value(), etc.  APIs for getting and setting options.
+     * Your plug-in will be called on its set_option() function with the task
+     * context.  The action will be EVMS_Task_Message, the task object will be
+     * set to the object_instance parameter that you provide on the call to
+     * user_communication().
+     *
+     * The "message_text" will be treated by the UI as a title for the options
+     * that are presented.  "options" is an array of option_descriptor_t
+     * structures.  Each of the option descriptors *must* have an initial value.
+     */
+    int (*user_communication)(void                * object_instance,
+                              char                * message_text,
+                              option_desc_array_t * options);
+
+    /*
+     * Can this object be renamed?  The Engine will figure out if there are any
+     * restrictions that would prevent the object from being renamed, e.g., the
+     * object is the topmost object of a compatibility volume (the volume name
+     * will have been derived from the object) and the volume is mounted.  The
+     * Engine won't allow a volume that is mounted to be renamed.  If the
+     * object cannot be renamed, the Engine will return an error code that
+     * (hopefully) gives some indication as to why the rename is not allowed.
+     * Plug-ins call this Engine service before allowing their object name to
+     * be changed by a set_info() call.
+     */
+    int (*can_rename)(storage_object_t * object);
+
+    /*
+     * Is this volume mounted?  If you want to know the name of the mount point,
+     * specify a location in mount_name where the service will place a pointer
+     * to malloced memory that contains the mount point name.  Remember to free
+     * the string when you are finished with it.  If you do not want to know the
+     * mount point and not have the hassle of freeing the memory, specify NULL
+     * for mount_name.
+     */
+    BOOLEAN (*is_mounted)(char   * volume_name,
+                          char * * mount_name);
+
+} engine_functions_t;
+
+
+typedef struct fsim_functions_s {
+    int (*setup_evms_plugin)(engine_mode_t        mode,
+                             engine_functions_t * functions);
+
+    void (*cleanup_evms_plugin)(void);
+
+    /*
+     * Does this FSIM manage the file system on this volume?
+     * Return 0 for "yes", else a reason code.
+     */
+    int (*is_this_yours)(logical_volume_t * volume);
+
+    /*
+     * Get the current size of the file system on this volume.
+     */
+    int (*get_fs_size)(logical_volume_t * volume,
+                       sector_count_t   * fs_size);
+
+    /*
+     * Get the file system size limits for this volume.
+     */
+    int (*get_fs_limits)(logical_volume_t * volume,
+                         sector_count_t   * fs_min_size,
+                         sector_count_t   * fs_max_size,
+                         sector_count_t   * vol_max_size);
+
+    /*
+     * Can you install your file system on this volume?
+     */
+    int (*can_mkfs)(logical_volume_t * volume);
+
+    /*
+     * Can you remove your file system from this volume?
+     */
+    int (*can_unmkfs)(logical_volume_t * volume);
+
+    /*
+     * Can you fsck this volume?
+     */
+    int (*can_fsck)(logical_volume_t * volume);
+
+    /*
+     * Can you defrag this volume?
+     */
+    int (*can_defrag)(logical_volume_t * volume);
+
+    /*
+     * Can you expand this volume by the amount specified?
+     * If your file system cannot handle expansion at all, return an
+     * error code that indicates why it cannot be expanded..
+     * If your file system can expand but cannot handle having unused
+     * space after the end of your file system, adjust the *delta_size
+     * to the maximum you allow and return 0.
+     * If your file system cannot fill the resulting size but your file
+     * system can handle extra unused space after the end of the file
+     * system, then do not change the *delta_size and return 0.
+     */
+    int (*can_expand_by)(logical_volume_t * volume,
+                         sector_count_t   * delta_size);
+
+    /*
+     * Can you shrink this volume by the amount specified?
+     * If your file system cannot handle shrinking at all, return an
+     * error code that indicates why it cannot be shrunk.
+     * If your file system can shrink but the *delta_size is too much to
+     * shrink by, adjust the *delta_size to the maximum shrinkage you allow and
+     * return 0.
+     */
+    int (*can_shrink_by)(logical_volume_t * volume,
+                         sector_count_t   * delta_size);
+
+    /*
+     * Install your file system on the volume.
+     */
+    int (*mkfs)(logical_volume_t * volume,
+                option_array_t   * options);
+
+    /*
+     * Remove your file system from the volume.  This could be as simple as
+     * wiping out critical sectors, such as a superblock, so that you will
+     * no longer detect that your file system is installed on the volume.
+     */
+    int (*unmkfs)(logical_volume_t * volume);
+
+    /*
+     * Run fsck on the volume.
+     */
+    int (*fsck)(logical_volume_t * volume,
+                option_array_t   * options);
+
+    /*
+     * Defragment on the volume.
+     */
+    int (*defrag)(logical_volume_t * volume,
+                  option_array_t   * options);
+
+    /*
+     * Expand the volume to new_size.  If the volume is not expanded exactly to
+     * new_size, set new_sie to the new_size of the volume.
+     */
+    int (*expand)(logical_volume_t * volume,
+                  sector_count_t   * new_size);
+
+    /*
+     * Shrink the volume to new_size.  If the volume is not expanded exactly to
+     * new_size, set new_size to the new_size of the volume.
+     */
+    int (*shrink)(logical_volume_t * volume,
+                  sector_count_t     requested_size,
+                  sector_count_t   * new_size);
+
+    /*
+     * Return the total number of supported options for the specified task.
+     */
+    int (*get_option_count)(task_context_t * context);
+
+    /*
+     * Fill in the initial list of acceptable objects.  Fill in the minimum and
+     * maximum number of objects that must/can be selected.  Set up all initial
+     * values in the option_descriptors in the context record for the given
+     * task.  Some fields in the option_descriptor may be dependent on a
+     * selected object.  Leave such fields blank for now, and fill in during the
+     * set_objects call.
+     */
+    int (*init_task)(task_context_t * context);
+
+    /*
+     * Examine the specified value, and determine if it is valid for the task
+     * and option_descriptor index. If it is acceptable, set that value in the
+     * appropriate entry in the option_descriptor. The value may be adjusted
+     * if necessary/allowed. If so, set the effect return value accordingly.
+     */
+    int (*set_option)(task_context_t * context,
+                      u_int32_t        index,
+                      value_t        * value,
+                      task_effect_t  * effect);
+
+    /*
+     * Validate the volumes in the selected_objects dlist in the task context.
+     * Remove from the selected objects lists any volumes which are not
+     * acceptable.  For unacceptable volumes, create a declined_handle_t
+     * structure with the reason why it is not acceptable, and add it to the
+     * declined_volumes dlist.  Modify the acceptable_objects dlist in the task
+     * context as necessary based on the selected objects and the current
+     * settings of the options.  Modify any option settings as necessary based
+     * on the selected objects.  Return the appropriate task_effect_t settings
+     * if the object list(s), minimum or maximum objects selected, or option
+     * settings have changed.
+     */
+    int (*set_volumes)(task_context_t * context,
+                       dlist_t          declined_volumes,    /* of type declined_handle_t */
+                       task_effect_t  * effect);
+
+
+    /*
+     * Return any additional information that you wish to provide about the
+     * volume.  The Engine provides an external API to get the information
+     * stored in the logical_volume_t.  This call is to get any other
+     * information about the volume that is not specified in the
+     * logical_volume_t.  Any piece of information you wish to provide must be
+     * in an extended_info_t structure.  Use the Engine's engine_alloc() to
+     * allocate the memory for the extended_info_t.  Also use engine_alloc() to
+     * allocate any strings that may go into the extended_info_t.  Then use
+     * engine_alloc() to allocate an extended_info_array_t with enough entries
+     * for the number of extended_info_t structures you are returning.  Fill
+     * in the array and return it in *info.
+     * If you have extended_info_t descriptors that themselves may have more
+     * extended information, set the EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE flag
+     * in the extended_info_t flags field.  If the caller wants more information
+     * about a particular extended_info_t item, this API will be called with a
+     * pointer to the storage_object_t and with a pointer to the name of the
+     * extended_info_t item.  In that case, return an extended_info_array_t with
+     * further information about the item.  Each of those items may have the
+     * EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE flag set if you desire.  It is your
+     * responsibility to give the items unique names so that you know which item
+     * the caller is asking additional information for.  If info_name is NULL,
+     * the caller just wants top level information about the object.
+     */
+    int (*get_volume_info)(logical_volume_t        * volume,
+                           char                    * info_name,
+                           extended_info_array_t * * info);
+
+    /*
+     * Apply the settings of the options to the given volume.
+     */
+    int (*set_volume_info)(logical_volume_t * volume,
+                           option_array_t   * options);
+
+    /*
+     * Return any additional information that you wish to provide about your
+     * plug-in.  The Engine provides an external API to get the information
+     * stored in the plugin_record_t.  This call is to get any other
+     * information about the plug-in that is not specified in the
+     * plugin_record_t.  Any piece of information you wish to provide must be
+     * in an extended_info_t structure.  Use the Engine's engine_alloc() to
+     * allocate the memory for the extended_info_t.  Also use engine_alloc() to
+     * allocate any strings that may go into the extended_info_t.  Then use
+     * engine_alloc() to allocate an extended_info_array_t with enough entries
+     * for the number of extended_info_t structures you are returning.  Fill
+     * in the array and return it in *info.
+     * If you have extended_info_t descriptors that themselves may have more
+     * extended information, set the EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE flag
+     * in the extended_info_t flags field.  If the caller wants more information
+     * about a particular extended_info_t item, this API will be called with a
+     * pointer to the storage_object_t and with a pointer to the name of the
+     * extended_info_t item.  In that case, return an extended_info_array_t with
+     * further information about the item.  Each of those items may have the
+     * EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE flag set if you desire.  It is your
+     * responsibility to give the items unique names so that you know which item
+     * the caller is asking additional information for.  If info_name is NULL,
+     * the caller just wants top level information about the object.
+     */
+    int (*get_plugin_info)(char                    * info_name,
+                           extended_info_array_t * * info);
+
+#ifndef ABI_EVMS_1_0
+    /*
+     * Return an array of private actions that you support for this volume.
+     */
+    int (*get_plugin_functions)(logical_volume_t        * volume,
+                                function_info_array_t * * actions);
+
+    /*
+     * Execute the private action on the volume.
+     */
+    int (*plugin_function)(logical_volume_t * volume,
+                           task_action_t      action,
+                           dlist_t            objects,
+                           option_array_t   * options);
+#endif
+    
+    /*
+     * Generic method for communicating with your plug-in.
+     */
+    int (*direct_plugin_communication)(void  * thing,
+                                       BOOLEAN target_kernel_plugin,
+                                       void  * arg);
+
+} fsim_functions_t;
+
+
+typedef struct plugin_functions_s {
+    int (*setup_evms_plugin)(engine_mode_t        mode,
+                             engine_functions_t * functions);
+
+    void (*cleanup_evms_plugin)(void);
+
+#ifndef ABI_EVMS_1_0
+    /*
+     * Can you apply your plug-in to the input_object?  If yes, return the size
+     * of the object you would create.
+     * The Engine will only call this function on EVMS feature plug-ins.
+     * Other plug-ins may choose whether or not to support this API.
+     */
+    int (*can_add_feature)(storage_object_t * input_object,
+                           sector_count_t   * size);
+#endif
+
+    /*
+     * Can you delete this object?
+     */
+    int (*can_delete)(storage_object_t * object);
+
+#ifndef ABI_EVMS_1_0
+    /*
+     * Can you unassign your plug-in from this object?
+     */
+    int (*can_unassign)(storage_object_t * object);
+#endif
+
+    /*
+     * Can you expand this object?  If yes, build an expand_object_info_t and
+     * add it to the expand_points list.  If you can't expand, but allow one of
+     * your children to expand, call can_expand on whichever child you will
+     * allow to expand.  If you can not handle expanding below you, do not pass
+     * the command down to your child.
+     */
+    int (*can_expand)(storage_object_t * object,
+                      sector_count_t   * expand_limit,      // a delta size
+                      dlist_t            expand_points);    // of type expand_object_info_t,
+                                                            // tag = EXPAND_OBJECT_TAG
+
+    /*
+     * Can you allow your child object to expand by "size"?  Return 0 if yes,
+     * else an error code.  "size" is the delta expand BY size, not the
+     * resulting size.  Update the "size" if your object would expand by a
+     * different delta size when your child object expanded by the given size.
+     */
+    int (*can_expand_by)(storage_object_t * object,
+                         sector_count_t   * size);
+
+    /*
+     * Can you shrink this object?  If yes, build a shrink_object_info_t and
+     * add it to the shrink_points list.  If you can't shrink, but allow one of
+     * your children to shrink, call can_shrink on whichever child you will
+     * allow to shrink.  If you can not handle shrinking below you, do not pass
+     * the command down to your child.
+     */
+    int (*can_shrink)(storage_object_t * object,
+                      sector_count_t   * shrink_limit,      // a delta size
+                      dlist_t            shrink_points);    // of type shrink_object_info_t,
+                                                            // tag = SHRINK_OBJECT_TAG
+
+
+    /*
+     * Can you allow your child object to shrink by "size"?  Return 0 if yes,
+     * else an error code.  "size" is the delta shrink BY size, not the
+     * resulting size.  Update the "size" if your object would shrink by a
+     * different delta size when your child object shrunk by the given size.
+     */
+    int (*can_shrink_by)(storage_object_t * object,
+                         sector_count_t   * size);
+
+    /*
+     * Can you move this object?
+     */
+    int (*can_move)(storage_object_t * object);
+
+    /*
+     * Will you allow your object to be made into a volume?  (We don't see
+     * any reason why you wouldn't.)  Will you allow a volume to be reverted
+     * off the top of your object?  The "flag" parameter says whether the
+     * volume is to be created (TRUE) or removed (FALSE).
+     */
+    int (*can_set_volume)(storage_object_t * object,
+                          BOOLEAN            flag);
+
+    /*
+     * Claim objects by removing them from the list.  Create a storage_object_t
+     * for the object you are discovering, fill in the appropriate fields and
+     * put the new object on the output_objects list.  If you do not claim an
+     * object from the input list, then just copy/move it to the output list.
+     * The input list can be modified at will.  The output list must contain
+     * all the storage objects in the system after yours are discovered, i.e.,
+     * it is the input list, minus the objects you claim, plus the objects you
+     * produce.
+     */
+    int (*discover)(dlist_t input_objects,
+                    dlist_t output_objects,
+                    BOOLEAN final_call);
+
+    /*
+     * Create storage_object_t(s) from the list of objects using the given
+     * options.  Return the newly allocated storage_object_t(s) in new_objects
+     * list.
+     */
+    int (*create)(dlist_t          input_objects,
+                  option_array_t * options,
+                  dlist_t          output_objects);
+
+#ifndef ABI_EVMS_1_0
+    /*
+     * Assign your plug-in to produce storage objects from the given storage
+     * object.  This function makes sense mainly for segment managers that are
+     * assigned to disks (or segments).
+     */
+    int (*assign)(storage_object_t * object,
+                  option_array_t   * options);
+#endif
+
+    /*
+     * Delete the object.  Free any privately allocated data.  Remove your
+     * parent pointer from your child objects.  Do any cleanup necessary to
+     * remove your plug-in from your child objects.  Put your object's children
+     * from the object's child_objects dlist_t onto the dlist_t provided in the
+     * second parameter.  Call the Engine's free_?????t() to free the object.
+     */
+    int (*delete)(storage_object_t * object,
+                  dlist_t            child_objects);
+
+#ifndef ABI_EVMS_1_0
+    /*
+     * Unassign your plug-in from producing storage objects from the given
+     * storage object.  This function makes sense mainly for segment managers
+     * that are assigned to disks (or segments).
+     */
+    int (*unassign)(storage_object_t * object);
+#endif
+
+    /*
+     * If the "object" is not the "expand_object", then your child is going to
+     * expand.  Do any necessary work to get ready for your child to expand,
+     * e.g., read in meta data, then call expand() on your child object which
+     * will expand.  Upon return from the call to your child's expand(), do
+     * any work necessary to adjust this object to account for the child
+     * object's new size, e.g., update the location of meta data.
+     * If the "object" is the same as the "expand_object", then this is the
+     * object targeted for expanding.  Expand the object according to the
+     * input_objects given and the options selected.
+     */
+    int (*expand)(storage_object_t * object,
+                  storage_object_t * expand_object,
+                  dlist_t            input_objects,
+                  option_array_t   * options);
+
+    /*
+     * If the "object" is not the "shrink_object", then your child is going to
+     * shrink.  Do any necessary work to get ready for your child to shrink,
+     * e.g., read in meta data, then call shrink() on your child object which
+     * will shrink.  Upon return from the call to your child's shrink(), do
+     * any work necessary to adjust this object to account for the child
+     * object's new size, e.g., update the location of meta data.
+     * If the "object" is the same as the "shrink_object", then this is the
+     * object targeted for shrinking.  Shrink the object according to the
+     * input_objects given and the options selected.
+     */
+    int (*shrink)(storage_object_t * object,
+                  storage_object_t * shrink_object,
+                  dlist_t            input_objects,
+                  option_array_t   * options);
+
+    /*
+     * Move the contents of the source object to the target object using the
+     * given options.
+     */
+    int (*move)(storage_object_t * source,
+                storage_object_t * target,
+                option_array_t   * options);
+
+    /*
+     * This call notifies you that your object is being made into (or part of)
+     * a volume or that your object is no longer part of a volume.  The "flag"
+     * parameter indicates whether the volume is being created (TRUE) or
+     * removed (FALSE).
+     */
+    void (*set_volume)(storage_object_t * object,
+                       BOOLEAN            flag);
+
+    /*
+     * Put sectors on the kill list.  The plug-in translates the lsn and count
+     * into lsn(s) and count(s) for its child object(s) and calls the child
+     * object's add_sectors_to_kill_list().
+     * The Device Manager calls the Engine's add_sectors_to_kill_list service
+     * to put the sectors on the Engine's kill list.
+     */
+    int (*add_sectors_to_kill_list)(storage_object_t * object,
+                                    lsn_t              lsn,
+                                    sector_count_t     count);
+
+    /*
+     * Write your plug-ins data, e.g., feature header and feature meta data, to
+     * disk.  Clear the SOFLAG_DIRTY in the storage_object_t(s).
+     * Committing changes in done in several (two for now) phases.  "phase"
+     * says which phase of the commit is being performed.
+     * Write your first copy of meta data during phase 1; write your second
+     * copy of meta data (if you have one) during phase 2.
+     */
+    int (*commit_changes)(storage_object_t * object,
+                          uint               phase);
+
+    /*
+     * Return the total number of supported options for the specified task.
+     */
+    int (*get_option_count)(task_context_t * context);
+
+    /*
+     * Fill in the initial list of acceptable objects.  Fill in the minimum and
+     * maximum number of objects that must/can be selected.  Set up all initial
+     * values in the option_descriptors in the context record for the given
+     * task.  Some fields in the option_descriptor may be dependent on a
+     * selected object.  Leave such fields blank for now, and fill in during the
+     * set_objects call.
+     */
+    int (*init_task)(task_context_t * context);
+
+    /*
+     * Examine the specified value, and determine if it is valid for the task
+     * and option_descriptor index. If it is acceptable, set that value in the
+     * appropriate entry in the option_descriptor. The value may be adjusted
+     * if necessary/allowed. If so, set the effect return value accordingly.
+     */
+    int (*set_option)(task_context_t * context,
+                      u_int32_t        index,
+                      value_t        * value,
+                      task_effect_t  * effect);
+
+    /*
+     * Validate the objects in the selected_objects dlist in the task context.
+     * Remove from the selected objects lists any objects which are not
+     * acceptable.  For unacceptable objects, create a declined_handle_t
+     * structure with the reason why it is not acceptable, and add it to the
+     * declined_objects dlist.  Modify the acceptable_objects dlist in the task
+     * context as necessary based on the selected objects and the current
+     * settings of the options.  Modify any option settings as necessary based
+     * on the selected objects.  Return the appropriate task_effect_t settings
+     * if the object list(s), minimum or maximum objects selected, or option
+     * settings have changed.
+     */
+    int (*set_objects)(task_context_t * context,
+                       dlist_t          declined_objects,    /* of type declined_handle_t */
+                       task_effect_t  * effect);
+
+    /*
+     * Return any additional information that you wish to provide about the
+     * object.  The Engine provides an external API to get the information
+     * stored in the storage_object_t.  This call is to get any other
+     * information about the object that is not specified in the
+     * storage_object_t.  Any piece of information you wish to provide must be
+     * in an extended_info_t structure.  Use the Engine's engine_alloc() to
+     * allocate the memory for the extended_info_t.  Also use engine_alloc() to
+     * allocate any strings that may go into the extended_info_t.  Then use
+     * engine_alloc() to allocate an extended_info_array_t with enough entries
+     * for the number of extended_info_t structures you are returning.  Fill
+     * in the array and return it in *info.
+     * If you have extended_info_t descriptors that themselves may have more
+     * extended information, set the EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE flag
+     * in the extended_info_t flags field.  If the caller wants more information
+     * about a particular extended_info_t item, this API will be called with a
+     * pointer to the storage_object_t and with a pointer to the name of the
+     * extended_info_t item.  In that case, return an extended_info_array_t with
+     * further information about the item.  Each of those items may have the
+     * EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE flag set if you desire.  It is your
+     * responsibility to give the items unique names so that you know which item
+     * the caller is asking additional information for.  If info_name is NULL,
+     * the caller just wants top level information about the object.
+     */
+    int (*get_info)(storage_object_t        * object,
+                    char                    * info_name,
+                    extended_info_array_t * * info);
+
+    /*
+     * Apply the settings of the options to the given object.
+     */
+    int (*set_info)(storage_object_t * object,
+                    option_array_t   * options);
+
+    /*
+     * Return any additional information that you wish to provide about your
+     * plug-in.  The Engine provides an external API to get the information
+     * stored in the plugin_record_t.  This call is to get any other
+     * information about the plug-in that is not specified in the
+     * plugin_record_t.  Any piece of information you wish to provide must be
+     * in an extended_info_t structure.  Use the Engine's engine_alloc() to
+     * allocate the memory for the extended_info_t.  Also use engine_alloc() to
+     * allocate any strings that may go into the extended_info_t.  Then use
+     * engine_alloc() to allocate an extended_info_array_t with enough entries
+     * for the number of extended_info_t structures you are returning.  Fill
+     * in the array and return it in *info.
+     * If you have extended_info_t descriptors that themselves may have more
+     * extended information, set the EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE flag
+     * in the extended_info_t flags field.  If the caller wants more information
+     * about a particular extended_info_t item, this API will be called with a
+     * pointer to the storage_object_t and with a pointer to the name of the
+     * extended_info_t item.  In that case, return an extended_info_array_t with
+     * further information about the item.  Each of those items may have the
+     * EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE flag set if you desire.  It is your
+     * responsibility to give the items unique names so that you know which item
+     * the caller is asking additional information for.  If info_name is NULL,
+     * the caller just wants top level information about the object.
+     */
+    int (*get_plugin_info)(char                    * info_name,
+                           extended_info_array_t * * info);
+
+    /*
+     * Convert lsn and count to lsn and count on the child object(s) and and
+     * call the read function of child objects.
+     */
+    int (*read)(storage_object_t * object,
+                lsn_t              lsn,
+                sector_count_t     count,
+                void             * buffer);
+
+    /*
+     * Convert lsn and count to lsn and count on the child object(s) and and
+     * call the write function of child objects.
+     */
+    int (*write)(storage_object_t * object,
+                 lsn_t              lsn,
+                 sector_count_t     count,
+                 void             * buffer);
+
+#ifndef ABI_EVMS_1_0
+    /*
+     * Return an array of private actions that you support for this object.
+     */
+    int (*get_plugin_functions)(storage_object_t        * object,
+                                function_info_array_t * * actions);
+
+    /*
+     * Execute the private action on the object.
+     */
+    int (*plugin_function)(storage_object_t * object,
+                           task_action_t      action,
+                           dlist_t            objects,
+                           option_array_t   * options);
+#endif
+
+    /*
+     * Generic method for communicating with your plug-in.
+     */
+    int (*direct_plugin_communication)(void    * thing,
+                                       BOOLEAN   target_kernel_plugin,
+                                       void    * arg);
+
+} plugin_functions_t;
+
+
+typedef struct container_functions_s {
+
+    /*
+     * Can you create a container from this list of data segments?
+     */
+    int (*can_create_container)(dlist_t objects);
+
+    /*
+     * Can you destroy the container?  You must check to be sure that no regions
+     * are exported from this container.
+     */
+    int (*can_delete_container)(storage_container_t * container);
+
+    /*
+     * Can you add this object to the container?
+     * Return 0 if you can, else return an error code.
+     */
+    int (*can_add_object)(storage_object_t    * object,
+                          storage_container_t * container);
+
+    /*
+     * Can you remove this object from the container that currently consumes
+     * it?  Return 0 if you can, else return an error code.
+     */
+    int (*can_remove_object)(storage_object_t * object);
+
+    /*
+     * Create and fill in the container adding newly created unallocated objects
+     * produced as appropriate.  The plug-in must claim the objects, as it does
+     * in discovery.  Mark the container dirty.  Must use allocate_container
+     * engine API to allocate the container structure.
+     */
+    int (*create_container)(dlist_t                 objects,
+                            option_array_t        * options,
+                            storage_container_t * * container);
+
+    /*
+     * Engine will remove the object from its current container before calling
+     * this API.  Claim the object and add it to a container objects_consumed
+     * list.  Mark the container dirty.  Update/allocate the unallocated object
+     * that is exported from the container.  If container is NULL, add the
+     * object to default (or unassigned) container.
+     */
+    int (*add_object)(storage_object_t    * object,
+                      storage_container_t * container,
+                      option_array_t      * options);
+
+    /*
+     * Transfer the object from its current container to the specified
+     * container.  Mark the container dirty.  If container is NULL, transfer
+     * the object to the default (or unassigned) container.
+     */
+    int (*transfer_object)(storage_object_t    * object,
+                           storage_container_t * container,
+                           option_array_t      * options);
+
+    /*
+     * Remove object from its current container.  Make sure there are no
+     * allocated objects produced by the container that are using space in the
+     * object.  Does not destroy segment.
+     */
+    int (*remove_object)(storage_object_t * object);
+
+    /*
+     * Destroy the container.  Make sure there are no allocated objects being
+     * produced by the container.  Put your consumed objects from the
+     * container's objects_consumed dlist_t onto the dlist_t provided in the
+     * second parameter.  Free any private data, then use the Engine's
+     * free_container() to deallocate the container object.
+     */
+    int (*delete_container)(storage_container_t * container,
+                            dlist_t               objects_consumed);
+
+    /*
+     * Write any container meta data, to disk.  Clear the SCFLAG_DIRTY in the
+     * container.
+     * Committing changes in done in several (two for now) phases.  "phase"
+     * says which phase of the commit is being performed.
+     * Write your first copy of meta data during phase 1; write your second
+     * copy of meta data (if you have one) during phase 2.
+     */
+    int (*commit_container_changes)(storage_container_t * container,
+                                    uint                  phase);
+
+    /*
+     * Return any additional information that you wish to provide about the
+     * container.  The Engine provides an external API to get the information
+     * stored in the storage_container_t.  This call is to get any other
+     * information about the container that is not specified in the
+     * storage_container_t.  Any piece of information you wish to provide must
+     * be in an extended_info_t structure.  Use the Engine's engine_alloc() to
+     * allocate the memory for the extended_info_t.  Also use engine_alloc() to
+     * allocate any strings that may go into the extended_info_t.  Then use
+     * engine_alloc() to allocate an extended_info_array_t with enough entries
+     * for the number of extended_info_t structures you are returning.  Fill
+     * in the array and return it in *info.
+     * If you have extended_info_t descriptors that themselves may have more
+     * extended information, set the EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE flag
+     * in the extended_info_t flags field.  If the caller wants more information
+     * about a particular extended_info_t item, this API will be called with a
+     * pointer to the storage_container_t and with a pointer to the name of the
+     * extended_info_t item.  In that case, return an extended_info_array_t with
+     * further information about the item.  Each of those items may have the
+     * EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE flag set if you desire.  It is your
+     * responsibility to give the items unique names so that you know which item
+     * the caller is asking additional information for.  If info_name is NULL,
+     * the caller just wants top level information about the object.
+     */
+    int (*get_container_info)(storage_container_t     * container,
+                              char                    * info_name,
+                              extended_info_array_t * * info);
+
+    /*
+     * Apply the settings of the options to the given container.
+     */
+    int (*set_container_info)(storage_container_t * container,
+                              option_array_t      * options);
+
+#ifndef ABI_EVMS_1_0
+    /*
+     * Return an array of private actions that you support for this container.
+     */
+    int (*get_plugin_functions)(storage_container_t     * container,
+                                function_info_array_t * * actions);
+
+    /*
+     * Execute the private action on the container.
+     */
+    int (*plugin_function)(storage_container_t * container,
+                           task_action_t         action,
+                           dlist_t               objects,
+                           option_array_t      * options);
+#endif
+
+} container_functions_t;
+
+#endif
+
diff --git a/lib/evms/plugin.h b/lib/evms/plugin.h
new file mode 100644
index 0000000..acb8625
--- /dev/null
+++ b/lib/evms/plugin.h
@@ -0,0 +1,32 @@
+/*
+ *
+ *   Copyright (c) International Business Machines  Corp., 2001
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Module: plugin.h
+ */
+
+#ifndef EVMS_PLUGIN_H_INCLUDED
+  #define EVMS_PLUGIN_H_INCLUDED 1
+
+  #include <dlist.h>
+  #include <common.h>
+  #include <options.h>
+
+  #include <enginestructs.h>
+  #include <plugfuncs.h>
+
+#endif