Skip to content

Instantly share code, notes, and snippets.

@bkahlert
Last active August 24, 2021 10:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bkahlert/9ba2228f0ebb0de8dbd21b90e83f35da to your computer and use it in GitHub Desktop.
Save bkahlert/9ba2228f0ebb0de8dbd21b90e83f35da to your computer and use it in GitHub Desktop.
POSIX script to access EXT4 partitions in img files
#!/bin/sh
# Abort script at first error, when a command exits with non-zero status
# (except in until or while loops, if-tests, list constructs)
set -e
# Attempt to use undefined variable outputs error message, and forces an exit
set -u
# Similar to verbose mode (-v), but expands commands
#set -x
# Causes a pipeline to return the exit status of the last command in the pipe
# that returned a non-zero return value.
set -o pipefail
# Causes libguestfs to display (very verbose) debug information
LIBGUESTFS_DEBUG=0
# Causes libguestfs to display a few dozens of traces
LIBGUESTFS_TRACE=0
_confirmOrQuit() {
QUESTION="${1:-"Do you want to continue?":}"
read -n1 -s -r -p "${QUESTION}" key
printf "\n\e[1A\e[K\e[2m%s\e[m" "${QUESTION}"
if [ "$key" = '' ]; then
printf "\e[1;32m✔\e[m\n"
else
printf "\e[1;91m✘\e[m\n"
exit 0
fi
}
_isAbsolute() {
case "$1" in
/*)
return 0
;;
*)
return 1
;;
esac
}
GUESTFISH_IMAGE="$(find -s . -iname "*.img" -not -path "./shared/*" | head -n 1)"
if [ ! -f "${GUESTFISH_IMAGE}" ]; then
printf "\e[1;31mNo image found to copy out from.\e[39m\n"
printf "Please run \e[1;96m%s\e[39m in a directory containing an \e[1;96m%s\e[39m file.\n" "$(basename "$0")" ".img"
exit 1
fi
printf "\e[40;90m░\e[49;39m\e[46;96m░\e[49;39m\e[44;94m░\e[49;39m\e[42;92m░\e[49;39m\e[43;93m\e[49;39m\e[45;95m░\e[49;39m\e[41;91m░\e[49;39m \e[96m%s\e[39m \e[36m%s\e[39m\n" "COPY-OUT" "from ${GUESTFISH_IMAGE}"
PATH_TO_COPY="${1:-/}"
if ! _isAbsolute "${PATH_TO_COPY}"; then
_confirmOrQuit "$(printf "An absolute path is required. Use \e[1;96m/%s\e[m instead? " "${PATH_TO_COPY}")"
PATH_TO_COPY="/${PATH_TO_COPY}"
fi
if [ "${PATH_TO_COPY}" = "/" ] && [ -n "$(find "${GUESTFISH_IMAGE}" -prune -size +200000000c)" ]; then
_confirmOrQuit "$(printf "The image is rather big. Are you sure you want to copy-out \e[1;96m%s\e[39m ? " "${PATH_TO_COPY}")"
fi
PATH_TO_COPY_TO=$(dirname "${PATH_TO_COPY}")
if [ "${PATH_TO_COPY_TO}" = "/" ]; then
PATH_TO_COPY_TO=""
fi
printf "Copying out \e[1;96m%s\e[m to \e[1;96m%s\e[m ...\n" "${PATH_TO_COPY}" "shared${PATH_TO_COPY_TO}"
GUESTFISH_SHARED_DIR="$(pwd)/shared"
if [ ! -e "${GUESTFISH_SHARED_DIR}" ]; then
mkdir "${GUESTFISH_SHARED_DIR}"
fi
docker 2>&1 run \
--env LIBGUESTFS_DEBUG="${LIBGUESTFS_DEBUG}" \
--env LIBGUESTFS_TRACE="${LIBGUESTFS_TRACE}" \
--rm \
-i \
--mount type=bind,source="${GUESTFISH_SHARED_DIR}",target=/shared \
--mount type=bind,source="$(pwd)/${GUESTFISH_IMAGE}",target=/images/disk.img \
-w / \
bkahlert/libguestfs \
/usr/bin/guestfish \
--ro \
--add /images/disk.img \
--mount /dev/sda2:/ \
--mount /dev/sda1:/boot \
<<COMMANDS
!mkdir -p "shared${PATH_TO_COPY}"
-copy-out "${PATH_TO_COPY}" "shared${PATH_TO_COPY_TO}"
umount-all
exit
COMMANDS
if [ -z "$(ls -A "${GUESTFISH_SHARED_DIR}")" ]; then
rmdir "${GUESTFISH_SHARED_DIR}"
fi
printf "Successfully copied out \e[1;96m%s\e[39m to \e[1;96m%s\e[39m\n" \
"${PATH_TO_COPY}" \
"shared${PATH_TO_COPY_TO}"
@bkahlert
Copy link
Author

copy-out

Simply type copy-out.
This script searches the current directory automatically for an .img file and copies its content to a newly created directory shared.

Type copy-out <path> to only copy a specific directory or file.

Uses a dockerized guestfish to do its magic. Should work on all POSIX platforms with installed Docker but only tested on macOS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment