#!/bin/bash
#
# TEMPORARY TESTING WORKAROUND ONLY
#
# DO NOT USE IN PRODUCTION.
#
# This workaround exists solely to enable continued SDP/P4D testing on
# Ubuntu 26 while Canonical investigates and fixes:
#
# https://bugs.launchpad.net/ubuntu/+source/rust-coreutils/+bug/2161574
#
# The bug appears to affect the default Rust-based implementation of
# 'chown' shipped in Ubuntu 26.
#
# This script attempts to redirect /usr/bin/chown to the GNU implementation
# (/usr/bin/gnuchown) if:
#
#   1. The script is run as root.
#   2. gnuchown is available.
#   3. chown currently resolves to the Rust implementation.
#   4. The workaround has not already been applied.
#
# This script is intentionally idempotent.
#
# Remove this workaround immediately when Canonical publishes an official
# fix for the defect referenced above.
#

set -eu

GNU_CHOWN="/usr/bin/gnuchown"
CHOWN="/usr/bin/chown"
BACKUP="/usr/bin/coreutils-chown"

log() {
    echo "INFO: $*"
}

fail() {
    echo "ERROR: $*" >&2
    exit 1
}

#
# Must be run as root.
#
if [ "$(id -u)" -ne 0 ]; then
    fail "This script must be run as root."
fi

log "Checking Ubuntu 26 chown workaround prerequisites..."

#
# GNU chown must exist.
#
if [ ! -x "$GNU_CHOWN" ]; then
    log "$GNU_CHOWN not found."
    log "No workaround applied."
    exit 0
fi

#
# If chown already points to gnuchown, we're done.
#
if [ -L "$CHOWN" ]; then
    CURRENT_TARGET="$(readlink "$CHOWN")"

    if [ "$CURRENT_TARGET" = "$GNU_CHOWN" ] || \
       [ "$CURRENT_TARGET" = "gnuchown" ]; then
        log "Workaround already applied."
        exit 0
    fi
fi

#
# Determine what chown currently resolves to.
#
RESOLVED="$(readlink -f "$CHOWN" 2>/dev/null || true)"

if [ -z "$RESOLVED" ]; then
    fail "Unable to resolve $CHOWN."
fi

#
# Refuse to proceed unless we can positively identify a Rust coreutils
# implementation. This avoids modifying unexpected packaging layouts.
#
# Two independent signals are checked, since the on-disk path shape has
# varied across Ubuntu 26 images seen so far:
#   - a path matching the multicall-binary or cargo-built layout, or
#   - the 'uutils coreutils' identifier in 'chown --version' (uutils is
#     the upstream project name for the Rust reimplementation).
#
VERSION_OUTPUT="$("$CHOWN" --version 2>/dev/null || true)"

case "$RESOLVED" in
    *rust-coreutils*|*/coreutils/coreutils|*/cargo/bin/coreutils/*)
        log "Rust-based chown detected (path):"
        log "  $RESOLVED"
        ;;
    *)
        case "$VERSION_OUTPUT" in
            *uutils*)
                log "Rust-based chown detected (version string):"
                log "  $VERSION_OUTPUT"
                ;;
            *)
                log "Current chown does not appear to be Rust coreutils:"
                log "  $RESOLVED"
                log "No workaround applied."
                exit 0
                ;;
        esac
        ;;
esac

#
# Preserve the original chown once.
#
if [ ! -e "$BACKUP" ]; then
    log "Creating backup:"
    log "  $BACKUP"

    mv "$CHOWN" "$BACKUP"
else
    log "Backup already exists:"
    log "  $BACKUP"
fi

#
# Replace chown with GNU chown.
#
ln -sfn "$GNU_CHOWN" "$CHOWN"

log "Workaround applied successfully."
log "$CHOWN now resolves to:"
log "  $(readlink -f "$CHOWN")"
log ""
log "FOR TESTING PURPOSES ONLY."
log "DO NOT USE THIS WORKAROUND IN PRODUCTION."
log "Track Canonical bug:"
log "  https://bugs.launchpad.net/ubuntu/+source/rust-coreutils/+bug/2161574"
