[Buildd-tools-devel] [PATCH 15/22] Filesystem union chroot options support

Jan-Marek Glogowski glogow at fbihome.de
Thu Mar 26 21:13:53 UTC 2009


Introduces a new type of chroot options.  This allows chroot
sessions to be generated using an unioning filesystem like aufs
or unionfs.  Per default this feature is disabled.  Check out
schroot.conf.5 for further information.
---
 bin/schroot/Makefile.am          |    2 +
 bin/schroot/schroot.conf.5.in    |   26 ++++
 bin/schroot/setup/00check        |    7 +-
 bin/schroot/setup/05fsunion      |   51 ++++++++
 bin/schroot/setup/10mount        |   80 ++++++++++++-
 bin/schroot/setup/Makefile.am    |    1 +
 configure.ac                     |    5 +
 debian/control                   |    2 +-
 sbuild/Makefile.am               |    2 +
 sbuild/sbuild-chroot-fs-union.cc |  255 ++++++++++++++++++++++++++++++++++++++
 sbuild/sbuild-chroot-fs-union.h  |  183 +++++++++++++++++++++++++++
 sbuild/sbuild-session.cc         |   10 ++
 12 files changed, 620 insertions(+), 4 deletions(-)
 create mode 100755 bin/schroot/setup/05fsunion
 create mode 100644 sbuild/sbuild-chroot-fs-union.cc
 create mode 100644 sbuild/sbuild-chroot-fs-union.h

