#!/bin/sh # set -ue #set -x #################### some settings ###################### # the base directory of your local development files ROOT_DIR=$(cd $(dirname "$0"); pwd) # the user may define a different location for the local configuration by setting "LOCAL_CONF_DIR" # otherwise use the default (local.conf.d) LOCALCONF_DIR=${LOCALCONF_DIR:-${ROOT_DIR}/local.conf.d} MASTER=$LOCALCONF_DIR/master.img BUILD_DIR=${BUILD_DIR:-$ROOT_DIR/build} IMAGE_DIR=${IMAGE_DIR:-$BUILD_DIR/images} SCRIPTS_DIR=$LOCALCONF_DIR/chroot_scripts.d TEMPLATE_DIR=$LOCALCONF_DIR/template-tree.d PKG_INSTALL_LIST_DIR=$LOCALCONF_DIR/package-install.lst.d PKG_REMOVE_LIST_DIR=$LOCALCONF_DIR/package-remove.lst.d ROOT_DIR=$BUILD_DIR/rootfs BOOT_DIR=$BUILD_DIR/bootfs TMP_DIR=$BUILD_DIR/tmp BACKUP_DIR=$BUILD_DIR/backup IMAGE_FILE=$IMAGE_DIR/remastered.iso IMAGEZ_FILE=$IMAGE_DIR/remastered.iso.z CDWRITER=0,0,0 ################# quite constant things ################# # the relative name of the image file on the cd KNOPPIX_IMAGE=KNOPPIX/KNOPPIX # isofs options MKISOFS_OPTIONS="-allow-multidot -U -D -iso-level 3 -b lib/grub/i386-pc/stage2_eltorito -no-emul-boot -boot-load-size 1 -boot-info-table -pad -R" ################### general functions ################### # maybe this could be useful later # for now it DOES NOT WORK # # get the path of a configuration file - local configuration files # supersede default files # parameter: base name of the configuration file function get_config_file() { [ -e "$LOCALCONF_DIR/$1" ] && echo "$LOCALCONF_DIR/$1" && return 0 [ -e "$DEFAULTCONF_DIR/$1" ] && echo "$DEFAULTCONF_DIR/$1" && return 0 echo "configuration file ($1) not found!" >&2 exit 1 } # just adds a tabulator at the beginning of every line (nice for sub-processes) # you should redirect stderr to stdout before, by adding '2>&1' to the previous command # example: "do_something_useful 2>&1 | indentation" function indentation() { sed 's/^/\t/' } function error_die() { echo "$2" >&2 exit $1 } ##################### active functions ################# function master_get() { umount_procfs local MASTER_MNT=$TMP_DIR/mnt-master-iso local ROOT_MNT=$TMP_DIR/mnt-roof-cloop echo "Mounting the master's image ..." local MNT_OPTIONS= # use loop option for mount, if the master is a file [ -f "$MASTER" ] && MNT_OPTIONS="-o loop" mount $MNT_OPTIONS "$MASTER" "$MASTER_MNT" 2>&1 | indentation echo "Removing old bootfs files ..." rm -rf "$BOOT_DIR" && mkdir "$BOOT_DIR" 2>&1 | indentation echo "Copying bootfs files ..." local item_dir # ignore the big KNOPPIX image find "$MASTER_MNT" -type f | sed 's#^$MASTER_MNT/##' | grep -v "^$KNOPPIX_IMAGE_FILE$" | while read item do item_dir=$(dirname "$item") [ -e "$BOOT_DIR/$item_dir" ] || mkdir -p "$BOOT_DIR/$item_dir" cp -a "$MASTER_MNT/$item" "$BOOT_DIR/$item_dir/" done 2>&1 | indentation echo "Mounting the compressed image file ..." mount "$MASTER_MNT/$KNOPPIX_IMAGE_FILE" "$ROOT_MNT" 2>&1 | intendation echo "Copying the compressed root system ..." cp -a "$ROOT_MNT/." "$ROOT_DIR" umount "$ROOT_MNT" umount "MASTER_MNT" } function master_backup() { umount_procfs local root_parent=$(dirname "$ROOT_DIR") local root_entry=$(basename "$ROOT_DIR") local boot_parent=$(dirname "$BOOT_DIR") local boot_entry=$(basename "$BOOT_DIR") [ -e "$BACKUP_DIR" ] || mkdir -p "$BACKUP_DIR" echo "Creating archive of the boot filesystem ..." tar czf "$BACKUP_DIR/bootfs.tar.gz" -C "$boot_parent" "$boot_entry" echo "Creating archive of the root filesystem (this may take _very_ long) ..." tar czf "$BACKUP_DIR/rootfs.tar.gz" -C "$root_parent" "$root_entry" } function master_restore() { umount_procfs local boot_backup_file=$BACKUP_DIR/bootfs.tar.gz local boot_parent=$(dirname "$BOOT_DIR") local root_backup_file=$BACKUP_DIR/rootfs.tar.gz local root_parent=$(dirname "$ROOT_DIR") # restoring the boot directory (the small one) if [ -e "$boot_backup_file" ] then if [ -e "$BOOT_DIR" ] then echo "Removing old files from boot filesystem ..." rm -rf "$BOOT_DIR" fi echo "Unpacking the boot filesystem archive ..." tar xzf "$boot_backup_file" -C "$boot_parent" else echo "Warning: no archive for boot filesystem found ($boot_backup_file) - skipping ..." fi # restoring the root directory (the big one) if [ -e "$root_backup_file" ] then if [ -e "$ROOT_DIR" ] then echo "Removing old files from root filesystem ..." rm -rf "$ROOT_DIR" fi echo "Unpacking the root filesystem archive ..." tar xzf "$root_backup_file" -C "$root_parent" else echo "Warning: no archive for root filesystem found ($root_backup_file) - skipping ..." fi } function remove_packages() { local pkg_list=$(find "$PKG_REMOVE_LIST_DIR" -type f | while read a do grep -v "^#" "$a" | tr "\n" " " done) [ -z "$pkg_list" ] && return echo "dpkg --force-all -P $pkg_list 2>&1 | grep -v 'which isn.t installed.'" | chroot_image } function umount_procfs() { # check for a mounted procfs mount | grep -q " $ROOT_DIR/proc " && umount "$ROOT_DIR/proc" true } # execute the content of stdin within the chroot environment # runs an interactive shell, if stdin is empty function chroot_image() { umount_procfs mount -t proc proc "$ROOT_DIR/proc" # ignore errors set +e local action=$@ [ -z "$action" ] && action=/bin/bash LANG=C TERM=linux chroot "$ROOT_DIR" $action set -e umount "$ROOT_DIR/proc" return } function create_iso_root() { umount_procfs echo "Creating the iso ..." mkisofs $MKISOFS_OPTIONS -o "$IMAGE_FILE" "$ROOT_DIR" #kisofs -b lib/grub/i386-pc/stage2_eltorito -no-emul-boot -boot-load-size 1 -boot-info-table -R -U -V "silicann_compressed_livecd" --publisher "Silicann GmbH" -hide-rr-moved -cache-inodes -no-bak -pad -o "$IMAGE_FILE" "$ROOT_DIR" } function configure() { if [ ! -e "$ROOT_DIR" ]; then echo -e "Directory \"$ROOT_DIR\" not found!" echo -e "Did you run \"$0 init\"?" exit 1 fi echo "Copying files ..." # svn export --force "$TEMPLATE_DIR/." "$ROOT_DIR" # only ignore the owner attribut cp -r --preserve=mode,timestamps,links "$TEMPLATE_DIR/." "$ROOT_DIR" 2>&1 | indentation echo "Configuring ..." # filter hidden files - they are usually vi-swap-files :) find -L "$SCRIPTS_DIR" -type f | grep -v "/\." | sort | while read scriptname do echo "Executing $scriptname ..." cat "$scriptname" | chroot_image done } function blanknburn_cdrw() { cdrecord -v dev=$CDWRITER blank=fast cdrecord -v dev=$CDWRITER "$IMAGEZ_FILE" } function initialization() { # initialize local directories (easier for users) for a in "$LOCALCONF_DIR" "$BUILD_DIR" "$SCRIPTS_DIR" "$PKG_INSTALL_LIST_DIR" "$PKG_REMOVE_LIST_DIR" "$TMP_DIR" "$BACKUP_DIR" "$TEMPLATE_DIR" "$IMAGE_DIR" do if [ ! -e "$a" ] then echo "Creating directory '$a' ... " mkdir -p "$a" fi done } ################ do it! ###################### if [ $# -eq 0 ] then echo "[`basename $0`] - no arguments supplied - maybe you want to use '--help'" >&2 exit 1 fi # check for uid=0 (necessary for all operations except for qemu) [ "$(id -u)" -ne 0 -a "$*" != "qemuz" ] && echo "this script ($0) has to be called as root" >&2 && exit 1 initialization while [ $# -gt 0 ] do case "$1" in init ) master_get ;; backup ) master_backup ;; restore ) master_restore ;; packages ) remove_packages #install_packages ;; config ) configure ;; compress ) [ -e "$IMAGE_FILE" ] || "$0" iso-root cat "$IMAGE_FILE" | chroot_image /usr/bin/create_compressed_fs --best - 65536 >"$BOOT_DIR/KNOPPIX/KNOPPIX" ;; iso-boot ) [ -e "$BOOT_DIR/KNOPPIX/KNOPPIX" ] || "$0" compress mkisofs -pad -l -r -J -v -V "silicann_livecd" --publisher "Silicann GmbH" -b boot/isolinux/isolinux.bin -no-emul-boot -boot-load-size 4 -boot-info-table -c KNOPPIX/boot.cat -hide-rr-moved -o "$IMAGEZ_FILE" "$BOOT_DIR" ;; chroot ) chroot_image ;; iso-root ) create_iso_root ;; qemu ) qemu -cdrom "$IMAGE_FILE" -nics 0 ;; qemuz ) qemu -cdrom "$IMAGEZ_FILE" -nics 0 ;; burn ) blanknburn_cdrw ;; release ) "$0" init packages config iso-root compress iso-boot md5sum "$IMAGEZ_FILE" > "${IMAGE_FILE}.md5sum" sha1sum "$IMAGEZ_FILE" > "${IMAGE_FILE}.sha1sum" ;; help|--help ) echo "Syntax: `basename $0` ( release | init | backup | packages | config | iso-root | iso-boot | compress | burn | help )" echo " (you may specify more than one action)" echo ;; * ) echo -e "unknown action: $1" echo "$0" help exit 1 ;; esac shift done