#!/usr/bin/env bash # used to work around cases where stdin is unavailable or not a terminal if bash -c ': > /dev/tty' > /dev/null 2>&1; then TTY_OR_CONSOLE="/dev/tty" else TTY_OR_CONSOLE="/dev/console" fi function echo_tty { if [ "$1" = "-n" ]; then shift echo -n "$@" > $TTY_OR_CONSOLE else echo "$@" > $TTY_OR_CONSOLE fi } function yesno { unset DISCARD_ME while [ -z "$DISCARD_ME" ]; do read -p "[y/n] " -n1 DISCARD_ME < $TTY_OR_CONSOLE > $TTY_OR_CONSOLE case "$DISCARD_ME" in y) echo_tty return 0 ;; n) echo_tty return 1 ;; *) echo_tty " Please enter y for yes or n for no." unset DISCARD_ME ;; esac done } #TODO: refuse to run if system is running if [ "$1" = "--yes" ]; then DONT_ASK="true" else DONT_ASK="false" echo_tty "Create a new system image?" echo_tty echo_tty "This will replace the existing system image with a snapshot of the currently" echo_tty "running system. Choosing no here will discard any newly installed programs," echo_tty "updates, system configuration changes, etc." echo_tty echo_tty "This should not affect your files in /home as they are stored to disk directly." echo_tty "Check /TODO/README.txt for more information." echo_tty echo_tty "Creating a new system image will take some time." echo_tty fi #TODO: colors (bright white / light gray for readability) if $DONT_ASK || yesno; then echo_tty -n "Generating exclusion list... " # cutting off the leading slash allows us to just ignore empty lines below readarray -t MOUNT_LIST <<< "$(findmnt --output TARGET --noheadings --raw | sed -e 's|^/||' | sort)" # always ignore /tmp and the package cache EXCLUDE_LIST=("tmp" "var/cache/xbps") for I in ${!MOUNT_LIST[@]}; do if [ ! -z "${MOUNT_LIST[$I]}" ]; then FOUND=0 for J in ${!EXCLUDE_LIST[@]}; do if grep "${EXCLUDE_LIST[$J]}" > /dev/null <<< "${MOUNT_LIST[$I]}"; then FOUND=1 break fi done # if no parent dir of ${MOUNT_LIST[$I]} is found in $EXCLUDE_LIST if [ $FOUND -eq 0 ]; then EXCLUDE_LIST+=("${MOUNT_LIST[$I]}") fi fi done touch /run/void-usb/system-image-excludes touch /run/void-usb/system-image-pseudo for I in ${!EXCLUDE_LIST[@]}; do echo "/${EXCLUDE_LIST[$I]}" >> /run/void-usb/system-image-excludes FILE_PERMS="$(stat -c '%a %u %g' "${EXCLUDE_LIST[$I]}")" echo "\"/${EXCLUDE_LIST[$I]}\" d $FILE_PERMS" >> /run/void-usb/system-image-pseudo done echo_tty "done" echo_tty "Building image..." mksquashfs / /run/void-usb/container/new_squashfs.img -b 1M -comp xz -progress -noappend -pf /run/void-usb/system-image-pseudo -ef /run/void-usb/system-image-excludes > $TTY_OR_CONSOLE echo_tty -n "Moving new image in place... " mv /run/void-usb/container/new_squashfs.img /run/void-usb/container/squashfs.img echo_tty "done" else echo_tty "Discarding system changes." fi echo_tty -n "Syncing... " sync echo_tty "done"