diff --git a/bin/schroot/Makefile.am b/bin/schroot/Makefile.am
index eb7f71b..0b251e3 100644
--- a/bin/schroot/Makefile.am
+++ b/bin/schroot/Makefile.am
@@ -75,3 +75,5 @@ install-data-hook:
 	$(mkinstalldirs) $(DESTDIR)$(SCHROOT_MOUNT_DIR)
 	$(mkinstalldirs) $(DESTDIR)$(SCHROOT_SESSION_DIR)
 	$(mkinstalldirs) $(DESTDIR)$(SCHROOT_UNPACK_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(SCHROOT_OVERLAY_DIR)
+
diff --git a/bin/schroot/schroot.conf.5.in b/bin/schroot/schroot.conf.5.in
index 7f3ce8c..90b55ab 100644
--- a/bin/schroot/schroot.conf.5.in
+++ b/bin/schroot/schroot.conf.5.in
@@ -268,6 +268,32 @@ example, if the filesystem contains a chroot in \fI/chroot/sid\fP, you would
 specify \[lq]/chroot/sid\[rq] here.  If the chroot is the only thing on the
 filesystem, i.e. \fI/\fP is the root filesystem for the chroot, this option
 should be left blank, or omitted entirely.
+.SS Filesystem Union chroot options
+Some chroots allow to create a session using filesystem unions to overlay the
+real data and redirect all modifications to a session-dependant directory.
+To activate this feature you have to set the \f[CI]fs-union-type\fP to any
+supported value.  If \[lq]\fIFilesystem Union\fP\[rq] is enabled the chroot
+will also be a \fBsource chroot\fP, which wil provide additional options
+(see \[lq]\fISource chroot options\fP\[rq], above).  All entries are optional.
+.TP
+\f[CBI]fs-union-type=\fP\f[CI]type\fP
+Allows to set the used filesystem.  This is especially important, if you use
+the \fIfs-branch-config\fP option to specify different options.  Currently
+supported filesystems are \[oq]aufs\[cq] and \[oq]unionfs\[cq].  Default is 
+\[oq]none\[cq], so this feature is disabled.
+.TP
+\f[CBI]fs-union-branch-config=\fP\f[CI]branch_config\fP
+The branch configuration is used for the first filesystem in the 
+\fIfs-union-type\fP filesystem list.  It replaces the complete \[lq]\-o\[rq] 
+string for mount and allows to make complex filesystem unions.
+.B Note:
+You can use the variables \[lq]${CHROOT_FS_UNION_OVERLAY_DIRECTORY}\[rq] and
+\[lq]${CHROOT_LOCATION}\[rq] in this option string, which will be replaced
+with the writeable session directory and the source-chroot directory.
+.TP
+\f[CBI]fs-union-overlay-base=directory
+This specifies the base directory, where the session writeable directories
+will be created. Default is \[oq]@SCHROOT_OVERLAY_DIR@\[cq].
 .SS Localisation
 .PP
 Some keys may be localised in multiple languages.  This is achieved by adding
diff --git a/bin/schroot/setup/00check b/bin/schroot/setup/00check
index f3fae64..e795d8f 100755
--- a/bin/schroot/setup/00check
+++ b/bin/schroot/setup/00check
@@ -52,6 +52,10 @@ if [ $1 = "setup-start" ] || [ $1 = "setup-recover" ]; then
 	echo "CHROOT_LOCATION=$CHROOT_LOCATION"
 	echo "CHROOT_PATH=$CHROOT_PATH"
 	echo "CHROOT_CONTAINER=$CHROOT_CONTAINER"
+	if [ "x" != "x$CHROOT_FS_UNION_TYPE" ] && [ "$CHROOT_FS_UNION_TYPE" != "none" ]; then
+	    echo "CHROOT_FS_UNION_TYPE=$CHROOT_FS_UNION_TYPE"
+	    echo "CHROOT_FS_UNION_OVERLAY_DIRECTORY=$CHROOT_FS_UNION_OVERLAY_DIRECTORY"
+	fi
 	if [ "$CHROOT_TYPE" = "plain" ] || [ "$CHROOT_TYPE" = "directory" ]; then
 	    echo "CHROOT_DIRECTORY=$CHROOT_DIRECTORY"
 	elif [ "$CHROOT_TYPE" = "file" ]; then
@@ -103,7 +107,8 @@ if [ $1 = "setup-start" ] || [ $1 = "setup-recover" ]; then
     if [ -z "$CHROOT_PATH" ] \
 	|| [ "$CHROOT_PATH" = "/" ] \
 	|| [ "$CHROOT_LOCATION" = "/" ] \
-	|| [ "$CHROOT_DIRECTORY" = "/" ]
+	|| [ "$CHROOT_DIRECTORY" = "/" ] \
+	|| [ "$CHROOT_FS_UNION_OVERLAY_DIRECTORY" = "/" ]
     then
 	echo "Invalid chroot mount path, location or directory."
 	exit 1
diff --git a/bin/schroot/setup/05fsunion b/bin/schroot/setup/05fsunion
new file mode 100755
index 0000000..c8c454f
--- /dev/null
+++ b/bin/schroot/setup/05fsunion
@@ -0,0 +1,51 @@
+#!/bin/sh
+# Copyright © 2008-2009  Jan-Marek Glogowski <glogow at fbihome.de>
+#
+# schroot 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 3 of the License, or
+# (at your option) any later version.
+#
+# schroot 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, see
+# <http://www.gnu.org/licenses/>.
+#
+#####################################################################
+
+set -e
+
+if [ -f "$CHROOT_SCRIPT_CONFIG" ]; then
+    . "$CHROOT_SCRIPT_CONFIG"
+fi
+
+if [ "xnone" != "x${CHROOT_FS_UNION_TYPE:-none}" ]; then
+
+    if [ $1 = "setup-start" ]; then
+	if [ "$CHROOT_SESSION_PURGE" = "true" ]; then
+		mkdir "${CHROOT_FS_UNION_OVERLAY_DIRECTORY}"
+	fi
+
+    elif [ $1 = "setup-recover" ]; then
+        if [ ! -d "${CHROOT_FS_UNION_OVERLAY_DIRECTORY}" ]; then
+	    echo "Missing overlay directory for session - can't restore"
+	    exit 1
+        fi
+
+    elif [ $1 = "setup-stop" ]; then
+        if [ "$CHROOT_SESSION_PURGE" = "true" ]; then
+	    if [ "$AUTH_VERBOSITY" = "verbose" ]; then
+		echo "Purging $CHROOT_FS_UNION_OVERLAY_DIRECTORY"
+	    fi
+	    if [ -d "${CHROOT_FS_UNION_OVERLAY_DIRECTORY}" ]; then
+		rm -rf "${CHROOT_FS_UNION_OVERLAY_DIRECTORY}"
+	    fi
+	fi
+    fi
+
+fi
+
diff --git a/bin/schroot/setup/10mount b/bin/schroot/setup/10mount
index b8a23b7..7c174d9 100755
--- a/bin/schroot/setup/10mount
+++ b/bin/schroot/setup/10mount
@@ -41,10 +41,15 @@ do_mount()
     fi
     if [ ! -d "$3" ]; then
 	echo "$3 does not exist, and could not be created"
-	exit 1
+	return 1
     fi
 
+    set +e
     mount $VERBOSE $1 "$2" "$3"
+    RESULT=$?
+    set -e
+
+    return $RESULT
 }
 
 # Unmount all filesystems under specified location
