#!/bin/bash -p

# omarchy:summary=Print the hardware platform: x86, aarch64 or aarch64-apple.

# Platform names are the CPU architecture, then the hardware family when it
# needs handling of its own: x86, aarch64 (every ARM machine without one) and
# aarch64-apple (Apple Silicon). A later family is aarch64-<family>, so
# "aarch64*" always means ARM (AGENTS.md, Platforms).
#
# ARM laptops have no DMI, so the board identity is the root node of the device
# tree the firmware hands the kernel: "apple,<model>" from Asahi's m1n1 on every
# Apple Silicon Mac, "qcom,<soc>" on Snapdragon laptops, which are plain aarch64
# here and must never pass for a Mac. Each compatible string is a NUL-separated
# list, and only a token's vendor prefix counts.
#
# An image is built away from the machine it will run on, so while this root is
# being built rather than booted, the image-target manifest the builder wrote
# names the platform and the build host's device tree is never read.
#
# Fixture roots let unprivileged tests fake the device tree, PID 1 and the image
# root. Naming any of them makes the whole view a fixture: nothing live is read,
# not even the device tree when only the image root is named. A privileged
# caller must not let its environment pick the platform at all.
# Privileged mode (-p) keeps exported functions and BASH_ENV out of this shell,
# so a launch without it is refused. Root then starts over in an empty
# environment and reads only the live paths with a fixed PATH.
if [[ $- != *p* ]]; then
  echo "Refusing an unsafe Bash startup." >&2
  exit 126
fi

if (( EUID == 0 )) && [[ ${1:-} != --clean-environment ]]; then
  exec /usr/bin/env -i PATH=/usr/bin /bin/bash -p -- "${BASH_SOURCE[0]}" --clean-environment "$@"
fi

if (( EUID == 0 )); then
  export PATH=/usr/bin
  fixtures=""
else
  fixtures=${OMARCHY_PROC_ROOT:-}${OMARCHY_SYS_ROOT:-}${OMARCHY_IMAGE_ROOT:-}
fi

if [[ -z $fixtures ]]; then
  proc=/proc
  sources=(/proc/device-tree/compatible /sys/firmware/devicetree/base/compatible)
  image_root=""
  image_dir=/var/lib/omarchy/image
  image_owner=0
else
  proc=${OMARCHY_PROC_ROOT:-}
  sources=()
  [[ -z ${OMARCHY_PROC_ROOT:-} ]] || sources+=("$OMARCHY_PROC_ROOT/device-tree/compatible")
  [[ -z ${OMARCHY_SYS_ROOT:-} ]] || sources+=("$OMARCHY_SYS_ROOT/firmware/devicetree/base/compatible")
  image_root=${OMARCHY_IMAGE_ROOT:-}
  image_dir=${image_root:+$image_root/var/lib/omarchy/image}
  image_owner=$EUID
fi
manifest=$image_dir/target

contradiction() {
  echo "Error: contradictory platform identity: $1" >&2
  exit 1
}

if ! machine=$(uname -m) || [[ -z $machine ]]; then
  echo "Error: cannot read the CPU architecture" >&2
  exit 1
fi

# A booted system is one systemd runs as PID 1 from this root. An image build
# is told apart by what it shows: no /run/systemd/system (a root with a /run of
# its own), PID 1's root being another (a chroot on the build host, even with
# the host's /run bound in, as arch-chroot does), or PID 1 being something other
# than systemd (a PID namespace whose PID 1 is the build). What cannot be seen,
# such as PID 1's root to a normal user or /proc/1 behind hidepid, never makes a
# build: a booted system always answers from its hardware, so a build runs as
# root. A caller in a private PID namespace looks like a build too, so nothing
# that asks the detector runs with PrivatePIDs=.
booted() {
  local comm

  [[ -d $image_root/run/systemd/system ]] || return 1
  if [[ -n $proc && -e $proc/1/root ]]; then
    [[ $proc/1/root -ef $image_root/ ]] || return 1
  fi
  if [[ -n $proc && -r $proc/1/comm ]]; then
    read -r comm <"$proc/1/comm" && [[ $comm == "systemd" ]] || return 1
  fi
}

