#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2026 Michal Schorm <mschorm@redhat.com>
#
# Regenerate /etc/odbcinst.ini from drop-in snippets.
#
# Merge order:
#   1. /usr/lib/odbc/odbcinst.d/*.ini  (vendor, low-numbered prefixes)
#   2. /etc/odbc/odbcinst.d/*.ini      (admin, high-numbered prefixes)
#
# Override rules:
#   - Files are sorted by full basename (numeric prefix determines order)
#   - When two files share the same name after stripping the numeric prefix
#     (e.g., 10-mariadb.ini and 60-mariadb.ini), the higher-numbered one wins
#   - A symlink to /dev/null disables the corresponding driver entry
#
# This script is called from RPM file triggers and %post.
# It must be safe to run at any time (idempotent).

set -eo pipefail

VENDOR_DIR=/usr/lib/odbc/odbcinst.d
ADMIN_DIR=/etc/odbc/odbcinst.d
TARGET=/etc/odbcinst.ini

tmpfile=$(mktemp "${TARGET}.XXXXXX")
resolved=""
trap 'rm -f "$tmpfile" "$resolved"' EXIT

cat > "$tmpfile" << 'HEADER'
# Auto-generated from drop-in snippets.  Do not edit this file.
#
# Vendor defaults:  /usr/lib/odbc/odbcinst.d/*.ini
# Admin overrides:  /etc/odbc/odbcinst.d/*.ini
#
# To override a vendor driver, place a file with the same name
# (or higher numeric prefix) in /etc/odbc/odbcinst.d/.
# To disable a vendor driver, symlink its snippet to /dev/null:
#   ln -sf /dev/null /etc/odbc/odbcinst.d/10-freetds.ini
#
# To apply changes after editing drop-in files, run:
#   odbcinst-generate
HEADER

# Build an associative array: key → path (last writer wins by sort order)
declare -A snippets

# Process vendor first (lower priority), then admin (higher priority)
for dir in "$VENDOR_DIR" "$ADMIN_DIR"; do
    [ -d "$dir" ] || continue
    for f in "$dir"/*.ini; do
        [ -e "$f" ] || continue
        base=$(basename "$f")
        # Strip numeric prefix for override matching: "10-mariadb.ini" → "mariadb.ini"
        key="${base#[0-9][0-9]-}"
        snippets["$key"]="$f"
    done
done

# Sort keys and emit content
if [ ${#snippets[@]} -gt 0 ]; then
    while IFS= read -r key; do
        f="${snippets[$key]}"

        # Symlink to /dev/null = disabled
        if [ -L "$f" ] && [ "$(readlink -f "$f")" = "/dev/null" ]; then
            continue
        fi

        [ -f "$f" ] || continue
        echo "" >> "$tmpfile"
        cat "$f" >> "$tmpfile"
    done < <(printf '%s\n' "${!snippets[@]}" | sort)
fi

# Resolve bare library names (e.g. "libmaodbc.so") to absolute paths.
# unixODBC finds bare names via its compiled-in --with-odbc-driver-path,
# but iODBC requires absolute paths for dlopen().  Absolute paths also
# make the generated config self-documenting.
#
# Multilib: when a driver .so exists in both /usr/lib64/odbc/ and
# /usr/lib/odbc/ (e.g. both x86_64 and i686 RPMs installed), emit
# Driver= for the 32-bit path and Driver64= for the 64-bit path.
# unixODBC selects the matching key based on the calling application's
# word size.  When only one architecture is present, only Driver= is
# emitted.  Same for Setup/Setup64.
#
# If a bare name is not found in either directory, it is left unchanged
# so unixODBC can still find it via its built-in search path.
resolved=$(mktemp "${TARGET}.XXXXXX")

while IFS= read -r line; do
    if [[ "$line" =~ ^((Driver|Setup)[[:space:]]*=[[:space:]]*)([^/[:space:]][^/[:space:]]*\.so[^/[:space:]]*)[[:space:]]*$ ]]; then
        prefix="${BASH_REMATCH[1]}"
        key="${BASH_REMATCH[2]}"
        bare="${BASH_REMATCH[3]}"

        in_lib64=""
        in_lib32=""
        [ -f "/usr/lib64/odbc/$bare" ] && in_lib64="/usr/lib64/odbc/$bare"
        [ -f "/usr/lib/odbc/$bare" ]   && in_lib32="/usr/lib/odbc/$bare"

        if [ -n "$in_lib64" ] && [ -n "$in_lib32" ]; then
            printf '%s%s\n' "$prefix" "$in_lib32"
            printf '%s64 = %s\n' "$key" "$in_lib64"
        elif [ -n "$in_lib64" ]; then
            printf '%s%s\n' "$prefix" "$in_lib64"
        elif [ -n "$in_lib32" ]; then
            printf '%s%s\n' "$prefix" "$in_lib32"
        else
            printf '%s\n' "$line"
        fi
    else
        printf '%s\n' "$line"
    fi
done < "$tmpfile" > "$resolved"

mv "$resolved" "$tmpfile"

# Atomic replace
chmod 644 "$tmpfile"
mv "$tmpfile" "$TARGET"
trap - EXIT
