Making references to debian more distribution neutral.
[live-boot-grml.git] / bin / live-snapshot
index 85a0ab5..08eee0a 100755 (executable)
@@ -4,10 +4,10 @@
 #
 #   This program mounts a device (fallback to /tmpfs under $MOUNTP
 #   and saves the /live/cow (or a different directory) filesystem in it
 #
 #   This program mounts a device (fallback to /tmpfs under $MOUNTP
 #   and saves the /live/cow (or a different directory) filesystem in it
-#   for reuse in another live-initramfs session.
+#   for reuse in another live-boot session.
 #   Look at the manpage for more informations.
 #
 #   Look at the manpage for more informations.
 #
-# Copyright (C) 2006-2008 Marco Amadori <marco.amadori@gmail.com>
+# Copyright (C) 2006-2011 Marco Amadori <marco.amadori@gmail.com>
 # Copyright (C) 2008 Chris Lamb <chris@chris-lamb.co.uk>
 #
 # This program is free software: you can redistribute it and/or modify
 # Copyright (C) 2008 Chris Lamb <chris@chris-lamb.co.uk>
 #
 # This program is free software: you can redistribute it and/or modify
@@ -23,7 +23,7 @@
 # You should have received a copy of the GNU General Public License
 # along with this program. If not, see <http://www.gnu.org/licenses/>.
 #
 # You should have received a copy of the GNU General Public License
 # along with this program. If not, see <http://www.gnu.org/licenses/>.
 #
-# On Debian systems, the complete text of the GNU General Public License
+# The complete text of the GNU General Public License
 # can be found in /usr/share/common-licenses/GPL-3 file.
 
 # declare here two vars from /etc/live.conf because of "set -u"
 # can be found in /usr/share/common-licenses/GPL-3 file.
 
 # declare here two vars from /etc/live.conf because of "set -u"
@@ -39,8 +39,12 @@ fi
 
 . /usr/share/initramfs-tools/scripts/live-helpers
 
 
 . /usr/share/initramfs-tools/scripts/live-helpers
 
-LIVE_CONF="/etc/live.conf"
-. "${LIVE_CONF}"
+LIVE_CONF="/etc/live/boot.d/snapshot.conf"
+
+if [ -r "${LIVE_CONF}" ]
+then
+       . "${LIVE_CONF}"
+fi
 
 export USERNAME USERFULLNAME HOSTNAME
 
 
 export USERNAME USERFULLNAME HOSTNAME
 
@@ -59,6 +63,7 @@ TMP_FILELIST="${PROGRAM}.list"
 # Command line defaults and declarations
 SNAP_COW="${DEF_SNAP_COW}"
 SNAP_DEV=""
 # Command line defaults and declarations
 SNAP_COW="${DEF_SNAP_COW}"
 SNAP_DEV=""
+SNAP_MNT=""
 SNAP_OUTPUT=""
 SNAP_RESYNC_STRING=""
 SNAP_TYPE="cpio"
 SNAP_OUTPUT=""
 SNAP_RESYNC_STRING=""
 SNAP_TYPE="cpio"
@@ -99,7 +104,7 @@ Help ()
        echo "  -o, --output: output image file (default: ${DEST})."
        echo "  -r, --resync-string: internally used to resync previous made snapshots."
        echo "  -f, --refresh: try to sync a running snapshot."
        echo "  -o, --output: output image file (default: ${DEST})."
        echo "  -r, --resync-string: internally used to resync previous made snapshots."
        echo "  -f, --refresh: try to sync a running snapshot."
-       echo "  -t, --type: snapshot filesystem type. Options: \"squashfs\", \"ext2\", \"ext3\", \"jffs2\" or \"cpio\".gz archive (default: ${SNAP_TYPE})"
+       echo "  -t, --type: snapshot filesystem type. Options: \"squashfs\", \"ext2\", \"ext3\", \"ext4\", \"jffs2\" or \"cpio\".gz archive (default: ${SNAP_TYPE})"
        echo
        echo "Look at live-snapshot(1) man page for more information."
 
        echo
        echo "Look at live-snapshot(1) man page for more information."
 