@@ -65,6 +70,59 @@ do_umount_all()
     fi
 }
 
+# Mount a filesystem union
+# $1: read-only branch
+do_mount_fs_union()
+{
+    MOUNT_RES=255
+
+    # Try mounting the filesystem module
+    if ! grep -q "${CHROOT_FS_UNION_TYPE}$" /proc/filesystems; then
+	set +e
+	modprobe ${CHROOT_FS_UNION_TYPE} &> /dev/null
+	set -e
+    fi
+
+    # Skip fs if not available
+    if ! grep -q "${CHROOT_FS_UNION_TYPE}$" /proc/filesystems; then
+	# branch config just works with the first fs
+	CHROOT_FS_UNION_BRANCH_CONFIG=""
+	continue
+    fi
+
+    # Prepare branch config for fs type
+    if [ "x" = "x${CHROOT_FS_UNION_BRANCH_CONFIG}" ]; then
+	case $CHROOT_FS_UNION_TYPE in
+	unionfs)
+	    CHROOT_FS_UNION_BRANCH_CONFIG="dirs=${CHROOT_FS_UNION_OVERLAY_DIRECTORY}=rw,${1}=ro"
+	    ;;
+	aufs)
+	    CHROOT_FS_UNION_BRANCH_CONFIG="br:${CHROOT_FS_UNION_OVERLAY_DIRECTORY}:${1}=ro"
+	    ;;
+	esac
+    fi
+
+    # Try mounting fs
+    set +e
+    mount -t $CHROOT_FS_UNION_TYPE -o "$CHROOT_FS_UNION_BRANCH_CONFIG" ${CHROOT_NAME} ${CHROOT_MOUNT_LOCATION}
+    MOUNT_RES=$?
+    set -e
+    if [ 0 -eq $MOUNT_RES ]; then
+	break
+    fi
+
+    if [ 0 -ne $MOUNT_RES ]; then
+	echo "Mounting filesystem union failed"
+	return 1
+    fi
+
+    if [ "$AUTH_VERBOSITY" = "verbose" ]; then
+	echo "Using '$TYPE' for filesystem union"
+    fi
+
+    return 0
+}
+
 if [ "$AUTH_VERBOSITY" = "verbose" ]; then
   VERBOSE="-v"
 #  FSCK_VERBOSE="-V"
@@ -72,6 +130,14 @@ fi
 
 if [ "$CHROOT_TYPE" = "plain" ] || [ "$CHROOT_TYPE" = "directory" ] || [ "$CHROOT_TYPE" = "file" ] || [ "$CHROOT_TYPE" = "file" ] || [ "$CHROOT_TYPE" = "loopback" ] || [ "$CHROOT_TYPE" = "block-device" ] || [ "$CHROOT_TYPE" = "lvm-snapshot" ]; then
 
+    if [ "xnone" != "x${CHROOT_FS_UNION_TYPE:-none}" ] \
+	&& [ "$CHROOT_SESSION_PURGE" = "true" ];
+    then
+	CREATE_FS_UNION="yes"
+    else
+	CREATE_FS_UNION="no"
+    fi
+
     if [ "$CHROOT_TYPE" = "plain" ]; then
 	CHROOT_MOUNT_OPTIONS="--rbind"
 	CHROOT_MOUNT_DEVICE="$CHROOT_DIRECTORY"
