#!/bin/ksh93
# Build script for hammerhead-userland
# Packages commands, libraries, headers, and system configuration from proto area
#
# Requires PROTO_AREA to be set to the hammerhead proto path, e.g.:
#   export PROTO_AREA=/usr/src/hammerhead-build/root_amd64
#
# Optional: ROOTFS_DIR for rootfs overlay (config files, ownership manifest)
#   export ROOTFS_DIR=/usr/src/hammerhead/rootfs

set -e

PROTO_AREA="${PROTO_AREA:?PROTO_AREA must be set to hammerhead proto path}"

# Validate required directories
for dir in bin sbin lib usr etc var; do
    if [ ! -d "$PROTO_AREA/$dir" ]; then
        printf "ERROR: %s/%s does not exist\n" "$PROTO_AREA" "$dir"
        printf "Has the hammerhead build completed successfully?\n"
        exit 1
    fi
done

# Validate critical files
for f in lib/libc.so.1 lib/ld.so.1 sbin/init; do
    if [ ! -f "$PROTO_AREA/$f" ]; then
        printf "ERROR: %s not found in proto area\n" "$f"
        exit 1
    fi
done

# --- /bin (real directory with boot-essential commands) ---
printf "Packaging bin...\n"
mkdir -p "$PKGDIR/bin"
(cd "$PROTO_AREA/bin" && find . | cpio -pdm "$PKGDIR/bin" 2>/dev/null)

# --- /sbin (essential system commands) ---
printf "Packaging sbin...\n"
mkdir -p "$PKGDIR/sbin"
(cd "$PROTO_AREA/sbin" && find . | cpio -pdm "$PKGDIR/sbin" 2>/dev/null)

# --- /lib (essential libraries + SMF infrastructure) ---
printf "Packaging lib...\n"
mkdir -p "$PKGDIR/lib"
(cd "$PROTO_AREA/lib" && find . | cpio -pdm "$PKGDIR/lib" 2>/dev/null)

# --- /usr (commands, libraries, headers, man pages, data) ---
printf "Packaging usr...\n"
mkdir -p "$PKGDIR/usr"
(cd "$PROTO_AREA/usr" && find . | cpio -pdm "$PKGDIR/usr" 2>/dev/null)

# --- /etc (system configuration) ---
# Exclude system-specific runtime files that are populated at install time
# or by the kernel. These must NOT be overwritten on upgrade.
printf "Packaging etc...\n"
mkdir -p "$PKGDIR/etc"
(cd "$PROTO_AREA/etc" && find . \
    ! -name name_to_major \
    ! -name path_to_inst \
    ! -name driver_aliases \
    ! -name driver_classes \
    ! -name minor_perm \
    ! -name device.tab \
    ! -name devlink.tab \
    ! -name dacf.conf \
    ! -name iu.ap \
    ! -name mnttab \
    ! -name utmpx \
    ! -name wtmpx \
    | cpio -pdm "$PKGDIR/etc" 2>/dev/null)

# --- /var (state directories — mostly empty structure) ---
printf "Packaging var...\n"
mkdir -p "$PKGDIR/var"
(cd "$PROTO_AREA/var" && find . | cpio -pdm "$PKGDIR/var" 2>/dev/null)

# --- Apply rootfs overlay ---
# These are Hammerhead-specific config files that override proto defaults
if [ -n "$ROOTFS_DIR" ] && [ -d "$ROOTFS_DIR" ]; then
    printf "Applying rootfs overlay...\n"
    for overlay_dir in etc lib root; do
        if [ -d "$ROOTFS_DIR/$overlay_dir" ]; then
            (cd "$ROOTFS_DIR/$overlay_dir" && find . | cpio -pdm "$PKGDIR/$overlay_dir" 2>/dev/null)
        fi
    done
    # Copy .zshrc for root
    if [ -f "$ROOTFS_DIR/root/.zshrc" ]; then
        mkdir -p "$PKGDIR/root"
        cp "$ROOTFS_DIR/root/.zshrc" "$PKGDIR/root/.zshrc"
    fi
fi