# Owned by root (the test's own user for a fixture), not a symlink, and not
# writable by anyone else.
trusted() {
  local owner mode

  [[ -e $1 && ! -L $1 ]] || return 1
  read -r owner mode < <(stat -c '%u %a' -- "$1") || return 1
  [[ $owner =~ ^[0-9]+$ && $mode =~ ^[0-7]+$ ]] && (( owner == image_owner && (8#$mode & 8#022) == 0 ))
}

# The manifest: format=1, platform= one of the platform names, comments and
# unknown keys ignored, and any other line refused. Image builders written before
# the names settled say apple-silicon, generic-aarch64 or generic, which still
# read as aarch64-apple, aarch64 and x86. The detector reads it itself, so it
# stands alone wherever a package ships a copy of it.
image_platform() {
  local line key value format="" platform=""

  if [[ ! -d $image_dir || ! -f $manifest ]] || ! trusted "$image_dir" || ! trusted "$manifest"; then
    echo "Error: the image manifest $manifest is not a root-owned regular file" >&2
    return 1
  fi

  while IFS= read -r line || [[ -n $line ]]; do
    [[ -n $line && $line != \#* ]] || continue
    if [[ $line != *=* ]]; then
      echo "Error: the image manifest $manifest is malformed: $line" >&2
      return 1
    fi
    key=${line%%=*}
    value=${line#*=}
    case $key in
      format) format=$value ;;
      platform) platform=$value ;;
    esac
  done <"$manifest"

  if [[ $format != "1" ]]; then
    echo "Error: the image manifest $manifest is not format=1" >&2
    return 1
  fi
  case $platform in
    apple-silicon) platform=aarch64-apple ;;
    generic-aarch64) platform=aarch64 ;;
    generic) platform=x86 ;;
  esac
  if [[ ! $platform =~ ^(x86|aarch64|aarch64-apple)$ ]]; then
    echo "Error: the image manifest $manifest names no known platform: ${platform:-none}" >&2
    return 1
  fi

  echo "$platform"
}

if [[ -n $image_dir ]] && [[ -e $manifest || -L $manifest ]] && ! booted; then
  platform=$(image_platform) || exit 1
  if [[ $platform == "x86" ]]; then
    [[ $machine != "aarch64" ]] || contradiction "$manifest names $platform hardware but the CPU is $machine"
  else
    [[ $machine == "aarch64" ]] || contradiction "$manifest names $platform hardware but the CPU is $machine"
  fi
  echo "$platform"
  exit 0
fi

vendor=""
vendor_source=""
for source in "${sources[@]}"; do
  [[ -r $source ]] || continue

  apple=0
  qcom=0
  mapfile -d '' -t tokens <"$source"
  for token in "${tokens[@]}"; do
    [[ $token == "apple,"* ]] && apple=1
    [[ $token == "qcom,"* ]] && qcom=1
  done

  if (( apple && qcom )); then
    contradiction "$source names both Apple and Qualcomm hardware"
  elif (( apple )); then
    found=apple
  elif (( qcom )); then
    found=qcom
  else
    found=none
  fi

  if [[ -n $vendor && $vendor != "$found" ]]; then
    contradiction "$vendor_source says $vendor but $source says $found"
  fi
  vendor=$found
  vendor_source=$source
done

case $vendor in
  apple | qcom)
    [[ $machine == "aarch64" ]] || contradiction "$vendor_source names $vendor hardware but the CPU is $machine"
    if [[ $vendor == "apple" ]]; then
      echo aarch64-apple
    else
      echo aarch64
    fi
    ;;
  *)
    if [[ $machine == "aarch64" ]]; then
      echo aarch64
    else
      echo x86
    fi
    ;;
esac
