From 7b48fc552fd5244064f217e3d4c5181c16e89e3c Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Fri, 24 Oct 2025 23:30:01 +0200 Subject: [PATCH] expand pacman whitelist and fix locked db --- scripts/pacman_whitelist.txt | 72 +++++++++++++++++++++- scripts/pacman_wrapper.sh | 114 +++++++++++++++++++++++++++++++++++ 2 files changed, 185 insertions(+), 1 deletion(-) diff --git a/scripts/pacman_whitelist.txt b/scripts/pacman_whitelist.txt index ee4e198..09facb9 100644 --- a/scripts/pacman_whitelist.txt +++ b/scripts/pacman_whitelist.txt @@ -99,4 +99,74 @@ python-dateutil python-kiwisolver python-pyparsing python-platformdirs -python-pycparser \ No newline at end of file +python-pycparser +python-dbus-next +python-parse +python-pyvips +python-systemd +python-colorlog +python-injector +python-peewee +python-py3nvml +python-reactivex +python-pyusb +python-hidapi +python-crcmod +gst-python +python-beautifulsoup4 +python-certifi +python-evdev +python-moddb +python-aioquic +python-argon2-cffi +python-asgiref +python-flask +python-h11 +python-h2 +python-hyperframe +python-kaitaistruct +python-ldap3 +python-mitmproxy-rs +python-msgpack +python-passlib +python-publicsuffix2 +python-pyperclip +python-ruamel-yaml +python-sortedcontainers +python-tornado +python-urwid +python-wsproto +python-zstandard +python-bcrypt +python-aaf2 +python-vdf +python-inputs +python-pyaml +python-steam +python-readme-renderer +python-requests-toolbelt +python-importlib-metadata +python-keyring +python-rfc3986 +python-rich +python-id +python-pylsqpack +python-argon2-cffi-bindings +python-soupsieve +python-blinker +python-itsdangerous +python-werkzeug +python-hpack +python-zipp +python-jaraco.classes +python-secretstorage +python-pkgconfig +python-docutils +python-nh3 +python-markdown-it-py +python-ruamel.yaml.clib +python-cachetools +python-pycryptodomex +python-wcwidth +python-mdurl +python-jeepney \ No newline at end of file diff --git a/scripts/pacman_wrapper.sh b/scripts/pacman_wrapper.sh index 7c1a53c..70c4046 100755 --- a/scripts/pacman_wrapper.sh +++ b/scripts/pacman_wrapper.sh @@ -204,6 +204,115 @@ function has_noconfirm_flag() { return 1 } +# Handle stale pacman database lock if present and no package managers are running +check_and_handle_db_lock() { + local lock_file="/var/lib/pacman/db.lck" + # Quick exit if no lock + if [[ ! -e "$lock_file" ]]; then + return 0 + fi + + # Determine which processes actually have the lock open + local -a holders=() + if command -v fuser >/dev/null 2>&1; then + mapfile -t holders < <(fuser "$lock_file" 2>/dev/null | tr ' ' '\n' | grep -E '^[0-9]+$' || true) + elif command -v lsof >/dev/null 2>&1; then + mapfile -t holders < <(lsof -t "$lock_file" 2>/dev/null | grep -E '^[0-9]+$' || true) + else + holders=() + fi + + # Filter out our own PID if it somehow appears + if [[ ${#holders[@]} -gt 0 ]]; then + local -a filtered=() + for pid in "${holders[@]}"; do + [[ "$pid" -eq "$$" ]] && continue + filtered+=("$pid") + done + holders=("${filtered[@]}") + fi + + if [[ ${#holders[@]} -gt 0 ]]; then + local pac_holder=0 + local gui_holder=0 + for pid in "${holders[@]}"; do + local comm args lower + comm=$(ps -p "$pid" -o comm= 2>/dev/null || true) + args=$(ps -p "$pid" -o args= 2>/dev/null || true) + lower="${comm,,} ${args,,}" + if [[ "$lower" == *" pacman"* || "$lower" == pacman* || "$lower" == *"/pacman "* || "$lower" == *" pamac"* ]]; then + pac_holder=1 + elif [[ "$lower" == *packagekit* || "$lower" == *gnome-software* || "$lower" == *discover* ]]; then + gui_holder=1 + fi + done + + if [[ $pac_holder -eq 1 ]]; then + echo -e "${RED}Another pacman/pamac transaction is holding the database lock. Try again later.${NC}" >&2 + return 1 + fi + + if [[ $gui_holder -eq 1 ]]; then + echo -e "${YELLOW}A background software updater is holding the pacman lock. Attempting to stop it...${NC}" >&2 + if command -v systemctl >/dev/null 2>&1; then + systemctl --quiet stop packagekit.service 2>/dev/null || true + systemctl --quiet stop packagekit 2>/dev/null || true + fi + pkill -x packagekitd 2>/dev/null || true + pkill -f gnome-software 2>/dev/null || true + pkill -f discover 2>/dev/null || true + sleep 1 + + # Re-check holders + holders=() + if command -v fuser >/dev/null 2>&1; then + mapfile -t holders < <(fuser "$lock_file" 2>/dev/null | tr ' ' '\n' | grep -E '^[0-9]+$' || true) + elif command -v lsof >/dev/null 2>&1; then + mapfile -t holders < <(lsof -t "$lock_file" 2>/dev/null | grep -E '^[0-9]+$' || true) + fi + if [[ ${#holders[@]} -gt 0 ]]; then + echo -e "${RED}Cannot free the pacman lock; another process still holds it. Try again later.${NC}" >&2 + return 1 + fi + fi + fi + + # Decide whether to remove the lock + local now epoch age + if epoch=$(stat -c %Y "$lock_file" 2>/dev/null); then + now=$(date +%s) + age=$(( now - epoch )) + else + age=999999 + fi + + # Auto-remove in non-interactive mode (--noconfirm) or if the lock is older than 10 minutes + if has_noconfirm_flag "$@" || [[ $age -ge 600 ]]; then + echo -e "${YELLOW}Stale pacman lock detected (age: ${age}s). Removing it automatically...${NC}" >&2 + if [[ $EUID -ne 0 ]]; then + sudo rm -f "$lock_file" || return 1 + else + rm -f "$lock_file" || return 1 + fi + return 0 + fi + + # Interactive prompt (15s timeout) + echo -e "${YELLOW}A pacman lock exists but no active pacman is running.${NC}" >&2 + echo -e "${CYAN}Lock path:${NC} $lock_file (age: ${age}s)" >&2 + read -r -t 15 -p $'Remove stale lock and continue? [y/N]: ' reply || reply="n" + if [[ "${reply,,}" == "y" || "${reply,,}" == "yes" ]]; then + if [[ $EUID -ne 0 ]]; then + sudo rm -f "$lock_file" || return 1 + else + rm -f "$lock_file" || return 1 + fi + return 0 + fi + echo -e "${RED}Aborting due to existing pacman lock. Close other updaters and retry, or run with --noconfirm to auto-clear stale locks.${NC}" >&2 + return 1 +} + # Cleanup: remove any installed blocked packages (in addition to the queued operation) function remove_installed_blocked_packages() { # args not used; kept for future policy extension @@ -586,6 +695,11 @@ if needs_unlock "$@"; then pre_unlock_hosts fi +# Handle a possible stale DB lock before executing +if ! check_and_handle_db_lock "$@"; then + exit 1 +fi + "$PACMAN_BIN" "$@" exit_code=$?