[Patch 4/5]
Author: Frederick Grose <fgrose@sugarlabs.org>
Date:   Thu Apr 14 10:53:09 2011 -0400

    Support installation of customized builds with --copy-home and
    --include options.
   
    Custom isos may package home.img and extra files or directories.
   
    Fix logic on unmounting and removing SRCMNT & TGTMNT.
    Include uncompressed ext3fs.img in detectsrctype() logic.
    Use loop mount for SRCMNT on running Live images.
    Add error messages and disc space estimation adjustments.
    Tolerate user changes to 'quiet rhgb' in configuration file.
    Support F15-style rd.luks=0 in configuration file adjustment.

diff --git a/tools/livecd-iso-to-disk.sh b/tools/livecd-iso-to-disk.sh
index 5261aab..de48ec4 100755
--- a/tools/livecd-iso-to-disk.sh
+++ b/tools/livecd-iso-to-disk.sh
@@ -33,6 +33,7 @@ shortusage() {
                        [--compress] [--skipcompress] [--swap-size-mb <size>]
                        [--overlay-size-mb <size>] [--home-size-mb <size>]
                        [--delete-home] [--crypted-home] [--unencrypted-home]
+                       [--copy-home]  [--include <file s>]
                        <source> <target device>
 
     (Enter livecd-iso-to-disk --help on the command line for more information.)"
@@ -242,6 +243,20 @@ usage() {
     --unencrypted-home
         Prevents the default option to encrypt a new persistent home directory.
 
+    --copy-home
+        This option allows one to copy a persistent home folder from one LiveOS
+        image to the target image.  Changes already made in the source home
+        directory will be propagated to the new image.
+            WARNING: User-sensitive information, such as password cookies and
+            user and application data, will be copied to the new image! Scrub
+            this information before using this option.
+
+    --include <path s>
+        This option allows one to copy one or more file or directory paths from
+        the outer source filesystem to the same path on the target.
+        Multiple paths should be specified in one string, i.e.,
+            --include "path1 path2 ..."
+
     CONTRIBUTORS
 
     livecd-iso-to-disk: David Zeuthen, Jeremy Katz, Douglas McClendon,
@@ -272,8 +287,14 @@ usage() {
 
 cleanup() {
     sleep 2
-    [ -d "$SRCMNT" ] && umount $SRCMNT && rmdir $SRCMNT
-    [ -d "$TGTMNT" ] && umount $TGTMNT && rmdir $TGTMNT
+    if [[ -d $SRCMNT ]]; then
+        umount $SRCMNT
+        rmdir $SRCMNT
+    fi
+    if [[ -d $TGTMNT ]]; then
+        umount $TGTMNT
+        rmdir $TGTMNT
+    fi
 }
 
 exitclean() {
@@ -594,7 +615,8 @@ if [ $(id -u) != 0 ]; then
 fi
 
 detectsrctype() {
-    if [[ -e $SRCMNT/LiveOS/squashfs.img ]]; then
+    if [[ -e $SRCMNT/LiveOS/squashfs.img ||
+          -e $SRCMNT/LiveOS/ext3fs.img ]]; then
         srctype=live
         return
     fi
@@ -652,6 +674,8 @@ shopt -s extglob
 
 cryptedhome=1
 keephome=1
+copyhome=
+copyhomesize=0
 homesizemb=0
 swapsizemb=0
 overlaysizemb=0
@@ -659,6 +683,7 @@ srctype=
 imgtype=
 LIVEOS=LiveOS
 HOMEFILE="home.img"
+includes=
 
 if [[ "$*" =~ "--help" ]]; then
     usage
@@ -747,6 +772,14 @@ while [ $# -gt 2 ]; do
         --delete-home)
             keephome=""
             ;;
+        --copy-home)
+            copyhome=1
+            cryptedhome=""
+            ;;
+        --include)
+            includes=($2)
+            shift
+            ;;
         *)
             echo "invalid arg -- $1"
             shortusage
@@ -795,6 +828,7 @@ fi
 
 # do some basic sanity checks.
 checkMounted $TGTDEV
+! [[ /dev/live == $1 || /dev/sr0 == $1 ]] && checkMounted $SRC
 
 # Format the device
 if [ -n "$format" -a -z "$skipcopy" ]; then
@@ -850,10 +884,13 @@ fi
 
 # FIXME: would be better if we had better mountpoints
 SRCMNT=$(mktemp -d /media/srctmp.XXXXXX)
-if [ -b $SRC ]; then
-    mount -o ro "$SRC" $SRCMNT || exitclean
-elif [ -f $SRC ]; then
+if [[ -f $SRC || /dev/live == $1 || /dev/sr0 == $1 ]]; then
     mount -o loop,ro "$SRC" $SRCMNT || exitclean
+    imgtype='iso'
+    [[ /dev/live == $1 ]] && imgtype='live'
+elif [[ -b $SRC ]]; then
+    mount -o ro "$SRC" $SRCMNT || exitclean
+    imgtype='blk'
 else
     echo "$SRC is not a file or block device."
     exitclean
@@ -865,11 +902,53 @@ trap exitclean SIGINT SIGTERM
 
 detectsrctype
 
-if [ -f "$TGTMNT/$LIVEOS/$HOMEFILE" -a -n "$keephome" -a "$homesizemb" -gt 0 ]; then
-    echo "ERROR: Requested keeping existing /home and specified a size for /home"
-    echo "Please either don't specify a size or specify --delete-home"
+if [[ -d $SRCMNT/LiveOS ]]; then
+    SRCLIVEOSDIR=$SRCMNT/LiveOS
+else
+    SRCLIVEOSDIR=$SRCMNT
+fi
+if [[ ! -f $SRCMNT/$LIVEOS/$HOMEFILE && -n $copyhome ]]; then
+    echo -e "ERROR: There appears to be no persistent /home.img on the source
+       Please check your inputs.\n"
+    exitclean
+fi
+if [[ -f $SRCMNT/$LIVEOS/$HOMEFILE && -n $copyhome && -n $cryptedhome ]]; then
+    echo -e "WARNING: You asked for an --encrypted-home and to copy the source's
+         /home.img to your target device.  The --encrypted-home option is only
+         available for newly-created /home directories.  (If the /home.img on
+         the source is encrypted, that feature will carry over.)\n
+         Press Enter to continue, or Ctrl-c to abort.\n"
+    read
+fi
+if [[ -f $TGTMNT/$LIVEOS/$HOMEFILE && -n $keephome && $homesizemb -gt 0 ]]; then
+    echo -e "ERROR: The target has an existing /home and you requested that a
+       new /home.img be created.
+       To remove an existing /home on the target, you must explicitly specify
+       --delete-home.
+       Please adjust your home options.\n"
+    exitclean
+fi
+if [[ -f $TGTMNT/$LIVEOS/$HOMEFILE && -n $keephome && -n $copyhome && \
+      -s $SRCMNT/$LIVEOS/$HOMEFILE ]]; then
+    echo -e "ERROR: The target has an existing /home and you requested that one
+       from the source be copied to the target device.
+       To remove an existing /home on the target, you must explicitly specify
+       --delete-home.
+       Please adjust your home options.\n"
     exitclean
 fi
+if [[ -s $SRCMNT/$LIVEOS/$HOMEFILE && -n $copyhome && $homesizemb -gt 0 ]]; then
+    echo -e "ERROR: You requested a new home AND a copy of one from the source.
+       Please request only one of these options.\n"
+    exitclean
+fi
+if [[ ! -s $SRCLIVEOSDIR/$HOMEFILE && -n $copyhome && $overlaysizemb -gt 0 ]]; then
+    echo -e "NOTICE: There appears to be no persistent /home.img on this image.
+        Would you LIKE to continue with just the persistent overlay?\n
+        Press Enter to continue, or Ctrl-c to abort.\n"
+    read
+    copyhome=""
+fi
 
 if [ -n "$efi" ]; then
     if [ -d $SRCMNT/EFI/BOOT ]; then
@@ -894,11 +973,11 @@ else
 fi
 
 if [[ live == $srctype ]]; then
-   targets="$TGTMNT/$SYSLINUXPATH"
-   [[ -n $efi ]] && targets+=" $TGTMNT$EFI_BOOT"
-   [[ -n $xo ]] && targets+=" $TGTMNT/boot/olpc.fth"
-   duTable=($(du -c -B 1M $targets 2> /dev/null || :))
-   tbd=$((tbd + ${duTable[*]: -2:1}))
+    targets="$TGTMNT/$SYSLINUXPATH"
+    [[ -n $efi ]] && targets+=" $TGTMNT$EFI_BOOT"
+    [[ -n $xo ]] && targets+=" $TGTMNT/boot/olpc.fth"
+    duTable=($(du -c -B 1M $targets 2> /dev/null || :))
+    tbd=$((tbd + ${duTable[*]: -2:1}))
 fi
 
 if [[ -n $skipcompress ]] && [[ -s $SRCMNT/LiveOS/squashfs.img ]]; then
@@ -931,22 +1010,52 @@ if [[ live == $srctype ]]; then
     [[ -n $xo ]] && sources+=" $SRCMNT/boot/olpc.fth"
     duTable=($(du -c -B 1M "$thisScriptpath" $sources 2> /dev/null || :))
     livesize=$((livesize + ${duTable[*]: -2:1}))
+    [[ -s $SRCLIVEOSDIR/$HOMEFILE  && -n $copyhome ]] && \
+        copyhomesize=($(du -s -B 1M $SRCLIVEOSDIR/$HOMEFILE))
+    if [[ 'iso' == $imgtype ]]; then
+        [[ -e $SRCMNT/boot ]] && findargs=$SRCMNT/boot
+        findargs+=" $SRCMNT"' -xdev -mindepth 1 -maxdepth 1
+            ( -type d -o -type f )
+            ! ( -name isolinux -o -name LiveOS -o -name EFI -o -name olpc.fth )
+            -print0'
+    fi
+    if [[ -n $includes ]]; then
+        includes=(${includes[@]/#/$SRCMNT})
+        for i in ${!includes[*]}; do
+            if [[ ! -e ${includes[i]} ]]; then
+                echo -e "\n${includes[i]#$SRCMNT} does not exist.
+                Please check your input.  Exiting..."; exitclean
+            fi
+        done
+    fi
+    includes_size=0
+    if [[ -n $includes || -n $findargs ]]; then
+        duTable=($(find ${includes[*]} $findargs | \
+                   du -cs -B 1M --files0-from=-))
+        includes_size=${duTable[*]: -2:1}
+    fi
 fi
 
 freespace=($(df -B 1M --total $TGTDEV))
 freespace=${freespace[*]: -2:1}
 
 if [[ live == $srctype ]]; then
-    tba=$((overlaysizemb + homesizemb + livesize + swapsizemb))
+    tba=$((overlaysizemb + homesizemb + copyhomesize + includes_size + \
+        livesize + swapsizemb))
     if ((tba > freespace + tbd)); then
         needed=$((tba - freespace - tbd))
-        printf "\n  The live image + overlay, home, & swap space, if requested,
-        \r  will NOT fit in the space available on the target device.\n
-        \r  + Size of live image: %10s  MiB\n" $livesize
+        printf "\n  The live image + overlay, home, includes, & swap space,
+        \r  if requested, will NOT fit in the space available on the
+        \r  target device.\n
+         \r  + Size of live image: %10s  MiB\n" $livesize
         (($overlaysizemb > 0)) && \
             printf "  + Overlay size: %16s\n" $overlaysizemb
         (($homesizemb > 0)) && \
             printf "  + Home directory size: %9s\n" $homesizemb
+        (($copyhomesize > 0)) && \
+            printf "  + Copy home directory size: %4s\n" $copyhomesize
+        (($includes_size > 0)) && \
+            printf "  + Included files size: %9s\n" $includes_size
         (($swapsizemb > 0)) && \
             printf "  + Swap overlay size: %11s\n" $swapsizemb
         printf "  = Total requested space:  %6s  MiB\n" $tba
@@ -1030,6 +1139,18 @@ if [ "$srctype" = "live" -a -z "$skipcopy" ]; then
     if [ -f $SRCMNT/LiveOS/osmin.img ]; then
         copyFile $SRCMNT/LiveOS/osmin.img $TGTMNT/$LIVEOS/osmin.img || exitclean
     fi
+    if [[ -s $SRCLIVEOSDIR/$HOMEFILE  && -n $copyhome ]]; then
+        copyFile $SRCLIVEOSDIR/$HOMEFILE $TGTMNT/$LIVEOS/$HOMEFILE || exitclean
+    fi
+    cp_mode='-ax'
+    [[ 'vfat' == $TGTFS || 'msdos' == $TGTFS ]] && cp_mode='-dRx'
+    if [[ 'iso' == $imgtype ]]; then
+        find $findargs -exec cp $cp_mode -t $TGTMNT {} + 1> /dev/null ||
+            exitclean
+    fi
+    if [[ -n $includes ]]; then
+        cp $cp_mode -t $TGTMNT ${includes[*]} || exitclean
+    fi
     sync
 fi
 
@@ -1112,7 +1233,8 @@ if [[ live == $srctype ]]; then
     if [[ -d $SRCMNT/syslinux/ ]]; then
         echo "Preparing boot config file."
         sed -i -e "s/root=live:[^ ]*/root=live:CDLABEL=name/"\
-               -e "s/liveimg .* quiet/liveimg quiet/"\
+               -e "s/liveimg .* rd_NO_LUKS/liveimg quiet rhgb rd_NO_LUKS/"\
+               -e "s/liveimg .* rd.luks=0/liveimg quiet rhgb rd.luks=0/"\
                     $BOOTCONFIG $BOOTCONFIG_EFI
         sed -i -e "s/^timeout.*$/timeout\ 100/"\
                -e "/^totaltimeout.*$/d" $BOOTCONFIG