@@ -120,12 +125,12 @@ Version ()
 {
        echo "${PROGRAM}"
        echo
 {
        echo "${PROGRAM}"
        echo
-       echo "Copyright (C) 2006 Marco Amadori <marco.amadori@gmail.com>"
+       echo "Copyright (C) 2006-2011 Marco Amadori <marco.amadori@gmail.com>"
        echo "Copyright (C) 2008 Chris Lamb <chris@chris-lamb.co.uk>"
        echo
        echo "This program is free software; you can redistribute it and/or modify"
        echo "it under the terms of the GNU General Public License as published by"
        echo "Copyright (C) 2008 Chris Lamb <chris@chris-lamb.co.uk>"
        echo
        echo "This program is free software; you can redistribute it and/or modify"
        echo "it under the terms of the GNU General Public License as published by"
-       echo "the Free Software Foundation; either version 2 of the License, or"
+       echo "the Free Software Foundation; either version 3 of the License, or"
        echo "(at your option) any later version."
        echo
        echo "This program is distributed in the hope that it will be useful,"
        echo "(at your option) any later version."
        echo
        echo "This program is distributed in the hope that it will be useful,"
@@ -137,8 +142,8 @@ Version ()
        echo "along with this program; if not, write to the Free Software"
        echo "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA"
        echo
        echo "along with this program; if not, write to the Free Software"
        echo "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA"
        echo
-       echo "On Debian systems, the complete text of the GNU General Public License"
-       echo "can be found in /usr/share/common-licenses/GPL-2 file."
+       echo "The complete text of the GNU General Public License"
+       echo "can be found in /usr/share/common-licenses/GPL-3 file."
        echo
        echo "Homepage: <http://debian-live.alioth.debian.org/>"
 
        echo
        echo "Homepage: <http://debian-live.alioth.debian.org/>"
 
@@ -237,11 +242,12 @@ Defaults ()
        # Parse resync string
        if [ -n "${SNAP_RESYNC_STRING}" ]
        then
        # Parse resync string
        if [ -n "${SNAP_RESYNC_STRING}" ]
        then
-               SNAP_COW=$(echo "${SNAP_RESYNC_STRING}" | cut -f1 -d ':')
+               SNAP_COW=$(echo "${SNAP_RESYNC_STRING}" | sed -r -e 's#^([^:]*).*$#'"${DEF_SNAP_COW}"'\1#')
                SNAP_DEV=$(echo "${SNAP_RESYNC_STRING}" | cut -f2 -d ':')
                SNAP_DEV=$(echo "${SNAP_RESYNC_STRING}" | cut -f2 -d ':')
-               DEST="${MOUNTP}/$(echo ${SNAP_RESYNC_STRING} | cut -f3 -d ':')"
+               SNAP_MNT=$(echo "${SNAP_RESYNC_STRING}" | cut -f3 -d ':')
+               DEST="${MOUNTP}/${SNAP_MNT}"
 
 
-               case "${DEST}" in
+               case "${SNAP_MNT}" in
                        *.cpio.gz)
                                SNAP_TYPE="cpio"
                                ;;
                        *.cpio.gz)
                                SNAP_TYPE="cpio"
                                ;;
@@ -254,9 +260,18 @@ Defaults ()
                                SNAP_TYPE="jffs2"
                                ;;
 
                                SNAP_TYPE="jffs2"
                                ;;
 
-                       ""|*.ext2|*.ext3)
+                       *.ext2|*.ext3)
                                SNAP_TYPE="ext2"
                                ;;
                                SNAP_TYPE="ext2"
                                ;;
+
+                       "")
+                               SNAP_TYPE="whole_partition"
+                               ;;
+
+                       *.ext4)
+                               SNAP_TYPE="ext4"
+                               ;;
+
                        *)
                                Error "unrecognized resync string"
                                ;;
                        *)
                                Error "unrecognized resync string"
                                ;;
@@ -276,6 +291,10 @@ Defaults ()
                        ext3)
                                DEST="${MOUNTP}/live-sn.ext2"
                                ;;
                        ext3)
                                DEST="${MOUNTP}/live-sn.ext2"
                                ;;
+
+                       ext4)
+                               DEST="${MOUNTP}/live-sn.ext4"
+                               ;;
                esac
        else
                DEST="${SNAP_OUTPUT}"
                esac
        else
                DEST="${SNAP_OUTPUT}"