# --- Remove items that should NOT be packaged ---
# Build tools
rm -rf "$PKGDIR/opt/onbld" 2>/dev/null || true
# Test suites (large, not needed on target)
rm -rf "$PKGDIR/opt/"*-tests 2>/dev/null || true
rm -rf "$PKGDIR/opt/test-runner" 2>/dev/null || true
# Build system remnants
rm -rf "$PKGDIR/usr/src" 2>/dev/null || true

# --- Apply ownership from manifest ---
if [ -n "$ROOTFS_DIR" ] && [ -f "$ROOTFS_DIR/ownership.manifest" ]; then
    printf "Applying ownership manifest...\n"

    # Phase 1: bulk defaults
    chown -R root:sys "$PKGDIR/"
    chown -R root:bin "$PKGDIR/bin" "$PKGDIR/sbin" \
        "$PKGDIR/usr/bin" "$PKGDIR/usr/sbin" \
        "$PKGDIR/usr/lib" "$PKGDIR/lib" 2>/dev/null || true

    # Phase 2: per-file overrides from manifest
    while IFS=' ' read -r path mode owner group; do
        # Skip comments and blank lines
        [[ -z "$path" || "$path" = \#* ]] && continue
        target="$PKGDIR$path"
        if [ -e "$target" ] || [ -L "$target" ]; then
            chmod "$mode" "$target" 2>/dev/null || true
            chown "$owner:$group" "$target" 2>/dev/null || true
        fi
    done < "$ROOTFS_DIR/ownership.manifest"
else
    # No manifest — apply bulk defaults only
    printf "WARNING: No ownership manifest found, applying bulk defaults\n"
    chown -R root:sys "$PKGDIR/"
    chown -R root:bin "$PKGDIR/bin" "$PKGDIR/sbin" \
        "$PKGDIR/usr/bin" "$PKGDIR/usr/sbin" \
        "$PKGDIR/usr/lib" "$PKGDIR/lib" 2>/dev/null || true
fi

# --- Create .CONFIG (config-protected files) ---
# These files will not be overwritten on upgrade if user has modified them.
# New versions are installed as <file>.pkg for manual merging.
cat > "$PKGDIR/.CONFIG" << 'EOF'
/etc/system
/etc/vfstab
/etc/passwd
/etc/shadow
/etc/group
/etc/hosts
/etc/inet/hosts
/etc/nsswitch.conf
/etc/resolv.conf
/etc/nodename
/etc/pam.conf
/etc/profile
/etc/zshenv
/etc/zshrc
/etc/zprofile
/etc/default/init
/etc/default/login
/etc/default/useradd
/etc/security/policy.conf
/etc/security/crypt.conf
/etc/crypto/pkcs11.conf
/etc/ssh/sshd_config
/etc/syslog.conf
/etc/sudoers.d/zygaena
/etc/svc/profile/site.xml
/etc/coral/coral.conf
EOF

# --- Post-install script ---
mkdir -p "$PKGDIR/.SCRIPTS"
cat > "$PKGDIR/.SCRIPTS/post-install.sh" << 'SCRIPT'
#!/bin/ksh93
# Refresh SMF repository if svc.configd is running (live system upgrade)
if [ -f /lib/svc/bin/svc.configd ]; then
    if pgrep -x svc.configd >/dev/null 2>&1; then
        printf "Refreshing SMF manifests...\n"
        svccfg import /lib/svc/manifest 2>/dev/null || true
    fi
fi
SCRIPT
chmod 755 "$PKGDIR/.SCRIPTS/post-install.sh"

# --- Summary ---
CMDS=0
for d in "$PKGDIR/bin" "$PKGDIR/sbin" "$PKGDIR/usr/bin" "$PKGDIR/usr/sbin"; do
    if [ -d "$d" ]; then
        n=$(find "$d" -type f | wc -l)
        CMDS=$((CMDS + n))
    fi
done
LIBS=$(find "$PKGDIR/lib" "$PKGDIR/usr/lib" -name "*.so.*" -type f 2>/dev/null | wc -l)
SIZE=$(du -sh "$PKGDIR" | cut -f1)
printf "Packaged %d commands, %d libraries (%s total)\n" "$CMDS" "$LIBS" "$SIZE"
