Skip to Content.
Sympa Menu

sm-commit - [SM-Commit] GIT changes to master cauldron by Justin Boffemmyer (b158dbe27d8080df83eef55fee94c2d1e1922e57)

sm-commit AT lists.ibiblio.org

Subject: Source Mage code commit list

List archive

Chronological Thread  
  • From: Justin Boffemmyer <scm AT sourcemage.org>
  • To: sm-commit AT lists.ibiblio.org
  • Subject: [SM-Commit] GIT changes to master cauldron by Justin Boffemmyer (b158dbe27d8080df83eef55fee94c2d1e1922e57)
  • Date: Thu, 30 Jun 2011 10:15:30 -0500

GIT changes to master cauldron by Justin Boffemmyer <flux AT sourcemage.org>:

cauldron/data/config/build.conf | 2
cauldron/data/config/commands.conf | 28 ++++---
cauldron/lib/errorcodes | 2
cauldron/lib/lib.chroot | 89 ++++++++++++++++++-------
cauldron/lib/lib.init | 4 +
cauldron/lib/lib.toolchain | 131
+++++++++++++++++++++++++++++++++++++
cauldron/lib/libcauldron | 11 +++
7 files changed, 230 insertions(+), 37 deletions(-)

New commits:
commit b158dbe27d8080df83eef55fee94c2d1e1922e57
Author: Justin Boffemmyer <flux AT sourcemage.org>
Commit: Justin Boffemmyer <flux AT sourcemage.org>

cauldron: config: use hyphen for tar options

Prefixing a hyphen to the different tar options feels more "correct",
since they are "options" to tar (as opposed to command names). Change
all occurrences of the tar "options" in the commands.conf file to be
preceded by a hyphen.

commit 87ea5cd8858c08c9186fce9739ce8d24f55abc0f
Author: Justin Boffemmyer <flux AT sourcemage.org>
Commit: Justin Boffemmyer <flux AT sourcemage.org>

cauldron: config: fix copy/pasted comments

A few of the CAULDRON_CMD_ comments (in particular UNPACK_) were
inaccurate because they had been copy/pasted from a single such
variables description. They have no been modified to more accurately
describe the respective command definitions.

commit 16e5b257d677928e1741f508a011f26e3e1fea14
Author: Justin Boffemmyer <flux AT sourcemage.org>
Commit: Justin Boffemmyer <flux AT sourcemage.org>

cauldron: config: fix ramfs command piping

The pipes in the ramfs creation command need to be escaped, or they will
be interpreted by the shell at source/load time rather than at call/run
time.

commit 6950ad57f637e14f56bdf0c19bb1e88b02ae3dc0
Author: Justin Boffemmyer <flux AT sourcemage.org>
Commit: Justin Boffemmyer <flux AT sourcemage.org>

cauldron: add CMD var for unpacking general tars

Add a CAULDRON_CMD_ global variable to hold the command used to unpack
arbitrary (compressed) tarballs.

commit 698070a107e6bc4b2ba8517b970e90c700c9da41
Author: Justin Boffemmyer <flux AT sourcemage.org>
Commit: Justin Boffemmyer <flux AT sourcemage.org>

cauldron: more chroot error testing/prevention

For cases where chroot execution is needed, try to ensure that we have
entered a chroot before trying to execute. If there are errors with the
chroot, report the errors rather than trying to run commands inside a
non-existent chroot.

commit e6bd81d240b3687b1a87fb754a909d867d1dbabd
Author: Justin Boffemmyer <flux AT sourcemage.org>
Commit: Justin Boffemmyer <flux AT sourcemage.org>

cauldron: chroots are tracked with list of users

Chroots are now treated as single objects that can have multiple
dependees, or users. When cauldron_chroot_init is called on a chroot
that is already initialized, the user count is increased, rather than
producing an error. When a subsequent cauldron_chroot_done is
encountered, the user count is checked, and the chroot is cleaned up
only if the final user is the one that made the call. This also enables
a sort of context-switching for cauldron_chroot calls.

commit ee2490416803d3c25027e8f6b1912955f14391e6
Author: Justin Boffemmyer <flux AT sourcemage.org>
Commit: Justin Boffemmyer <flux AT sourcemage.org>

cauldron: lib.init: missing 'then' keywords

