--- /dev/null
+#!/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