#!/bin/bash

TMP=/tmp/changes$$
EXCLUDE="^\$|/\$|[.]wh[.][.]wh[.]orph/|^[.]wh[.][.]pwd[.]lock|^[.]wh[.][.]wh[.]plnk/|^[.]wh[.][.]wh[.]aufs|^var/cache/|^var/backups/|^var/tmp/|^var/log/|^var/lib/apt/|^var/lib/dhcp/|^var/lib/systemd/|^sbin/fsck[.]aufs|^etc/resolv[.]conf|^root/[.]Xauthority|^root/[.]xsession-errors|^root/[.]fehbg|^root/[.]fluxbox/lastwallpaper|^root/[.]fluxbox/menu_resolution|^etc/mtab|^etc/fstab|^boot/|^dev/|^mnt/|^proc/|^run/|^sys/|^tmp/"
CHANGES=/run/initramfs/memory/changes

if [ "$1" = "-h" -o "$1" = "--help" ]; then
   echo ""
   echo "savechanges - save all changed files in a compressed filesystem bundle"
   echo "            - excluding some predefined files such as /etc/mtab,"
   echo "              temp & log files, empty directories, apt cache, and such"
   echo ""
   echo "Usage:"
   echo "        $0 [ target_file.sb ] [ changes_directory ]"
   echo ""
   echo "If changes_directory is not specified, /run/initramfs/memory/changes is used."
   echo "If target_file.sb is not specified, /run/initramfs/memory/data/slax/modules/99-changes-??.sb is used."
   echo ""
   exit 1
fi

TARGET="$1"

if [ "$TARGET" = "" ]; then
   TARGETDIR=/run/initramfs/memory/data/slax/modules
   ix=$(cat /run/savechanges.session 2>/dev/null)
   if [ "$ix" = "" ]; then
      ix=$(cd $TARGETDIR; ls -1 | sort -V | tail -n 1 | sed -r "s/^99-changes-//" | sed -r "s/[.]sb\$//")
      ix=$(($ix + 1))
   fi
   echo $ix > /run/savechanges.session
   TARGET=$TARGETDIR/99-changes-$ix.sb
fi

touch $TARGET || exit 1

if [ ! "$2" = "" ]; then
   CHANGES="$2"
fi

# Overlayfs requires one more subdir. Detect it this way
if [ -d "$CHANGES/changes" -a -d "$CHANGES/workdir" -a "$(ls -1 "$CHANGES" | egrep -v '^changes$' | egrep -v '^workdir')" = "" ]; then
   CHANGES="$CHANGES/changes"
fi

# exclude control files for automounted disk drives
EXCLUDEDISKS=$(grep "Slax skip savechanges" /etc/systemd/system/{*,*/*} 2>/dev/null | cut -d : -f 1 | cut -b 2- | tr '\n' '|')
if [ "$EXCLUDEDISKS" != "" ]; then
   EXCLUDE="$EXCLUDE|^($EXCLUDEDISKS)\$"
fi

# exclude the save_file itself of course
EXCLUDE="$EXCLUDE|^""$(readlink -f "$TARGET" | cut -b 2- | sed -r "s/[.]/[.]/")""\$"

CWD=$(pwd)

cd $CHANGES || exit

mkdir -p $TMP
mount -t tmpfs tmpfs $TMP

find \( -type d -printf "%p/\n" , -not -type d -print \) \
  | sed -r "s/^[.]\\///" | egrep -v "$EXCLUDE" \
  | while read FILE; do
    cp --parents -afr "$FILE" "$TMP"
done

cd $CWD

mksquashfs $TMP "$TARGET" -comp xz -b 1024K -Xbcj x86 -always-use-fragments -noappend > /dev/null

umount $TMP
rmdir $TMP