Due to copy/pasting, several if blocks were missing the corresponding
'then' keyword. This has now been corrected.

commit 0c8d0f859ea955477b4989324087cd3e6e347066
Author: Justin Boffemmyer <flux AT sourcemage.org>
Commit: Justin Boffemmyer <flux AT sourcemage.org>

cauldron: toolchain learns to use baseroots

lib.toolchain has gained the ability to use pre-built basesystem
chroots. The baseroot can either be downloaded fresh, unpacked from an
already downloaded/created (compressed) archive, or an already unpacked
directory (i.e., a chroot directory ready for use). There are also
functions to verify the usability of the chroot post-unpacking, by
ensuring that it has some necessary directories as well as being able to
compile and execute a very simple C source file.

For later cross-compilation functionality (an eventual goal of cauldron
is automated cross-compilation to be able to build farm ISOs for
multiple target architectures), the compiler test will have to be
modified to not attempt to run the compiled binary, unless through a VM,
if the chroot is to be used for cross builds.

commit 7d4bb17af1d044822fdbff8f03cc0805d9dae4fc
Author: Justin Boffemmyer <flux AT sourcemage.org>
Commit: Justin Boffemmyer <flux AT sourcemage.org>

cauldron: fix typos in config files

Had a few typos in variable definitions in some of the config files.

diff --git a/cauldron/data/config/build.conf b/cauldron/data/config/build.conf
index 2f1b8cb..2eb904f 100644
--- a/cauldron/data/config/build.conf
+++ b/cauldron/data/config/build.conf
@@ -12,7 +12,7 @@
CAULDRON_TOOLCHAIN="${CAULDRON_TOOLCHAIN:-$CAULDRON_DATA/$CAULDRON_ARCH/toolchai

# name of the local on-disk basesystem chroot image to use for the
# baseroot method (i.e. cauldron_toolchain_baseroot)
-CAULDRON_BASEROOT="${CAULDRON_BASEROOT:-smgl-stable-0.47-basesytem-$CAULDRON_ARCH.tar.bz2}"
+CAULDRON_BASEROOT="${CAULDRON_BASEROOT:-smgl-stable-0.47-basesystem-$CAULDRON_ARCH.tar.bz2}"
# URL to a basesystem chroot for use with cauldron_toolchain_baseroot
# only used when generating CAULDRON_BUILD from the baseroot method

CAULDRON_BASEROOT_URL="${CAULDRON_BASEROOT_URL:-http://download.sourcemage.org/image/official/$CAULDRON_BASEROOT}";
diff --git a/cauldron/data/config/commands.conf
b/cauldron/data/config/commands.conf
index 9a269b9..be78ae5 100644
--- a/cauldron/data/config/commands.conf
+++ b/cauldron/data/config/commands.conf
@@ -36,7 +36,7 @@
[[ -n "${CAULDRON_CMD_ARCHIVE_SYS[@]}" ]] ||
CAULDRON_CMD_ARCHIVE_SYS=(
tar
- cf "$CAULDRON_BUILD"/"${CAULDRON_SYS_NAME}.tar"
+ -cf "$CAULDRON_BUILD"/"${CAULDRON_SYS_NAME}.tar"
-C "$CAULDRON_SYS"
)

@@ -46,34 +46,40 @@
bzip2
)

-# command to unpack a baseroot archive into the cauldron build
+# command for (un)archiving files/directory trees
[[ -n "${CAULDRON_CMD_TAR[@]}" ]] ||
CAULDRON_CMD_TAR=(
tar
)

-# command to unpack a sorcery archive into the cauldron build
+# command to unpack an arbitrary archive
+[[ -n "${CAULDRON_CMD_TAR_UNPACK[@]}" ]] ||
+ CAULDRON_CMD_TAR_UNPACK=(
+ tar
+ -xf
+ )
+# command to unpack a sorcery archive into the cauldron build usr/src dir
[[ -n "${CAULDRON_CMD_UNPACK_SORCERY[@]}" ]] ||
CAULDRON_CMD_UNPACK_SORCERY=(
"${CAULDRON_CMD_TAR[@]}"
-C "$CAULDRON_BUILD/usr/src"
- xf
+ -xf
)

