#!/bin/sh # vim: set sw=4 ts=4 sts=4 et : SUBVOLUMES=' /var /var/log /var/tmp /etc ' cleanup() { if [ -n "${tmpdir}" ] && [ "${tmpdir}" != / ]; then if mountpoint -q "${tmpdir}"; then umount "${tmpdir}" fi rm -rf "${tmpdir}" unset tmpdir fi } copy_vol() { dev="$1" vol=$2 printf 'Copying %s contents to data volume\n' "${vol}" >&2 mount -o subvol="${vol#/}" "${dev}" "${tmpdir}" || exit cp -au${VERBOSE+v} /sysroot/${vol#/}/. "${tmpdir}" || exit umount "${tmpdir}" } find_part() { _i=0 while [ $_i -lt 5 ]; do findfs "$1" 2>/dev/null && return _i=$((_i + 1)) sleep 1 done findfs "$1" } format_dev() { dev="$1" partno=$(partition_number "${dev}") if [ -n "${partno}" ]; then disk="$(get_disk "${dev}")" if [ -n "${disk}" ]; then printf 'Resizing partition %d on disk %s\n' \ "${partno}" \ "${disk}" \ >&2 resize_partition "${disk}" "${partno}" else printf 'Could not find disk for device %s\n' \ "${dev}" \ >&2 fi fi printf 'Creating BTRFS filesystem on %s\n' "${dev}" >&2 mkfs.btrfs --quiet "${dev}" || exit mount "${dev}" "${tmpdir}" || exit for vol in ${SUBVOLUMES}; do mkdir -p "${tmpdir}${vol%/*}" || exit btrfs subvolume create "${tmpdir}${vol}" || exit done relabel_all umount "${dev}" || exit } get_disk() { _syspath=/sys/class/block/${1##*/} [ -d "${_syspath}" ] || return 1 if [ ! -f "${_syspath}"/partition ]; then readlink -f "${1}" return $? fi _disk=$(readlink -f "${_syspath}"/..) if [ -n "${_disk}" ]; then printf '/dev/%s\n' "${_disk##*/}" return 0 fi return 1 } has_fs() { dev="$1" fstype=$(blkid -o value -s TYPE "${dev}") [ -n "${fstype}" ] } last_partition() { cat /sys/class/block/"${1##*/}"/*/partition \ | sort -n \ | tail -n1 } partition_number() { cat /sys/class/block/${1##*/}/partition } relabel_all() { if [ ! -d /sys/fs/selinux ] || [ ! -f /etc/selinux/config ]; then return fi selinuxtype=$(. /etc/selinux/config && echo ${SELINUXTYPE}) find "${tmpdir}" | \ setfiles \ -v \ -F \ -m \ -r "${tmpdir}" \ -s \ /etc/selinux/${selinuxtype}/contexts/files/file_contexts } resize_partition() { _disk="${1}" _part="${2}" _lastpart=$(last_partition "${_disk}") if [ "${_part}" -ne "${_lastpart}" ]; then printf 'Cannot resize %s, it is not the last partition on the disk\n' \ "${_dev}" \ >&2 return 1 fi _uuid=$(sfdisk --part-uuid "${_disk}" "${_part}") || return $? _type=$(sfdisk --part-type "${_disk}" "${_part}") || return $? _label=$(sfdisk --part-label "${_disk}" "${_part}") || return $? sfdisk --delete "${_disk}" "${_part}" || return $? printf 'type=%s, uuid=%s, name="%s"\n' \ "${_type}" \ "${_uuid}" \ "${_label}" \ | sfdisk -N "${_part}" "${_disk}" --quiet --force \ || return $? partx -u "${_disk}" } setup_etc() { dev="$1" echo 'Initializing /etc overlay' >&2 mkdir -p /run/aimeeos/etc || return mount -o subvol=etc "${dev}" /run/aimeeos/etc || return mkdir -p /run/aimeeos/etc/rw /run/aimeeos/etc/work || return mount -t overlay \ -o lowerdir=/sysroot/etc,upperdir=/run/aimeeos/etc/rw,workdir=/run/aimeeos/etc/work \ overlay \ /sysroot/etc } rootdev=$(find_part "$1") datapart=$(find_part "${2:-PARTLABEL=aimeeos-data}") if [ -b "${datapart}" ]; then printf 'Found data partition: %s\n' "${datapart}" >&2 else echo 'Could not identify data partition' >&2 exit 1 fi trap cleanup INT TERM QUIT EXIT tmpdir=/run/storinit mkdir -p "${tmpdir}" if ! has_fs "${datapart}"; then format_dev "${datapart}" fi mkdir -p /sysroot mount -o ro "${rootdev}" /sysroot || exit setup_etc "${datapart}" copy_vol "${datapart}" /var exit 0