initial version of scripts, config and debian package
[moebian] / install / installroot
diff --git a/install/installroot b/install/installroot
new file mode 100755 (executable)
index 0000000..cd0a9be
--- /dev/null
@@ -0,0 +1,276 @@
+#!/bin/sh
+# (c) copyright 2010 by Thomas Tanner <tanner@gmx.de>
+
+# create a bootable Maemo 5 root on /home or some mounted MMC partition
+# either symlink or copy all files on NAND
+# copy files relocated to /home
+# ignore or copy files from /opt
+# symlink or mount old home, or setup new home
+# for installation in /home move /home/opt to /home/opt.orig and update /opt symlink
+
+# $dest/nand - mount point for UBIFS or mount binds
+# for chroot mounts in $dest are: dev home media proc srv sys syspart tmp var/run
+mountpoints="cdrom dev floppy home initrd media mnt nand proc sys syspart tmp"
+
+mode=link # link or copy content
+withopt=no # copy or ignore files in /opt
+homedir=keep # link/mount old home (keep) or create new home (new)
+bootable=yes # bootable installation
+
+debug=:
+#debug=echo
+#set -x
+
+test "$#" -eq 0 && echo "$0 destination [source]" && exit 1
+dest="$1" # rootfs destination (absolute path or device)
+#dest=`pwd`
+src=  # default source (absolute path)
+test -n "$2" && src="$2" # or alternative rootfs copy
+case "$src" in */);; *) src="$src/" ;; esac # make sure src has trailing slash 
+here=`dirname $0`
+here=`realpath $here`
+
+rawdest=no
+case $dest in 
+/dev/mmcblk[01]p?)
+    rawdest=yes
+    echo destination is partition
+    test -d /media/moebian && (echo cannot create mountdir; exit 1)
+    echo -n formatting $dest as ext3. are you sure [y/N]:
+    read go && test $go != y && echo aborting && exit 1
+    mkfs.ext3 $dest
+    mkdir -p /media/moebian
+    mount $dest /media/moebian
+    dest=/media/moebian
+    ;;
+esac
+
+if test $bootable = yes; then
+    device=`cat /proc/mounts | grep " $dest " | awk '{print $1}'`
+    case $device in 
+        /dev/mmcblk0*) card='${INT_CARD}'; cardname='eMMC' ;;
+        /dev/mmcblk1*) card='${EXT_CARD}'; cardname='SD' ;;
+        *)
+            echo invalid destination
+            exit 1
+            ;;
+    esac
+    partition=`echo $device | sed s%/dev/mmcblk.%%`
+    card=$card$partition
+    echo installing bootable rootfs in $dest on $device = $card
+else
+    echo installing chroot in $dest
+fi
+echo mode: $mode, copy /opt: $withopt, $homedir /home
+
+cd "$dest"
+# create toplevel dirs and nand mount point
+mountpoints="cdrom floppy home initrd media mnt nand proc srv sys syspart tmp"
+content="usr"
+copydirs="bin boot etc dev lib sbin root var"
+checklinkdirs="bin boot etc lib sbin root usr var"
+
+mkdir -p $mountpoints
+mkdir -p mnt/initfs # bootmenu nand mount point (required for boot!)
+
+if test $dest = /home && test -L /opt; then
+    if test -d opt.nand; then
+        echo "opt for NAND does already exist. not updating"
+    else
+        mv opt opt.nand
+        ln -sf $dest/opt.nand /opt
+        echo "/home/opt moved to /home/opt.nand and symlink updated"
+    fi
+fi
+
+if test $mode = link; then
+    mkdir -p $content
+    copydirs="$copydirs usr/local usr/share/man"
+    # excluded shared dirs
+    cd "$src"
+    dontlink="usr/bin usr/games usr/include usr/lib usr/libexec usr/sbin \
+    usr/share usr/share/applications/*/ usr/X11R6"
+    echo $dontlink
+    cd "$dest"
+    for d in $dontlink; do
+        test -L "$d" && test ! -L "$src$d" && rm $d # remove existing links
+        mkdir -p $d
+    done
+elif test $mode = copy; then
+    copydirs="$copydirs $content"
+else
+    echo "error: unknown mode $mode" && exit 1
+fi
+
+for d in $copydirs; do
+    if test -d $d; then
+        echo "skipping existing directory ${src}$d"
+        continue
+    fi
+    echo copying ${src}$d
+    mkdir -p $d
+    cp -a ${src}$d $d/..
+done
+modules=/lib/modules/2.6.28maemo-omap1
+if test $bootable = yes && test -d $modules -a ! -d $dest$modules; then
+    echo copying maemo kernel modules
+    cp -a /lib/modules/2.6.28maemo-omap1 $dest/lib/modules
+fi
+if test $withopt = yes; then
+    echo copying /opt
+    cp -a ${src}home/opt/* $dest/opt
+else
+    mkdir -p $dest/opt # create empty opt
+fi
+
+symlink () { # args: subdir path relpath
+    # recursive symlinking: create or update
+    $debug sub $1 $2 $topdir$2 $3
+    echo symlinking "$2"
+    cd "$1"
+    IFS="%" && for f in `/bin/ls -d * .[^.]* 2>/dev/null | tr '\n' '%'`; do
+    #IFS=$'\n' && for f in `/bin/ls -d * .[^.]* 2>/dev/null`; do
+        if test -L "$f"; then # update symlinks
+            # target exists and is not symlink: ignore
+            if test ! -e "$dest$2/$f" -o -L "$dest$2/$f"; then
+                target=`readlink $f`
+                case "$target" in
+                /home/*) # copy relocated files
+                       mkdir -p "$dest$2/$f"
+                    echo copying $target
+                       cp -a $target "$dest$2/$f/.."
+                    continue
+                       ;;
+                /*) 
+                    $debug al "$2/$f" $target
+                    # if it links to rootfs make it a rel. symlink
+                    test -e "$3$target" && target="$3$target"
+                    ;;
+                *)
+                    $debug rl "$2/$f" $target
+                    # just keep the rel. symlink
+                    ;;
+                esac
+                rm -f "$dest$2/$f"
+                ln -s "$target" "$dest$2/$f"
+            else
+                echo "warning: $dest$2/$f exists but is not a symlink. ignoring"
+            fi
+        elif test -d "$f"; then # a subdirectory
+            $debug sd "$2/$f"
+            if test -L "$dest$2/$f" -o ! -e "$dest$2/$f"; then
+                # target is a symlink or doesn't exist -> update symlink
+               if test -L "$2/$f"; then
+                       # symlink on NAND, was relocated
+                       mkdir -p "$dest$2/$f"
+                    echo copying "$2/$f"
+                       cp -a $2/$f/* "$dest$2/$f"
+                else
+                       rm -f "$dest$2/$f"
+                   ln -s "$3$2/$f" "$dest$2/$f"
+               fi
+            else
+                if test -d "$dest$2/$f"; then
+                    # symlink contents if is an existing directory in root
+                    symlink "$f" "$2/$f" "../$3"
+                else
+                    echo "warning: $dest$2/$f exists but is not a file. ignoring"
+                fi
+            fi
+        else
+            $debug fi "$2/$f"
+            # update symlink is it not a existing file
+            test -f "$dest$2/$f" || ln -sf "$3$2/$f" "$dest$2/$f"
+        fi
+    done
+    cd ..
+}
+
+if test $mode = link; then
+       # TODO: find files that were moved from NAND to /home and copy or symlink them
+    for d in $content; do
+        (symlink "$src$d" "/$d" ../nand)
+    done
+elif test $mode = copy; then
+    # process /home and /opt symlinks
+    echo -n checking for external symlinks...
+    tmp=`mktemp`
+    find $checklinkdirs -type l > $tmp
+    echo processing `wc -l $tmp | awk '{print $1}'` links
+    while read l; do
+        f=`readlink $l`
+        case "$f" in
+        /opt/*)
+            test $withopt = yes || rm $l # delete /opt links
+            ;;
+        /home/*) # copy files relocated from NAND to /home
+            rm $l
+            test -d $f && echo copying $f
+            cp -a $f $l # copy original file/dir
+            ;;
+        *) ;;
+        esac
+    done < $tmp
+    rm $tmp
+fi
+
+if test $homedir = keep; then
+    if test $dest = /home && test ! -d $dest/home/user; then
+        echo symlinking existing home
+        ln -s /user $dest/home/user
+    fi
+elif test $homedir = new; then
+    echo creating new home
+    rm -rf $dest/home/user
+    mkdir -p $dest/home/user
+    (cd $src/etc/skel && cp -a . $dest/home/user)
+    chown -R user:users $dest/home/user
+else
+    echo "error: unknown homedir mode $mode" && exit 1
+fi
+if test $bootable = yes; then
+    stat=$(dpkg-query -W -f='${Status}' bootmenu 2>&1) || stat=none
+    if test "$stat" != "install ok installed"; then
+        echo installing bootmenu
+        deb=/var/tmp/bootmenu.deb
+        wget -O$deb "http://www.daimi.au.dk/~cvm/bootmenu_1.6_armel.deb" || \
+            (echo 'download failed'; exit 1)
+        dpkg -i $deb || (echo 'installation failed'; exit 1)
+        rm $deb
+        echo bootmenu successfully installed
+    else
+        echo bootmenu is already installed
+    fi
+    bootitem=/etc/bootmenu.d/moebian.item
+    cat > $bootitem <<EOF
+ITEM_NAME="Moebian ($cardname $partition)"
+ITEM_ID="moebian"
+ITEM_DEVICE="$card"
+ITEM_MODULES="mbcache jbd ext3"
+ITEM_FSTYPE="ext3"
+ITEM_FSOPTIONS="noatime,ro"
+EOF
+    echo bootmenu item created
+fi
+
+echo copying configuration
+cp -a $here/etc $dest
+mkdir -p $dest/var/lib/apt/lists/partial
+
+$here/mountroot $dest
+inroot="chroot $dest"
+$inroot apt-get update
+if test $bootable = yes; then
+    $inroot apt-get install -y --force-yes openssh-server
+fi
+$here/umountroot $dest
+
+echo installation finished successfully
+df -h $dest
+
+if test $rawdest = yes; then
+    echo removing temporary mount point
+    umount $dest && rm -rf $dest
+fi
+
+exit 0