-# command to unpack a baseroot archive into the cauldron build
+# command to unpack a baseroot archive into the cauldron build baseroot dir
[[ -n "${CAULDRON_CMD_UNPACK_BASEROOT[@]}" ]] ||
CAULDRON_CMD_UNPACK_BASEROOT=(
"${CAULDRON_CMD_TAR[@]}"
-C "$CAULDRON_BUILD/baseroot"
- xf "$CAULDRON_BASEROOT"
+ -xf
)

-# command to unpack a baseroot archive into the cauldron build
+# command to unpack a baseroot archive into the cauldron build dir
[[ -n "${CAULDRON_CMD_UNPACK_BUILD[@]}" ]] ||
CAULDRON_CMD_UNPACK_BUILD=(
"${CAULDRON_CMD_TAR[@]}"
-C "$CAULDRON_BUILD/"
- xf
+ -xf
)

# command to chmod files
@@ -137,8 +143,8 @@

# command to remove files forcefully
[[ -n "${CAULDRON_CMD_RM_FORCE[@]}" ]] ||
- CAULDRON_CMD_RM_FORCE=(
- "${CAULDRON_CMD_RM_[@]}"
+ eval CAULDRON_CMD_RM_FORCE=(
+ "${CAULDRON_CMD_RM[@]}"
-f
)

@@ -233,7 +239,7 @@
# command to package the iso initramfs
[[ -n "${CAULDRON_CMD_MKRAMFS[@]}" ]] ||
CAULDRON_CMD_MKRAMFS=(
- find * -depth -print | cpio -H newc -o | gzip -9c
+ find * -depth -print \| cpio -H newc -o \| gzip -9c
)

# command to find files
diff --git a/cauldron/lib/errorcodes b/cauldron/lib/errorcodes
index 8bee67e..9a131f3 100644
--- a/cauldron/lib/errorcodes
+++ b/cauldron/lib/errorcodes
@@ -116,6 +116,8 @@ liberror_add_error ERR_TOOLCHAIN_SORCERY \
"sorcery not found in toolchain root"
liberror_add_error ERR_TOOLCHAIN_RESURRECT \
"could not resurrect spell using sorcery"
+liberror_add_error ERR_TOOLCHAIN_BASEROOT \
+ "could not acquire and unpack a valid basesystem chroot"


#-------------------------------------------------------------------------------
##
diff --git a/cauldron/lib/lib.chroot b/cauldron/lib/lib.chroot
index b3487e2..b35b45c 100644
--- a/cauldron/lib/lib.chroot
+++ b/cauldron/lib/lib.chroot
@@ -15,18 +15,35 @@
##

#-------------------------------------------------------------------------------

+# global variables for tracking chroot users
+LIBCHROOT_PATHS=()
+LIBCHROOT_USERS=()
+

#-------------------------------------------------------------------------------
## @param target dir to chroot into (optional)
+## @param target sorcery config (optional)
+## @param target sorcery local config (optional)
##
## Prepares a chroot environment and exports necessary variables. For every
## target dir to chroot into, there should be one
## [cauldron_chroot_init ... cauldron_chroot_done] pair.
##
+## If supplied, the second and third parameters should be file paths to the
+## sorcery config and local config inside the chroot target (the first
+## parameter). They will default to etc/sorcery/config and
+## etc/sorcery/local/config relative to the chroot target, respectively.
+##

#-------------------------------------------------------------------------------
function cauldron_chroot_init() {
local target="${1:-$CAULDRON_BUILD}"
+ local num="${#LIBCHROOT_PATHS[@]}"
+ local sconfig="${2:-$target/etc/sorcery/config}"
+ local slconfig="${3:-$target/etc/sorcery/local/config}"

- [[ "$CAULDRON_CHROOTINIT" -eq 1 ]] && return $ERR_CHROOT_NEST
+ if [[ "$CAULDRON_CHROOTINIT" -eq 1 ]]
+ then
+ CAULDRON_CHROOT_USERS=$((CAULDRON_CHROOT_USERS+1))
+ fi

# if target is somehow null, return an error
if [[ -z "$target" ]]
@@ -34,19 +51,32 @@ function cauldron_chroot_init() {
return $ERR_CHROOT_UNDEF
fi

- # bind the needed mounts
- "${CAULDRON_CMD_MOUNT_BIND[@]}" \
- "$CAULDRON_HOST/dev" \
- "$target/dev" ||
- return $ERR_CHROOT_INIT
- "${CAULDRON_CMD_MOUNT_BIND[@]}" \
- "$CAULDRON_HOST/dev/pts" \
- "$target/dev/pts" ||
- return $ERR_CHROOT_INIT
- "${CAULDRON_CMD_MOUNT_BIND[@]}" \
- "$CAULDRON_HOST/proc" \
- "$target/proc" ||
- return $ERR_CHROOT_INIT
+ if $(echo "${LIBCHROOT_PATHS[@]}" | grep -q "$target")
+ then
+ for((path=0; path < num; path++))
+ do
+ if [[ "$target" == "${LIBCHROOT_PATHS[path]}" ]]
+ then
+ ((LIBCHROOT_USERS[path]++))
+ fi
+ done
+ else
+ # increase the total number of entries
+ ((num++))
+ # add the target path to the list of chrooted paths
+ LIBCHROOT_PATHS[num]="$target"
+ # set the user count to 1
+ LIBCHROOT_USERS[num]=1
+
+ # bind the needed mounts
+ for bind in dev dev/pts proc
+ do
+ "${CAULDRON_CMD_MOUNT_BIND[@]}" \
+ "$CAULDRON_HOST/$bind" \
+ "$target/$bind" ||
+ return $ERR_CHROOT_INIT
+ done
+ fi

# make sure the sorcerous library is loaded
# which provides cauldron_source_sorcery
@@ -55,7 +85,7 @@ function cauldron_chroot_init() {
cauldron_load_library lib.sorcerous
fi
# source the target sorcery, so we have access to its functions
- cauldron_sorcerous_load "$target" || return $ERR_SORCEROUS_TARGET
+ cauldron_sorcerous_load $sconfig $slconfig || return $ERR_SORCEROUS_TARGET

# everything went OK, so export the chroot definitions
export CAULDRON_CHROOTINIT=1
@@ -71,24 +101,33 @@ function cauldron_chroot_init() {
##

#-------------------------------------------------------------------------------
function cauldron_chroot_done() {
+ local target="${1:-$CAULDRON_BUILD}"
+
if [[ "$CAULDRON_CHROOTINIT" -eq 1 ]]
then
- local target="${1:-$CAULDRON_BUILD}"
-
# if target is somehow null, return an error
if [[ -z "$target" ]]
then
return $ERR_CHROOT_UNDEF
fi

- # unmount the bind mounts
- "${CAULDRON_CMD_UNMOUNT[@]}" "$target/proc" || return $ERR_CHROOT_DONE
- "${CAULDRON_CMD_UNMOUNT[@]}" "$target/dev/pts" || return $ERR_CHROOT_DONE
- "${CAULDRON_CMD_UNMOUNT[@]}" "$target/dev" || return $ERR_CHROOT_DONE
-
- # clear the chroot definitions
- unset CAULDRON_CHROOTINIT
- unset CAULDRON_CHROOT
+ # remove one "lock" for each time cauldron_chroot_done is called until we
+ # are down to the last one, and then do the actual cleanup of the chroot
+ if [[ "$CAULDRON_CHROOT_USERS" -gt 1 ]]
+ then
+ CAULDRON_CHROOT_USERS=$((CAULDRON_CHROOT_USERS-1))
+ else
+ # unmount the bind mounts
+ for bind in proc dev/pts dev
+ do
+ "${CAULDRON_CMD_UNMOUNT[@]}" "$target/$bind" || return
$ERR_CHROOT_DONE
+ done
+
+ # clear the chroot definitions
+ unset CAULDRON_CHROOTINIT
+ unset CAULDRON_CHROOT
+ unset CAULDRON_CHROOT_USERS
+ fi
fi

return $ERR_OK
diff --git a/cauldron/lib/lib.init b/cauldron/lib/lib.init
index 6240458..d40b102 100755
--- a/cauldron/lib/lib.init
+++ b/cauldron/lib/lib.init
@@ -144,6 +144,7 @@ function cauldron_init_fs_dirs() {
local list="$CAULDRON_DATA/$CAULDRON_ARCH/initfs/dirs"

if [[ -f "$list" ]]
+ then
for dir in $("${CAULDRON_CMD_CAT[@]}" "$list")
do
"${CAULDRON_CMD_MKDIR[@]}" "$initfs/$dir" || return $ERR_MK_DIR
@@ -164,6 +165,7 @@ function cauldron_init_fs_bins() {
local list="$CAULDRON_DATA/$CAULDRON_ARCH/initfs/binaries"

if [[ -f "$list" ]]
+ then
for bin in $("${CAULDRON_CMD_CAT[@]}" "$list")
do
"${CAULDRON_CMD_CP[@]}" "$bin" "$initfs/bin" || return $ERR_CP_FILE
@@ -184,6 +186,7 @@ function cauldron_init_fs_libs() {
local list="$CAULDRON_DATA/$CAULDRON_ARCH/initfs/libs"

if [[ -f "$list" ]]
+ then
for lib in $("${CAULDRON_CMD_CAT[@]}" "$list")
do
"${CAULDRON_CMD_CP[@]}" "$lib" "$initfs/lib/" || return $ERR_CP_FILE
@@ -204,6 +207,7 @@ function cauldron_init_fs_mods() {
local list="$CAULDRON_DATA/$CAULDRON_ARCH/initfs/modules"

if [[ -f "$list" ]]
+ then
for module in $("${CAULDRON_CMD_CAT[@]}" "$list")
do
"${CAULDRON_CMD_CP[@]}" \
diff --git a/cauldron/lib/lib.toolchain b/cauldron/lib/lib.toolchain
index 0359788..d9b900a 100644
--- a/cauldron/lib/lib.toolchain
+++ b/cauldron/lib/lib.toolchain
@@ -18,6 +18,137 @@

#-------------------------------------------------------------------------------


#-------------------------------------------------------------------------------
+## @param chroot path (required)
+## @param compiler (optional)
+##
+## Performs a very basic compiler test by creating a C source file that
simply
+## exits with 0 (success), attempts to compile it, then runs the output if
the
+## compile was successful. A final test for the exit status of the program
+## determins if the compiler can create (at least trivial) programs that
+## actually run correctly in the build environment.
+##
+## The chroot path parameter is the path to the chroot build environment, and
+## defaults to "$CAULDRON_BUILD/baseroot" if not provided. The optional
compiler
+## second parameter is the compiler to use (defaults to gcc). Currently the
+## compiler is expected to have the same parameters as gcc (though only the
+## ouput flag [-o] is used).
+##
+#-------------------------------------------------------------------------------
+function cauldron_toolchain_compiler_test() {
+ local chroot="${1:-$CAULDRON_BUILD/baseroot}"
+ local compiler="${2:-gcc}"
+ local comptest="tmp/compiler.test"
+
+
+ # create an extremely simple C source for testing the compiler
+ echo -e "#include <stdlib.h>\nint main(void) { exit(0); }" \
+ > "$chroot/tmp/compiler.test.c"
+
+ cauldron_chroot_init "$chroot" || return $?
+
+ # compile a very simple source file to ensure the compiler works
+ cauldron_chroot "$compiler" -o "/$comptest" "/$comptest.c" ||
+ return $ERR_TOOLCHAIN_COMPILER_TEST
+
+ # run the generated binary to make sure it was properly compiled
+ cauldron_chroot "/$comptest" || return $ERR_TOOLCHAIN_COMPILER_TEST
+
+ cauldron_chroot_done "$chroot" || return $?
+
+ # clean up the temporary files
+ "${CAULDRON_CMD_RM_FORCE[@]}" "$chroot/$comptest.c" "$chroot/$comptest" ||
+ return $ERR_RM_FILES
+
+ return $ERR_OK
+}
+
+#-------------------------------------------------------------------------------
+## @param baseroot (optional)
+##
+## Performs basic quality assurance over an acquired basesystem chroot for
+## cauldron purposes. The path to the (unpacked) baseroot directory (which
will
+## function as the build chroot hereafter) defaults to
+## "$CAULDRON_BUILD/baseroot" if not provided.
+##
+#-------------------------------------------------------------------------------
+function cauldron_toolchain_baseroot_test() {
+ local chroot="${1:-$CAULDRON_BUILD/baseroot}"
+ local fhs=(
+ bin
+ boot
+ dev
+ home
+ etc
+ lib
+ mnt
+ opt
+ proc
+ root
+ sbin
+ tmp
+ usr/bin
+ usr/sbin
+ var
+ )
+
+ # ensure that a valid chroot was passed in as the first parameter
+ [[ -d "$chroot" ]] || return $ERR_TOOLCHAIN_BASEROOT_TEST
+
+ # ensure the important standard FHS directories are present
+ for dir in "${fhs[@]}"
+ do
+ [[ -d "$chroot/$dir" ]] ||
+ return $ERR_TOOLCHAIN_BASEROOT_TEST
+ done
+
+ cauldron_toolchain_compiler_test "$chroot"
+
+ return $ERR_OK
+}
+
+#-------------------------------------------------------------------------------
+## @param baseroot (optional)
+##
+## Sets up a toolchain chroot by acquiring and unpacking an already prepared
+## basesystem chroot rather than generating one using the host system. If the
+## optional parameter baseroot is provided, it will use that instead of
+## downloading a fresh image. The provided baseroot can either be an unpacked
+## directory or a (possibly compressed) archive.
+##
+#-------------------------------------------------------------------------------
+function cauldron_toolchain_baseroot() {
+ local baseroot="${1:-$CAULDRON_BASEROOT}"
+ local baseroot_url="$CAULDRON_BASEROOT_URL"
+ local chroot="$CAULDRON_BUILD/baseroot"
+
+ if [[ -d "$baseroot" ]]
+ then
+ ln -sf "$baseroot" "$chroot" || return "$ERR_TOOLCHAIN_BASEROOT"
+ else
+ # ensure that the target chroot directory exists
+ "${CAULDRON_CMD_MKDIR[@]}" "$chroot" || return $ERR_TOOLCHAIN_BASEROOT
+
+ if [[ ! -f "$baseroot" ]]
+ then
+ # get a fresh basesystem chroot package
+ (
+ cd "$CAULDRON_BUILD"
+ "${CAULDRON_CMD_URL_DL[@]}" "$baseroot_url" ||
+ return $ERR_TOOLCHAIN_BASEROOT
+ )
+ fi
+
+ # unpack it
+ "${CAULDRON_CMD_UNPACK_BASEROOT[@]}" "$baseroot" ||
+ return $ERR_TOOLCHAIN_BASEROOT
+ fi
+
+ # perform basic sanity checking on the chroot
+ # return whatever error code baseroot_test gives back to us
+ cauldron_toolchain_baseroot_test "$chroot" || return $?
+}
+
+#-------------------------------------------------------------------------------
##
## Scans the sorcery archspec files to find the host triplet.
##
diff --git a/cauldron/lib/libcauldron b/cauldron/lib/libcauldron
index 5546ddf..7a84969 100755
--- a/cauldron/lib/libcauldron
+++ b/cauldron/lib/libcauldron
@@ -107,6 +107,8 @@ function cauldron_clean_iso_system() {

[[ -z "$cleanfile" ]] && return $ERR_CLEAN_FILE

+ [[ -z "$CAULDRON_CHROOT" ]] && return $ERR_CHROOT_INIT
+
for i in $(sort -r $cleanfile)
do
if [[ -d "$i" ]]
@@ -234,12 +236,18 @@ function cauldron_prepare() {
# ensure that the build dir exists
"${CAULDRON_CMD_MKDIR[@]}" "$CAULDRON_BUILD"

+ # ensure CAULDRON_BUILD/etc exists
+ "${CAULDRON_CMD_MKDIR[@]}" "$CAULDRON_BUILD/etc"
+
# copy the host's resolv.conf in order to dl sources from the net
"${CAULDRON_CMD_CP[@]}" \
"$CAULDRON_RESOLV" \
"$CAULDRON_BUILD/etc/resolv.conf" ||
return $ERR_RESOLV

+ # prepare chroots to $CAULDRON_BUILD
+ cauldron_chroot_init || return $?
+
# install sorcery into the build dir
if [[ -z cauldron_sorcerous_install ]]
then
@@ -251,6 +259,9 @@ function cauldron_prepare() {
# there is a spoon
cauldron_chroot "${CAULDRON_CMD_CAST[@]}" cauldron || return
$ERR_CHROOT_CAST

+ # clean up the chroot
+ cauldron_chroot_done || return $?
+
return $ERR_OK
}




  • [SM-Commit] GIT changes to master cauldron by Justin Boffemmyer (b158dbe27d8080df83eef55fee94c2d1e1922e57), Justin Boffemmyer, 06/30/2011

Archive powered by MHonArc 2.6.24.

Top of Page