diff options
-rwxr-xr-x | bootless | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/bootless b/bootless new file mode 100755 index 0000000..6f72da8 --- /dev/null +++ b/bootless @@ -0,0 +1,228 @@ +#!/bin/bash +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License along with this program. If not, see +# <http://www.gnu.org/licenses/>. + +# Loader +function bootless_load { + local dest + local base + + # Determine if we are in a local or system-wide install. + if [ -h "$0" ]; then + dest="$(readlink $0)" + + # Check again as the caller might be a symlink as well + if [ -h "$dest" ]; then + base="`dirname $dest`" + dest="$(dirname $(readlink $dest))" + else + base="`dirname $0`" + dest="`dirname $dest`" + fi + + # Deal with relative or absolute links + if [ "`basename $dest`" == "$dest" ]; then + export APP_BASE="$base" + else + export APP_BASE="$dest" + fi + else + export APP_BASE="`dirname $0`" + fi +} + +# Usage +function bootless_usage { + echo "Usage: `basename $0` <action> <folder> [arguments]" + exit 1 +} + +# Sync bootless folder +function bootless_rsync { + # Exclude git folder and follow git-annex symlinks + rsync -CLavz --exclude boot $1/ $2/ + + # Make sure there's a symlink to itself + ( cd $2 && ln -s . boot ) +} + +# Repository initiator +function bootless_init { + if [ -e "$BOOTLESS_DIR" ]; then + echo "folder $BOOTLESS_DIR already exists" + exit 1 + fi + + if [ ! -z "$1" ]; then + # Clone from url + git clone $1 $BOOTLESS_DIR + + # Support for git-annex + #( cd $BOOTLESS_DIR && git annex init && git config annex.sshcaching false && git annex sync ) + exit $? + fi + + # Create a fresh repository + mkdir -p $BOOTLESS_DIR/{default,custom,grub} + mkdir -p $BOOTLESS_DIR/custom/{debian,memtest} + touch $BOOTLESS_DIR/{default,custom,grub}/.empty + touch $BOOTLESS_DIR/default/{debian,memtest}/.empty + ( cd $BOOTLESS_DIR && ln -s . boot) + + if [ -f "/boot/memtest86+.bin" ]; then + cp /boot/memtest86+.bin $BOOTLESS_DIR/default/memtest + else + echo "No memtest image found. Please install memtest86+ package" + echo "and manually copy /boot/memtest86+.bin if you want memtest support" + fi + + # Grub configuration + cp $APP_BASE/templates/grub.cfg $BOOTLESS_DIR/grub/ + cp $APP_BASE/templates/custom.cfg $BOOTLESS_DIR/custom/ + + # Initialize git repository + #( + #cd $BOOTLESS_DIR + #git init + #git annex init + #git config annex.sshcaching false + #git add boot + #git add {default,custom,grub}/.empty + #git add default/{debian,memtest,ubuntu}/.empty + #git add grub/grub.cfg + #git annex add . + #git commit -a -m "Initial import" + #) + + echo "Now add your boot images and/or edit $BOOTLESS_DIR/custom/custom.cfg to suit your needs." +} + +function bootless_warning { + local device=$1 + local go + + echo "******************" + echo "* ATTENTION!!! *" + echo "******************" + echo "" + echo "If you continue, all data in device \"${device}\" will be destroyed!" + echo "" + echo -n "Are you sure you want to continue? Type uppercase \"YES\": " + read go + + if [ "${go}" != "YES" ]; then + false + else + true + fi +} + +# Generate a bootless disk image +function bootless_image { + local output="$1" + local device="$2" + + if [ ! -d "$BOOTLESS_DIR" ]; then + echo "missing $BOOTLESS_DIR folder, please initialize first" + exit 1 + fi + + # Fix parameters + if echo ${output} | grep -q "/dev/"; then + output="bootless.iso" + device="$1" + elif [ -z "$output" ]; then + output="bootless.iso" + fi + + # Set sudo config + local sudo + if [ "`whoami`" != 'root' ]; then + sudo="sudo" + fi + + # Copy data + tmpdir=`mktemp --tmpdir=/tmp -d` + bootless_rsync ${BOOTLESS_DIR} ${tmpdir}/boot + + # Make rescue disk + grub-mkrescue -o ${output} ${tmpdir} + + # Optionally copy to removable media + if [ ! -z "$device" ]; then + # Issue a warning + bootless_warning ${device} + + if [ "$?" != "0" ]; then + echo "Skipping copy of ${output} to ${device}..." + else + # Check if device is mounted + if [ "`mount | grep ${device}`" != "" ]; then + echo "Error: device \"${device}\" is mounted." + echo "Skipping copy of ${output} to ${device}..." + else + $sudo dd if=${output} of=${device} + fi + fi + + fi + + # Cleanup + rm -rf ${tmpdir} + + # Finish + if [ -z "$device" ]; then + echo "Image saved at ${output}" + else + echo "Removing image ${output}..." + rm ${output} + fi + + echo "Done." +} + +# Check image/device integrity +function bootless_check { + echo "Not implemented yet :(" + exit 1 +} + +# Load +bootless_load $* + +# Config +NAME="bootless" +BOOTLESS_VERSION="0.0.1" +BOOTLESS_ACTION="$1" +BOOTLESS_DIR="$2" + +# Output name and version +echo "$NAME $BOOTLESS_VERSION" + +# Parameter verification +if [ -z "$BOOTLESS_DIR" ]; then + bootless_usage +elif [ "$BOOTLESS_ACTION" == "init" ]; then + shift 2 + bootless_init $* +elif [ "$BOOTLESS_ACTION" == "image" ]; then + shift 2 + bootless_image $* +elif [ "$BOOTLESS_ACTION" == "check" ]; then + shift 2 + bootless_check $* +else + bootless_usage +fi |