+Entry_is_modified ()
+{
+ # Returns true if file exists and it is also present in "cow" directory
+ # This means it is modified in respect to read-only media, so it deserve
+ # to be saved
+
+ entry="${1}"
+
+ if [ -e "${entry}" ] || [ -L "${entry}" ]
+ then
+ if [ -e "${SNAP_COW}/${entry}" ] || [ -L "${SNAP_COW}/${entry}" ]
+ then
+ return 0
+ fi
+ fi
+ return 1
+}
+
+Do_filelist ()
+{
+ # BUGS: does not handle deleted files yet
+ TMP_FILELIST=$1
+
+ if [ -f "${SNAP_LIST}" ]
+ then
+ # if SNAP_COW == /live/overlay/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
+ find "${entry}" | while read line
+ do
+ if Entry_is_modified "${line}"
+ then
+ printf "%s\000" "${line}" >> "${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}"
+
+ # echo Working dir
+ echo "${SNAP_RW}"
+ else
+ cd "${SNAP_COW}"
+ # removing whiteouts from list
+ find . -path '*.wh.*' -prune -o -print0 >> "${TMP_FILELIST}"
+ cd "${OLDPWD}"
+ # echo Working dir
+ echo "${SNAP_COW}"
+ fi
+}
+
+Do_snapshot ()
+{
+ TMP_FILELIST=$(mktemp -p "${SAFE_TMPDIR}" "${TMP_FILELIST}.XXXXXX")
+ if [ -e "${EXCLUDE_LIST}" ]
+ then
+ # Create a TMP filelist removing empty lines (grep -f does not like them)
+ # and comments (for speedup and LST)
+ TMP_EXCLUDE_LIST=$(mktemp -p "${SAFE_TMPDIR}" "${PROGRAM}_excludelist.XXXXXX")
+ grep -v '^#.*$' "${EXCLUDE_LIST}" | grep -v '^ *$' > "${TMP_EXCLUDE_LIST}"
+ fi
+
+ case "${SNAP_TYPE}" in
+ squashfs)
+ echo ".${TMP_FILELIST}" > "${TMP_FILELIST}"
+ # Removing whiteheads of unionfs
+ cd "${SNAP_COW}"
+ find . -name '*.wh.*' >> "${TMP_FILELIST}"
+
+ if [ -e "${EXCLUDE_LIST}" ]
+ then
+ # Add explicitly excluded files
+ cat "${TMP_EXCLUDE_LIST}" >> "${TMP_FILELIST}"
+ fi
+
+ cd "${OLDPWD}"
+ mksquashfs "${SNAP_COW}" "${DEST}" -ef "${TMP_FILELIST}"
+ ;;
+
+ 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}" ]
+ then
+
+ # Convert \0 to \n and tag existing (rare but possible) \n in filenames,
+ # this to let grep -F -v do a proper work in filtering out
+ cat "${TMP_FILELIST}" | \
+ tr '\n' '\1' | \
+ tr '\0' '\n' | \
+ grep -F -v -f "${TMP_EXCLUDE_LIST}" | \
+ tr '\n' '\0' | \
+ tr '\1' '\n' | \
+ eval $COPY_CMD || exit 1
+ else
+ cat "${TMP_FILELIST}" | \
+ eval $COPY_CMD || exit 1
+ fi
+ cd "${OLDPWD}"
+ ;;
+
+ # ext2|ext3|ext4 and jffs2 does not easily support an exclude list; files
+ # should be copied to another directory in order to filter content
+ 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}"
+ ;;
+
+ jffs2)
+ mkfs.jffs2 --root="${SNAP_COW}" --output="${DEST}"
+ ;;
+ esac
+
+ # Remove temporary file lists
+ for filelist in "${TMP_FILELIST}" "${TMP_EXCLUDE_LIST}"
+ do
+ if [ -f "${filelist}" ]
+ then
+ rm -f "${filelist}"
+ fi
+ done