#!/bin/sh
# -*- indent-tabs-mode: nil; -*-
# @(#)$HGid$

set -eu

VERSION="@@VERSION@@"

# Reset to standard umask
umask 0022


#
# "datasets" -- create the ZFS dataset tree
#
# command_datasets [ -u ] parent-dataset child-dataset
#
#    -u  do not automatically mount newly created datasets
#
command_datasets() {
    # parent ZFS dataset -- child ZFS dataset name
    local _pds _cds
    # and its mount point
    local _pmp _get _dummy
    # full name of the dataset
    local _ds
    # dynamic ZFS options
    local _zfsopts

    _zfsopts=""
    while getopts "u" _opt ; do
        case ${_opt} in
            u)
                # do not mount newly created datasets
                _zfsopts="${_zfsopts} -u"
                ;;
            \?|:)
                return 2;
                ;;
        esac
    done
    shift $((OPTIND-1))
    OPTIND=1

    _pds="$1"
    if [ -z "${_pds}" ]; then
        echo "ERROR: no parent dataset given" >&2
        return 2
    fi
    _get=$(zfs get -H mountpoint "${_pds}" 2>/dev/null) || { echo "ERROR: dataset \`${_pds}' does not exist" >&2; return 1; }
    IFS=$'\t' read _dummy _dummy _pmp _dummy <<EOF
${_get}
EOF
    case "${_pmp}" in
        none)
            echo "ERROR: dataset \`${_pds}' has no mountpoint" >&2
            return 1
            ;;
        legacy)
            echo "ERROR: dataset \`${_pds}' has a \`${_mp}' mountpoint" >&2
            return 1
            ;;
        *)
            # VOID
            ;;
    esac
    _cds="$2"
    if [ -z "${_cds}" ]; then
        echo "ERROR: no child dataset given" >&2
        return 2
    fi
    _ds="${_pds}/${_cds}"
    echo "Resulting new root dataset is \`${_ds}' at mountpoint \`${_pmp}/${_cds}'"
    if zfs get -H mountpoint "${_ds}" >/dev/null 2>/dev/null; then
        echo "ERROR: dataset \`${_ds}' does already exist" >&2
        return 1
    fi
    zfs create ${_zfsopts} -o atime=off                                                                      "${_ds}"
    zfs create ${_zfsopts} -o sync=disabled -o setuid=off                                                    "${_ds}/tmp"
    zfs create ${_zfsopts}                                                                                   "${_ds}/usr"
    zfs create ${_zfsopts}                                                                                   "${_ds}/var"
    zfs create ${_zfsopts} -o exec=off -o setuid=off                                                         "${_ds}/var/audit"
    zfs create ${_zfsopts} -o exec=off -o setuid=off                                                         "${_ds}/var/cache"
    zfs create ${_zfsopts} -o exec=off -o setuid=off -o compression=off                                      "${_ds}/var/cache/pkg"
    zfs create ${_zfsopts} -o exec=off -o setuid=off -o compression=off                                      "${_ds}/var/crash"
    zfs create ${_zfsopts} -o exec=off -o setuid=off                                                         "${_ds}/var/db"
    zfs create ${_zfsopts} -o exec=on -o setuid=off                                                          "${_ds}/var/db/pkg"
    zfs create ${_zfsopts} -o readonly=on -o exec=off -o setuid=off                                          "${_ds}/var/empty"
    zfs create ${_zfsopts} -o exec=off -o setuid=off -o primarycache=metadata                                "${_ds}/var/log"
    zfs create ${_zfsopts} -o exec=off -o setuid=off -o atime=on                                             "${_ds}/var/mail"
    zfs create ${_zfsopts} -o sync=disabled -o exec=off -o setuid=off -o compression=off -o primarycache=all "${_ds}/var/run"
    zfs create ${_zfsopts} -o sync=disabled -o setuid=off                                                    "${_ds}/var/tmp"
}


#
# "privs" -- adjust privileges
#
# To be used when all ZFS datasets are mounted.
#
command_privs() {
    # mountpoint
    local _mp _d

    _mp="$1"
    if [ -z "${_mp}" ]; then
        echo "ERROR: no mountpoint given" >&2
        return 2
    fi
    if [ ! -d "${_mp}" ]; then
        echo "ERROR: directory \`${_mp}' does not exist" >&2
        return 1
    fi
    for _d in tmp var/tmp ; do
       chmod 01777 "${_mp}/${_d}"
    done
    chown root:mail "${_mp}/var/mail"
    chmod 0775 "${_mp}/var/mail"
}


#
# Global option handling
#
while getopts "h" _opt ; do
    case ${_opt} in
        h)
            echo "Usage: XXX TBD"
            exit 0
            ;;
        \?|:)
            exit 2;
            ;;
    esac
done

#
# Reset the Shell's option handling system to prepare for handling
# command-local options.
#
shift $((OPTIND-1))
OPTIND=1

command="$1"
shift

case "${command}" in
    datasets)
        command_datasets "$@"
        ;;
    privs)
        command_privs "$@"
        ;;
    *)
        echo "ERROR" >&2
        exit 2
        ;;
esac