@@ -285,7 +304,7 @@ Defaults ()
 Validate_input ()
 {
        case "${SNAP_TYPE}" in
 Validate_input ()
 {
        case "${SNAP_TYPE}" in
-               cpio|squashfs|jffs2|ext2|ext3)
+               cpio|squashfs|jffs2|ext2|ext3|ext4|whole_partition)
                        ;;
 
                *)
                        ;;
 
                *)
@@ -331,7 +350,7 @@ Entry_is_modified ()
 
        if [ -e "${entry}" ] || [ -L "${entry}" ]
        then
 
        if [ -e "${entry}" ] || [ -L "${entry}" ]
        then
-               if [ -e "${DEF_SNAP_COW}/${entry}" ] || [ -L "${DEF_SNAP_COW}/${entry}" ]
+               if [ -e "${SNAP_COW}/${entry}" ] || [ -L "${SNAP_COW}/${entry}" ]
                then
                        return 0
                fi
                then
                        return 0
                fi
@@ -341,17 +360,25 @@ Entry_is_modified ()
 
 Do_filelist ()
 {
 
 Do_filelist ()
 {
-       # BUGS: supports only cpio.gz types, and does not handle deleted files yet
-
+       # BUGS: does not handle deleted files yet
        TMP_FILELIST=$1
        TMP_FILELIST=$1
+
        if [ -f "${SNAP_LIST}" ]
        then
        if [ -f "${SNAP_LIST}" ]
        then
-               # Generate include list
-               for entry in $(cat "${SNAP_LIST}" | grep -v '^#.*$' | grep -v '^ *$')
+               # if SNAP_COW == /live/cow/home, SNAP_RW = /home
+               SNAP_RW=$(echo "${SNAP_COW}" | sed -e "s|${DEF_SNAP_COW}||g")
+               if [ -z "${SNAP_RW}" ]
+               then
+                       SNAP_RW="/"
+               fi
+
+               cd "${SNAP_RW}"
+               # Generate include list removing empty and commented lines
+               # and transforming paths to relatives
+               for entry in $(sed -e '/^ *$/d' -e '/^#.*$/d' -e 's#^.*$#./&#' -e 's#/\+#/#g' "${SNAP_LIST}")
                do
                        if [ -d "${entry}" ]
                        then
                do
                        if [ -d "${entry}" ]
                        then
-                               cd /
                                find "${entry}" | while read line
                                do
                                        if Entry_is_modified "${line}"
                                find "${entry}" | while read line
                                do
                                        if Entry_is_modified "${line}"
@@ -359,26 +386,22 @@ Do_filelist ()
                                                printf "%s\000" "${line}" >> "${TMP_FILELIST}"
                                        fi
                                done
                                                printf "%s\000" "${line}" >> "${TMP_FILELIST}"
                                        fi
                                done
-                               cd "${OLDPWD}"
                        elif Entry_is_modified "${entry}"
                        then
                                # if file exists and it is modified
                                printf "%s\000" "${entry}" >> "${TMP_FILELIST}"
                        fi
                done
                        elif Entry_is_modified "${entry}"
                        then
                                # if file exists and it is modified
                                printf "%s\000" "${entry}" >> "${TMP_FILELIST}"
                        fi
                done
+               cd "${OLDPWD}"
 
 
-               if [ "${SNAP_COW}" = "${DEF_SNAP_COW}" ]
-               then
-                       # Relative to rootfs
-                       echo "/"
-               else
-                       # Mostly "/home"
-                       echo "${SNAP_COW}"
-               fi
+               # echo Working dir
+               echo "${SNAP_RW}"
        else
                cd "${SNAP_COW}"
        else
                cd "${SNAP_COW}"
+               # removing whiteouts from list
                find . -path '*.wh.*' -prune -o -print0 >> "${TMP_FILELIST}"
                cd "${OLDPWD}"
                find . -path '*.wh.*' -prune -o -print0 >> "${TMP_FILELIST}"
                cd "${OLDPWD}"
+               # echo Working dir
                echo "${SNAP_COW}"
        fi
 }
                echo "${SNAP_COW}"
        fi
 }
@@ -397,14 +420,21 @@ Do_snapshot ()
                        if [ -e "${EXCLUDE_LIST}" ]
                        then
                                # Add explicitly excluded files
                        if [ -e "${EXCLUDE_LIST}" ]
                        then
                                # Add explicitly excluded files
