#!/bin/bash ############################################################################## # This scrripts creates miniroot images currently for ARM and x86_64 machines # and possible for any slackware port with minor editing. # # It is a rework from scratch of Suart's miniroot creation script for # slackwareARM # ftp.arm.slackware.com/slackwarearm/slackwarearm-devtools/minirootfs # # Although, in order to produce a bootable image, it is still necessary to run # the script from the same type of machine as the miniroot target it is # possible to do part of the work cross platform. # # Another fundamental difference is that this script will download the packages wheras # Stuart's script needs a local repo. # # Author: louigi600 # # Redistribution and use of this script, with or without modification, is # permitted provided that the following conditions are met: # # 1. Redistributions of this script must retain the above copyright # notice, this list of conditions and the following disclaimer. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### #configuration for this script is in the conf subflder Name=$(basename $0) Basedir=$(dirname $0) [ "$Basedir" = "." ] && Basedir=$PWD Cfgdir=${Basedir}/conf #sourcing configuration file source ${Cfgdir}/${Name}.conf LARCH="$(uname -m)" if $Debug then cat << EOF! Script Name : $Name Base Directory : $Basedir Config Directory : $Cfgdir Supported Releases : ${SupportedReleases[*]} EOF! sleep 1 fi #functn for chsng the miniroot you wat to build from the supported list Choose_Release () { #echo "${!SupportedReleases[*]}" DialogString="$(awk '{ for (a=1;a<=NF;a++) {printf("%s %i ",$a,a);} }' <<< ${!SupportedReleases[*]})" #echo "$DialogString" exec 3>&1; Release=$(dialog --title 'Release' --menu 'Choose Release:' 0 0 0 $DialogString 2>&1 1>&3) Res=$? exec 3>&-; [ $Res -ne 0 ] && exit 0 } Get_Packages () { mkdir -p $1 cd $1 for pkgspec in $Pkglist do pkg=$(basename ${pkgspec}) FileName="$(links -dump $(dirname "${URL}/$pkgspec") | sed 's/^.*] *//' |awk -v pattern="^${pkg}-[0-9].*t.z\$" '$1 ~ pattern {print $1}')" [ "$FileName" = "" ] && continue PatchesFileName="$(links -dump $(dirname $URL)/patches/packages | awk -v pattern="^${pkg}-[0-9].*z\$" '$2 ~ pattern {print $2}')" if [ "$PatchesFileName" != "" ] then $Debug && echo "$pkgspec : $(dirname $URL)/patches/packages/$PatchesFileName" FileName="$PatchesFileName" FetchURL="$(dirname $URL)/patches/packages/$PatchesFileName" else $Debug && echo "$pkgspec : ${URL}/$(dirname $pkgspec)/$FileName" FetchURL="${URL}/$(dirname $pkgspec)/$FileName" fi LocalFlename="$(ls ${pkg}-[0-9]*.t*z 2>/dev/null)" if [ "$LocalFlename" != "" -a "$LocalFlename" != "$FileName" ] then $Debug && echo "There is a newer verson $LocalFlename -> $FileName" rm -f $LocalFlename fi echo "$FileName" wget -qN --show-progres $FetchURL done } Recreate_Miniroot () { [ "$1" = "" ] && usage Recreate_Miniroot was caled wth no miniroot path #create a fresh miniroot echo "Recreating a fresh minroot in $1 ..." $Debug && sleep 1 mkdir -p $1 cd $1 rm -rf ./* #installing into miniroot with option --root $1 echo "install the packages into $1" $Debug && sleep 1 for pkgspec in $Pkglist do pkg=$(basename ${pkgspec}) FileName="$(ls ${Pkgdir}/${Release}/${pkg}-[0-9]* 2>/dev/null)" [ "$FileName" = "" ] && continue installpkg --threads $( nproc ) --terse --root $1 $FileName done #patching update-ca-certificates not to use perl echo "patching update-ca-certificates so that it will not use perl" $Debug && sleep 1 ( cd ${1}/usr/sbin patch -p0 < ${Basedir}/conf/update-ca-certificates_no-perl.patch ) #setting up root password echo "setting root password on miniroot" $Debug && sleep 1 chpasswd -R $1 <<< "root:$(get_myoptions_value p)" 2>/dev/null } Chroot_Setup () { #configure dynamic linker run-time bindings #this does not work cross platform but is necessary to be able to boot the image echo "configuring dynamic linker run-time bindings and cache" ldconfig -r $1 2>/dev/null echo "updateing /etc/ssl/certs and ca-certificates.crt" $Debug && sleep 1 chroot $1 usr/sbin/update-ca-certificates --fresh } Setup_Fstab () { echo "generating a sample fstab" $Debug && sleep 1 #creating the fstab cat << EOF > ${1}/etc/fstab proc /proc proc defaults 0 0 devpts /dev/pts devpts gid=5,mode=620 0 0 tmpfs /dev/shm tmpfs nosuid,nodev,noexec 0 0 #example of boot and root for normal ide/sata/scsi/sas/usb storage #/dev/sda1 /boot ext4 errors=remount-ro,noatime 0 1 #/dev/sda3 / ext4 errors=remount-ro,noatime 0 1 #example of boot and root for mmc storage like the RPi #/dev/mmcblk0p1 /boot vfat errors=remount-ro,noatime 0 1 #/dev/mmcblk0p2 / ext4 errors=remount-ro,noatime 0 1 EOF } Setup_Basic_Networking () { echo "setting u loopback networking on miniroot" $Debug && sleep 1 #creating hosts and resolv.conf echo "miniroot" > ${1}/etc/HOSTNAME cat << EOF > ${1}/etc/hosts # For loopbacking. 127.0.0.1 localhost #::1 localhost #uncomment if you are going to use ipv6 # Same thing for the default hostname if nothing was set up by netconfig: 127.0.0.1 miniroot.example.net miniroot #::1 miniroot.example.net miniroot # End of hosts. EOF cat << EOF > ${1}/etc/resolv.conf search example.net nameserver 192.168.0.1 EOF #making sure sshd is enabled chmod +x ${1}/etc/rc.d/rc.ssh* } Setup_Timezone () { echo "setting up timezone" $Debug && sleep 1 #setting up timezone ( cd ${1}/etc cat << EOF > hardwareclock localtime EOF rm -f localtime* ln -vfs ../usr/share/zoneinfo/Europe/Rome localtime-copied-from cp -favv ../usr/share/zoneinfo/Europe/Rome localtime ) } Setup_Keymap () { echo "setting up keymap" $Debug && sleep 1 cat << EOF > ${1}/etc/rc.d/rc.keymap #!/bin/sh # Load the keyboard map. More maps are in /usr/share/kbd/keymaps. if [ -x /usr/bin/loadkeys ]; then /usr/bin/loadkeys us.map fi EOF chmod 755 ${1}/etc/rc.d/rc.keymap } ################## #main ################## $Debug && dump_options $Debug && echo -n "Composing optistring for getopt ... " GetoptString=$( for I in ${!MyOptions[@]} do echo -en "${I}${MyOptions[$I]%%,*}" done ) $Debug && echo $GetoptString getopt $GetoptString $* >/dev/null 2>/dev/null || \ usage unknown option or insufficient parameters: $* GPO=$(getopt $GetoptString $* 2>/dev/null |tr -d "'") set -- $GPO $Debug && echo "Getopt Parsed Options: $*" $Debug && echo -n "Beginning to parse options internally ... " while [ $# -ge 1 ] do $Debug && echo "parsing $1 ..." case $1 in -r|-p) if $Debug ; then echo "$1 $2"; fi; set_myoptions_value ${1#-} $2; shift 2;; -h|-D|-I|-R|-T) if $Debug ; then echo "$1"; fi; set_myoptions_value ${1#-} true; shift;; --) shift ;; *) usage $1 unknown option ;; esac done #show usahe is -h was issued $(get_myoptions_value h) && usage #run chooser function if no release was specified if [ "$(get_myoptions_value r)" = "" ] then Choose_Release else Release="$(get_myoptions_value r)" fi URL="${SupportedReleases[$Release]}" [ "$URL" = "" ] && usage unknown release $Release if $Debug then echo "$Release $URL" sleep 1 fi #disabling chroot post install if LARCH id different to target architecture case $Release in slackwarearm-14.2) TARCH="armv7l";; slackwarearm-current) TARCH="armv7l";; slackwareaarch64-current) TARCH="aarch64";; slackware64-14.2|slackware64-current) TARCH="x86_64" ;; *) echo "Unsupported release : $Release"; exit 1 ;; esac if [ "$LARCH" != "$TARCH" ] then set_myoptions_value R true echo "Disabling chroot post install setup bacause $LARCH != $TARCH" fi if $(get_myoptions_value D) && [ -d ${Minirootdir}/$Release ] then echo "You have chosen to skip package download/update and work with wht's already inside ${Minirootdir}/$Release" $Debug && sleep 1 else #Download or update the required packages (${Cfgdir}/pkglist.txt) echo "Downloading/updating packges for $Release ... " $Debug && sleep 1 Get_Packages ${Pkgdir}/$Release fi #will now create a fresh minirot for $Release if $(get_myoptions_value I) && [ -d ${Minirootdir}/$Release ] then echo "You have chosen to skip package and proceed with post install setup in ${Minirootdir}/$Release" $Debug && sleep 1 else Recreate_Miniroot ${Minirootdir}/$Release fi if ! $(get_myoptions_value R) then Chroot_Setup ${Minirootdir}/$Release fi #creating a sample fstab Setup_Fstab ${Minirootdir}/$Release Setup_Basic_Networking ${Minirootdir}/$Release Setup_Timezone ${Minirootdir}/$Release Setup_Keymap ${Minirootdir}/$Release ############################# #doing the other trivial post install stuff echo "doing the other trivial post install stuff" $Debug && sleep 1 cd ${Minirootdir}/$Release #setting up default window manager if [ -d etc/X11/xinit/ ]; then ( cd etc/X11/xinit/ ln -vfs xinitrc.fluxbox xinitrc ) fi sed -i 's?^#ttyS0?ttyS0?' etc/securetty cat << EOF > etc/e2fsck.conf # These options stop e2fsck from erroring/requiring manual intervention # when it encounters bad time stamps on filesystems -- which happens on # the Versatile platform because QEMU does not have RTC (real time clock) # support. # [options] accept_time_fudge = 1 broken_system_clock = 1 EOF #if we have a local copy of netconnect copy that into the miniroot #this will attempt to get dhcp addres on wired first then from any known AP in range via wifi if [ -r ${Cfgdir}/netconnect ] then cp ${Cfgdir}/netconnect usr/local/bin/ echo "/usr/local/bin/netconnect start" >> etc/rc.d/rc.local fi #copying wpa_supplicant.conf into th miniroot cp /etc/wpa_supplicant.conf etc/wpa_supplicant.conf #by default sshd will not allow password auth #copying over roots authorized_keys so that you have root access via ssh mkdir root/.ssh chmod 700 root/.ssh [ -r /root/.ssh/authorized_keys ] && cp -p /root/.ssh/authorized_keys root/.ssh/authorized_keys #put a copy of MANIFEST.bz2 in root's home wget -qN --show-progres ${URL}/MANIFEST.bz2 -O root/MANIFEST.bz2 if ! $(get_myoptions_value T) then #creating the tarball echo "creating the miniroot tarball" $Debug && sleep 1 Date="$(date +%Y%m%d)" tar cpJf ../${Release}_${Date}.txz * #Creating the release txt echo "creating the miniroot txt" $Debug && sleep 1 ( cd ${Minirootdir} cat << EOF > ${Release}_${Date}.txt Build date : ${Date} root password : $(get_myoptions_value p) Uncompressed size : $(du -ms ${Release}) Compressed size : $(du -ms ${Release}_${Date}.txz) md5sum : $(md5sum ${Release}_${Date}.txz) EOF ) fi if ! $(get_myoptions_value R) then #looking if any bins broke (not belonging to the known broken list) echo "checking if any more bins broke in this build" $Debug && sleep 1 cp ${Cfgdir}/chroot_checks tmp chroot . /tmp/chroot_checks fi