@@ -110,7 +176,17 @@ if [ "$CHROOT_TYPE" = "plain" ] || [ "$CHROOT_TYPE" = "directory" ] || [ "$CHROO
 	    do_umount_all "$CHROOT_MOUNT_LOCATION"
 	fi
 
-	do_mount "$CHROOT_MOUNT_OPTIONS" "$CHROOT_MOUNT_DEVICE" "$CHROOT_MOUNT_LOCATION"
+	if [ "xyes" = "x${CREATE_FS_UNION}" ]; then
+	    if ! do_mount_fs_union "$CHROOT_FS_UNION_RO_BRANCH"
+	    then
+		exit 1
+	    fi
+	else
+	    if ! do_mount "$CHROOT_MOUNT_OPTIONS" "$CHROOT_MOUNT_DEVICE" "$CHROOT_MOUNT_LOCATION"
+	    then
+		exit 1
+	    fi
+	fi
 
 	if [ "$CHROOT_TYPE" != "plain" ]; then
 	    if [ -n "$FSTAB" ]; then
diff --git a/bin/schroot/setup/Makefile.am b/bin/schroot/setup/Makefile.am
index 56fbe3c..16fc261 100644
--- a/bin/schroot/setup/Makefile.am
+++ b/bin/schroot/setup/Makefile.am
@@ -27,6 +27,7 @@ setup_SCRIPTS =		\
 	00check		\
 	05lvm		\
 	05file		\
+	05fsunion	\
 	10mount		\
 	15killprocs	\
 	20copyfiles	\
diff --git a/configure.ac b/configure.ac
index 198552e..a85cd91 100644
--- a/configure.ac
+++ b/configure.ac
@@ -399,6 +399,11 @@ AC_SUBST([SCHROOT_UNPACK_DIR])
 AH_TEMPLATE(SCHROOT_UNPACK_DIR, [schroot unpack directory])
 AC_DEFINE_UNQUOTED(SCHROOT_UNPACK_DIR, ["$SCHROOT_UNPACK_DIR"])
 
+SCHROOT_OVERLAY_DIR="${PACKAGE_LOCALSTATE_DIR}/lib/${PACKAGE}/overlay"
+AC_SUBST([SCHROOT_OVERLAY_DIR])
+AH_TEMPLATE(SCHROOT_OVERLAY_DIR, [schroot overlay directory])
+AC_DEFINE_UNQUOTED(SCHROOT_OVERLAY_DIR, ["$SCHROOT_OVERLAY_DIR"])
+
 dnl Set PACKAGE_SYSCONF_DIR in config.h.
 AH_TEMPLATE(PACKAGE_SYSCONF_DIR, [Package system configuration directory])
 if test "x${sysconfdir}" = 'x${prefix}/etc'; then
diff --git a/debian/control b/debian/control
index 1ec2d65..8df5779 100644
--- a/debian/control
+++ b/debian/control
@@ -87,7 +87,7 @@ Architecture: any
 Depends: ${shlibs:Depends}, schroot-common (=${source:Version})
 Conflicts: dchroot (<< 0.13)
 Enhances: sbuild
-Suggests: debootstrap, lvm2, unzip
+Suggests: debootstrap, lvm2, unzip, aufs-modules | unionfs-modules
 Description: Execute commands in a chroot environment
  schroot allows users to execute commands or interactive shells in
  different chroots.  Any number of named chroots may be created, and
diff --git a/sbuild/Makefile.am b/sbuild/Makefile.am
index 0e4fc33..400fcc0 100644
--- a/sbuild/Makefile.am
+++ b/sbuild/Makefile.am
@@ -36,6 +36,7 @@ sbuild_public_h_sources =		\
 	sbuild-chroot-block-device.h	\
 	sbuild-chroot-directory.h	\
 	sbuild-chroot-file.h		\
+	sbuild-chroot-fs-union.h	\
 	sbuild-chroot-loopback.h	\
 	sbuild-chroot-lvm-snapshot.h	\
 	sbuild-chroot-mountable.h	\
@@ -78,6 +79,7 @@ sbuild_public_cc_sources =		\
 	sbuild-chroot-block-device.cc	\
 	sbuild-chroot-directory.cc	\
 	sbuild-chroot-file.cc		\
+	sbuild-chroot-fs-union.cc	\
 	sbuild-chroot-loopback.cc	\
 	sbuild-chroot-lvm-snapshot.cc	\
 	sbuild-chroot-mountable.cc	\
diff --git a/sbuild/sbuild-chroot-fs-union.cc b/sbuild/sbuild-chroot-fs-union.cc
new file mode 100644
index 0000000..8ddd351
--- /dev/null
+++ b/sbuild/sbuild-chroot-fs-union.cc
@@ -0,0 +1,255 @@
+/* Copyright © 2008-2009  Jan-Marek Glogowski <glogow at fbihome.de>
+ *
+ * schroot 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * schroot 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, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *********************************************************************/
+
+#include <config.h>
+
+#include "sbuild-chroot-fs-union.h"
+
+#include <cerrno>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <unistd.h>
+
+using namespace sbuild;
+
+namespace
+{
+  typedef std::pair<chroot_fs_union::error_code,const char *> emap;
+
+  /**
+   * This is a list of the supported error codes.  It's used to
+   * construct the real error codes map.
+   */
+  emap init_errors[] =
+    {
+      // TRANSLATORS: %1% = chroot fs type
+      emap(chroot_fs_union::FS_TYPE_UNKNOWN,     N_("Unknown filesystem type '%1%'"))
+    };
+}
+
+template<>
+error<chroot_fs_union::error_code>::map_type
+error<chroot_fs_union::error_code>::error_strings
+(init_errors,
+ init_errors + (sizeof(init_errors) / sizeof(init_errors[0])));
+
+chroot_fs_union::chroot_fs_union ():
+  chroot(),
+  chroot_source(),
+  fs_union_type("none"),
+  overlay_base_directory(SCHROOT_OVERLAY_DIR)
+{
+}
+
+chroot_fs_union::~chroot_fs_union ()
+{
+}
+
+bool
+chroot_fs_union::get_fs_union_configured () const
+{
+  std::string type = get_fs_union_type();
+  return (type != "none") ? true : false;
+}
+
+std::string const&
+chroot_fs_union::get_overlay_session_directory () const
+{
+  return overlay_session_directory;
+}
+
+void
+chroot_fs_union::set_overlay_session_directory 
+(std::string const& overlay_session_directory)
+{
+  if (!is_absname(overlay_session_directory))
+    throw chroot::error(overlay_session_directory, LOCATION_ABS);
+
+  this->overlay_session_directory = overlay_session_directory;
+}
+
+std::string const&
+chroot_fs_union::get_overlay_base_directory () const
+{
+  return overlay_base_directory;
+}
+
+void
+chroot_fs_union::set_overlay_base_directory
+(std::string const& overlay_base_drectory)
+{
+  if (!is_absname(overlay_base_directory))
+    throw chroot::error(overlay_base_directory, LOCATION_ABS);
+
+  this->overlay_base_directory = overlay_base_directory;
+}
+
+std::string const&
+chroot_fs_union::get_fs_union_type () const
+{
+  return fs_union_type;
+}
+
+void
+chroot_fs_union::set_fs_union_type (std::string const& fs_union_type)
+{
+  if ((fs_union_type == "aufs") || (fs_union_type == "unionfs"))
+    {
+      set_run_setup_scripts(true);
+      set_run_exec_scripts(true);
+      this->fs_union_type = fs_union_type;
+    }
+  else
+    {
+      if (fs_union_type == "none")
+	this->fs_union_type = fs_union_type;
+      else
+	throw error(fs_union_type, FS_TYPE_UNKNOWN);
+    }
+}
+
+std::string const&
+chroot_fs_union::get_fs_union_branch_config () const
+{
+  return fs_union_branch_config;
+}
+
+void
+chroot_fs_union::set_fs_union_branch_config 
+(std::string const& fs_union_branch_config)
+{
+  this->fs_union_branch_config = fs_union_branch_config;
+}
+
+void
+chroot_fs_union::setup_env (environment& env)
+{
+  chroot::setup_env(env);
+  chroot_source::setup_env(env);
+
+  env.add("CHROOT_FS_UNION_TYPE", get_fs_union_type());
+  if (get_fs_union_configured())
+    {
+      env.add("CHROOT_FS_UNION_OVERLAY_DIRECTORY", 
+        get_overlay_session_directory());
+      env.add("CHROOT_FS_UNION_BRANCH_CONFIG", 
+        get_fs_union_branch_config());
+    }
+}
+
+std::string
+chroot_fs_union::get_path() const
+{
+  if (get_fs_union_configured())
+    return get_mount_location();
+  else
+    return chroot::get_path();
+}
+
+sbuild::chroot::session_flags
+chroot_fs_union::get_session_flags () const
+{
+  std::string type = get_fs_union_type();
+  if (get_run_setup_scripts() == true) {
+    if (get_fs_union_configured()) 
+      return SESSION_CREATE | chroot_source::get_session_flags();
+    else
+      return SESSION_CREATE;
+  }
+  else
+    return SESSION_NOFLAGS;
+}
+
+void
+chroot_fs_union::get_details (format_detail& detail) const
+{
+  chroot::get_details(detail);
+  chroot_source::get_details(detail);
+
+  if (!this->overlay_session_directory.empty())
+    detail.add(_("Filesystem union overlay directory"),
+      get_overlay_session_directory());
+  if (!this->fs_union_branch_config.empty())
+    detail.add(_("Filesystem union branch config"), 
+      get_fs_union_branch_config());
+}
+
+void
+chroot_fs_union::get_keyfile (keyfile& keyfile) const
+{
+  chroot::get_keyfile(keyfile);
+  chroot_source::get_keyfile(keyfile);
+
+  keyfile::set_object_value(*this, &chroot_fs_union::get_fs_union_type,
+			    keyfile, get_name(), "fs-union-type");
+
+  keyfile::set_object_value(*this, 
+			    &chroot_fs_union::get_fs_union_branch_config,
+			    keyfile, get_name(), "fs-union-branch-config");
+
+  if (get_active())
+    keyfile::set_object_value(*this, 
+			      &chroot_fs_union::get_overlay_session_directory,
+			      keyfile, get_name(), 
+			      "fs-union-overlay-session-directory");
+  else
+    keyfile::set_object_value(*this, 
+			      &chroot_fs_union::get_overlay_base_directory,
+			      keyfile, get_name(), 
+			      "fs-union-overlay-base-directory");
+}
+
+void
+chroot_fs_union::set_keyfile (keyfile const& keyfile,
+			      string_list&   used_keys)
+{
+  chroot::set_keyfile(keyfile, used_keys);
+  chroot_source::set_keyfile(keyfile, used_keys);
+
+  keyfile::get_object_value(*this, &chroot_fs_union::set_fs_union_type,
+			    keyfile, get_name(), "fs-union-type",
+			    keyfile::PRIORITY_OPTIONAL);
+  used_keys.push_back("fs-union-type");
+
+  keyfile::get_object_value(*this, 
+			    &chroot_fs_union::set_fs_union_branch_config,
+			    keyfile, get_name(), "fs-union-branch-config",
+			    keyfile::PRIORITY_OPTIONAL);
+  used_keys.push_back("fs-union-branch-config");
+
+  if (get_active())
+    keyfile::get_object_value(*this, 
+			      &chroot_fs_union::set_overlay_session_directory,
+			      keyfile, get_name(), 
+			      "fs-union-overlay-session-directory",
+			      (get_fs_union_configured() ?
+			       keyfile::PRIORITY_REQUIRED :
+			       keyfile::PRIORITY_OPTIONAL));
+  else
+    keyfile::get_object_value(*this, 
+			      &chroot_fs_union::set_overlay_base_directory,
+			      keyfile, get_name(), 
+			      "fs-union-overlay-base-directory",
+			      keyfile::PRIORITY_OPTIONAL);
+
+  used_keys.push_back("fs-union-overlay-session-directory");
+  used_keys.push_back("fs-union-overlay-base-directory");
+}
+
diff --git a/sbuild/sbuild-chroot-fs-union.h b/sbuild/sbuild-chroot-fs-union.h
new file mode 100644
index 0000000..3e4bb4c
--- /dev/null
+++ b/sbuild/sbuild-chroot-fs-union.h
@@ -0,0 +1,183 @@
+/* Copyright © 2008-2009  Jan-Marek Glogowski <glogow at fbihome.de>
+ *
+ * schroot 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * schroot 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, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *********************************************************************/
+
+#ifndef SBUILD_CHROOT_FS_UNION_H
+#define SBUILD_CHROOT_FS_UNION_H
+
+#include <sbuild/sbuild-chroot-source.h>
+
+namespace sbuild
+{
+  /**
+   * A chroot may offer session support using a union filesystem like
+   * aufs or unionfs.
+   *
+   * This interface can be implemented by any chroot wishing to provide such
+   * functionality.  It already includes sbuild::chroot_source support.
+   *
+   * At a minimum, the inheriting class has to implement the
+   * chroot_source::clone_source() function, depending on the
+   * setting of get_fs_union_configured().
+   */
+  class chroot_fs_union : public chroot_source
+  {
+  protected:
+    /// The constructor.
+    chroot_fs_union ();
+
+    friend class chroot;
+
+  public:
+    /// The destructor.
+    virtual ~chroot_fs_union ();
+
+    /// Error codes.
+    enum error_code
+      {
+	FS_TYPE_UNKNOWN      ///< Unknown union fs type
+      };
+
+    /// Exception type.
+    typedef custom_error<error_code> error;
+
+    /**
+     * Get fs union configured state.
+     *
+     * @returns if fs union is configured
+     */
+    bool
+    get_fs_union_configured () const;
+
+    /**
+     * Get the union filesystem type.
+     *
+     * @see set_fs_union_type
+     * @returns the union filesytem type.
+     */
+    virtual std::string const&
+    get_fs_union_type () const;
+
+    /**
+     * Get the union filesystem branch configuration.
+     *
+     * @see set_fs_union_branch_config
+     * @returns the union filesystem branch configuration.
+     */
+    virtual std::string const&
+    get_fs_union_branch_config () const;
+
+    /**
+     * Get the overlay base directory.
+     *
+     * @see set_overlay_base_directory
+     * @returns the writeable overlay directory.
+     */
+    virtual std::string const&
+    get_overlay_base_directory () const;
+
+    /**
+     * Get the writeable overlay directory of the session.
+     *
+     * @see set_overlay_session_directory
+     * @returns the writeable overlay directory.
+     */
+    virtual std::string const&
+    get_overlay_session_directory () const;
+
+    /**
+     * Set the union filesystem type.
+     *
+     * Currently supported values are aufs, unionfs and none.
+     *
+     * @param fs_union_type the filesystem type.
+     **/
+    virtual void
+    set_fs_union_type (std::string const& fs_union_type);
+
+    /**
+     * Set a complex branch configuration.
+     *
+     * Normally a temporary directory is used as the writeable branch, which 
+     * is removed on session end. This allows to build a complex union chroot 
+     * which can merge multiple branches. The string has to be constructed as 
+     * expected by the union filesystem type and is directly used as the mount
+     * '-o' option string.
+     *
+     * @param fs_union_branch_config a @fs_type specific branch description
+     **/
+    virtual void
+    set_fs_union_branch_config (std::string const& fs_union_branch_config);
+
+    /**
+     * Allows one to set the directory, where session overlay directories will
+     * be created.
+     *
+     * @param the absolute path of the overlay_base_directory.
+     **/
+    virtual void
+    set_overlay_base_directory 
+    (std::string const& overlay_base_directory);
+
+    /**
+     * Allows schrooot to set the session dependant overlay directory.
+     *
+     * @param the absolute path of the overlay_session_directory.
+     **/
+    virtual void
+    set_overlay_session_directory 
+    (std::string const& overlay_session_directory);
+
+    virtual std::string
+    get_path () const;
+
+    virtual void
+    setup_env (environment& env);
+
+    virtual session_flags
+    get_session_flags () const;
+
+  protected:
+    virtual void
+    get_details (format_detail& detail) const;
+
+    virtual void
+    get_keyfile (keyfile& keyfile) const;
+
+    virtual void
+    set_keyfile (keyfile const& keyfile,
+                 string_list&   used_keys);
+
+  private:
+    /// Union filesystem type
+    std::string fs_union_type;
+    /// Complex branch configuration to pass directly as mount option
+    std::string fs_union_branch_config;
+    /// Directory used as the overlay base directory
+    std::string overlay_base_directory;
+    /// Writeable directory used as the overlay write branch
+    std::string overlay_session_directory;
+  };
+}
+
+#endif /* SBUILD_CHROOT_FS_UNION_H */
+
+/*
+ * Local Variables:
+ * mode:C++
+ * End:
+ */
diff --git a/sbuild/sbuild-session.cc b/sbuild/sbuild-session.cc
index fda5507..a6bbe8d 100644
--- a/sbuild/sbuild-session.cc
+++ b/sbuild/sbuild-session.cc
@@ -20,6 +20,7 @@
 
 #include "sbuild-chroot-plain.h"
 #include "sbuild-chroot-lvm-snapshot.h"
+#include "sbuild-chroot-fs-union.h"
 #include "sbuild-ctty.h"
 #include "sbuild-run-parts.h"
 #include "sbuild-session.h"
@@ -663,6 +664,15 @@ session::run_impl ()
 	      snapshot->set_snapshot_device(device);
 	    }
 
+	  /* Filesystem unions need the overlay directory specifying. */
+	  chroot_fs_union *overlay = 0;
+	  if ((overlay = dynamic_cast<chroot_fs_union *>(chroot.get())) != 0)
+	    {
+	      std::string dir = overlay->get_overlay_base_directory();
+              dir += "/" + this->session_id;
+	      overlay->set_overlay_session_directory(dir);
+	    }
+
 	  try
 	    {
 	      /* Run setup-start chroot setup scripts. */
-- 
1.6.2.1




More information about the Buildd-tools-devel mailing list