-                               cat "${EXCLUDE_LIST}" | grep -v '^#.*$' | grep -v '^ *$' >> "${TMP_FILELIST}"
+                               grep -v '^#.*$' "${EXCLUDE_LIST}" | grep -v '^ *$' >> "${TMP_FILELIST}"
                        fi
 
                        cd "${OLDPWD}"
                        mksquashfs "${SNAP_COW}" "${DEST}" -ef "${TMP_FILELIST}"
                        ;;
 
                        fi
 
                        cd "${OLDPWD}"
                        mksquashfs "${SNAP_COW}" "${DEST}" -ef "${TMP_FILELIST}"
                        ;;
 
-               cpio)
+               cpio|whole_partition)
+                       if [ "${SNAP_TYPE}" = "cpio" ]
+                       then
+                               COPY_CMD="cpio --quiet -o0 -H newc | gzip -9c > ${DEST}"
+                       else
+                               COPY_CMD="cpio --quiet -pumd0 ${DEST}/"
+                       fi
+
                        WORKING_DIR=$(Do_filelist "${TMP_FILELIST}")
                        cd "${WORKING_DIR}"
                        if [ -e "${EXCLUDE_LIST}" ]
                        WORKING_DIR=$(Do_filelist "${TMP_FILELIST}")
                        cd "${WORKING_DIR}"
                        if [ -e "${EXCLUDE_LIST}" ]
@@ -417,19 +447,17 @@ Do_snapshot ()
                                        grep -F -v -f "${EXCLUDE_LIST}" | \
                                        tr '\n' '\0' | \
                                        tr '\1' '\n' | \
                                        grep -F -v -f "${EXCLUDE_LIST}" | \
                                        tr '\n' '\0' | \
                                        tr '\1' '\n' | \
-                                       cpio --quiet -o0 -H newc | \
-                                       gzip -9c > "${DEST}" || exit 1
+                                       eval $COPY_CMD || exit 1
                        else
                                cat "${TMP_FILELIST}" | \
                        else
                                cat "${TMP_FILELIST}" | \
-                                       cpio --quiet -o0 -H newc | \
-                                       gzip -9c > "${DEST}" || exit 1
+                                       eval $COPY_CMD || exit 1
                        fi
                        cd "${OLDPWD}"
                        ;;
 
                        fi
                        cd "${OLDPWD}"
                        ;;
 
-               # ext2|ext3 and jffs2 does not easily support an exclude list; files
+               # ext2|ext3|ext4 and jffs2 does not easily support an exclude list; files
                # should be copied to another directory in order to filter content
                # should be copied to another directory in order to filter content
-               ext2|ext3)
+               ext2|ext3|ext4)
                        DU_DIM="$(du -ks ${SNAP_COW} | cut -f1)"
                        REAL_DIM="$(expr ${DU_DIM} + ${DU_DIM} / 20)" # Just 5% more to be sure, need something more sophistcated here...
                        genext2fs --size-in-blocks=${REAL_DIM} --reserved-percentage=0 --root="${SNAP_COW}" "${DEST}"
                        DU_DIM="$(du -ks ${SNAP_COW} | cut -f1)"
                        REAL_DIM="$(expr ${DU_DIM} + ${DU_DIM} / 20)" # Just 5% more to be sure, need something more sophistcated here...
                        genext2fs --size-in-blocks=${REAL_DIM} --reserved-percentage=0 --root="${SNAP_COW}" "${DEST}"
@@ -462,7 +490,7 @@ Warn_user ()
        if [ -z "${SNAP_RESYNC_STRING}" ]
        then
                case ${SNAP_TYPE} in
        if [ -z "${SNAP_RESYNC_STRING}" ]
        then
                case ${SNAP_TYPE} in
-                       cpio|ext2|ext3)
+                       cpio|ext2|ext3|ext4)
                                echo "Please move ${DEST} (if is not already in it)" > /dev/null 1>&2
                                echo "in a supported writable partition (e.g ext3, vfat)." > /dev/null 1>&2
                                ;;
                                echo "Please move ${DEST} (if is not already in it)" > /dev/null 1>&2
                                echo "in a supported writable partition (e.g ext3, vfat)." > /dev/null 1>&2
                                ;;