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