grml-chroot: properly handle multiple chroots [Closes: issue659]
[grml-scripts.git] / usr_sbin / grml-chroot
index a53412c..2540957 100755 (executable)
@@ -10,6 +10,12 @@ PROG_NAME_=$(basename $0)
 DEST_=""
 MOUNTED_=""     # all mounted destinations
 
+function bailout
+{
+  umount_all
+  die "Bailout"
+}
+trap bailout 1 2 3 3 6 9 14 15
 
 function die
 {
@@ -17,6 +23,16 @@ function die
     exit 1
 }
 
+function isMounted
+{
+    local dir="$1"
+    if cut -d\  -f 2 /proc/mounts | grep -q "$dir"; then
+        return 0
+    else
+        return 1
+    fi
+}
+
 function printUsage
 {
     cat <<EOT
@@ -45,19 +61,23 @@ function mountit
 
     local all_options_=""
 
-    if [[ $options_ == "--bind" ]]; then
+    if ! isMounted "${DEST_}/$dest_"; then
+      if [[ $options_ == "--bind" ]]; then
         all_options_="--bind $type_"
-    else
+      else
         all_options_="-t $type_ none"
+      fi
+      mount $all_options_ "${DEST_}/$dest_" && storeMounts "$dest_"
     fi
-    mount $all_options_ "${DEST_}/$dest_" && storeMounts "$dest_"
 }
 
 function umount_all
 {
-    for i in $MOUNTED_; do
-        umount "${DEST_}/$i"
+    for i in /proc /sys /dev; do
+        umount "${DEST_}/${i}"
     done
+
+    rm -f "$DEST_"/etc/debian_chroot
 }
 
 
@@ -88,10 +108,35 @@ fi
 mountit "proc"  "proc"
 mountit "sysfs" "sys"
 mountit "/dev"   "dev"   "--bind"
+
+# do not write to /var/run of chroot if it's not present
+if [ -d "$DEST_/tmp" ] ; then
+  STATEDIR="tmp/grml-chroot"
+  mkdir -p "$DEST_/$STATEDIR"
+  touch "$DEST_/$STATEDIR/$$"
+fi
+
+if [ ! -e "$DEST_"/etc/debian_chroot ]; then
+    echo "Writing /etc/debian_chroot ..."
+    cat "$DEST_"/etc/hostname > "$DEST_"/etc/debian_chroot
+fi
+
 if (( $# < 1 )); then
     chroot "$DEST_"
+    RC=$?
 else
     chroot "$DEST_" "$@"
+    RC=$?
+fi
+
+if [ -z "$STATEDIR" ] ; then
+  umount_all
+else
+  rm "$DEST_/$STATEDIR/$$"
+
+  if rmdir "$DEST_/$STATEDIR" 2>/dev/null; then
+    umount_all
+  fi
 fi
-umount_all
 
+exit $RC