#!/bin/bash # fix-rootfs.sh — nakłada poprawki na istniejący rootfs (bez przebudowy pakietów), # przed ponownym budowaniem ISO. Uzupełnienie dla build-pagan.sh (którego poprawki # wchodzą w życie dopiero przy świeżym buildzie; resume pomija już zbudowane pakiety). # # Uruchom: sudo ./fix-rootfs.sh [PAGAN_ROOT] set -euo pipefail PAGAN_ROOT="${1:-/mnt/pagan}" if [[ ! -d "$PAGAN_ROOT/usr" || ! -d "$PAGAN_ROOT/etc" || ! -f "$PAGAN_ROOT/etc/passwd" ]]; then echo "BŁĄD: $PAGAN_ROOT nie wygląda na rootfs Pagan" >&2 exit 1 fi # dbus: jeśli binarka wspiera aktywację socketową (przebudowa z ENABLE_SYSTEMD=ON # w build-pagan.sh), piszemy POPRAWNE jednostki dbus.socket/dbus.service # (cmake z dbus 1.16.2 generuje je z pustymi @EXPANDED_BINDIR@/@DBUS_SYSTEM_SOCKET@ – # bug, patrz bus/dbus.service.in) i włączamy socket. Hack tylko dla starego dbus # (bez wsparcia systemd). Uwaga: dbus-daemon --help NIE pokazuje tej opcji, # dlatego sprawdzamy strings. if strings "$PAGAN_ROOT/usr/bin/dbus-daemon" 2>/dev/null | grep -q -- "--systemd-activation"; then echo "=== 1/8 dbus: wsparcie systemd (aktywacja socketowa) – poprawne jednostki ===" cat > "$PAGAN_ROOT/usr/lib/systemd/system/dbus.socket" <<'EOF' [Unit] Description=D-Bus System Message Bus Socket [Socket] ListenStream=/run/dbus/system_bus_socket SocketMode=0666 [Install] WantedBy=sockets.target EOF cat > "$PAGAN_ROOT/usr/lib/systemd/system/dbus.service" <<'EOF' [Unit] Description=D-Bus System Message Bus Documentation=man:dbus-daemon(1) Requires=dbus.socket [Service] Type=notify NotifyAccess=main ExecStart=/usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only ExecReload=/usr/bin/dbus-send --print-reply --system --type=method_call --dest=org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig ExecStartPre=/usr/bin/dbus-uuidgen --ensure RuntimeDirectory=dbus RuntimeDirectoryMode=0755 Restart=on-failure RestartSec=1s OOMScoreAdjust=-900 EOF # Stary symlink z hacka (multi-user.target.wants) i drop-in logind są zbędne rm -f "$PAGAN_ROOT/etc/systemd/system/multi-user.target.wants/dbus.service" \ "$PAGAN_ROOT/etc/systemd/system/systemd-logind.service.d/override.conf" chroot "$PAGAN_ROOT" systemctl enable dbus.socket 2>/dev/null || true # Wczesny start dbus.service (sockets.target) – klienci (PID1/networkd) łączą # się zanim daemon wystartuje; dbus zrywa połączenia z okna startowego ln -sf /usr/lib/systemd/system/dbus.service \ "$PAGAN_ROOT/etc/systemd/system/sockets.target.wants/dbus.service" else echo "=== 1/8 dbus: usuwam dbus.socket (aktywacja socketowa psuje dbus-daemon) ===" rm -f "$PAGAN_ROOT/usr/lib/systemd/system/dbus.socket" \ "$PAGAN_ROOT/etc/systemd/system/sockets.target.wants/dbus.socket" echo "=== 2/8 dbus.service: klasyczne wywołanie + czekanie na socket + restart ===" cat > "$PAGAN_ROOT/usr/lib/systemd/system/dbus.service" <<'EOF' [Unit] Description=D-Bus System Message Bus [Service] ExecStart=/usr/bin/dbus-daemon --system --nofork --nopidfile ExecStartPost=/bin/sh -c 'i=0; while [ ! -S /run/dbus/system_bus_socket ] && [ $i -lt 100 ]; do i=$((i+1)); sleep 0.1; done; [ -S /run/dbus/system_bus_socket ]' ExecReload=/usr/bin/dbus-send --print-reply --system --type=method_call --dest=org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig ExecStartPre=/usr/bin/dbus-uuidgen --ensure RuntimeDirectory=dbus RuntimeDirectoryMode=0755 Restart=on-failure RestartSec=1 Type=simple EOF # dbus-daemon loguje na stderr → journal → konsola (diagnostyka) grep -q '^ExecStart=/usr/bin/dbus-daemon --system --nofork --nopidfile$' "$PAGAN_ROOT/usr/lib/systemd/system/dbus.service" || { echo "BŁĄD: dbus.service nie ma poprawnego ExecStart" >&2 exit 1 } fi echo "=== 3/7 usrmerge: /usr/sbin → /usr/bin, /sbin → usr/bin (systemd split-usr=false) ===" if [[ ! -L "$PAGAN_ROOT/usr/sbin" && -d "$PAGAN_ROOT/usr/sbin" ]]; then # SysVinit-owe halt/shutdown/poweroff/reboot przegrywają z systemd (/usr/bin) rm -f "$PAGAN_ROOT/usr/sbin/halt" "$PAGAN_ROOT/usr/sbin/shutdown" \ "$PAGAN_ROOT/usr/sbin/poweroff" "$PAGAN_ROOT/usr/sbin/reboot" \ "$PAGAN_ROOT/usr/sbin/init" mv "$PAGAN_ROOT/usr/sbin"/* "$PAGAN_ROOT/usr/bin/" rmdir "$PAGAN_ROOT/usr/sbin" fi ln -sfn bin "$PAGAN_ROOT/usr/sbin" ln -sfn usr/bin "$PAGAN_ROOT/sbin" echo "=== 4/7 /usr/lib64 → /usr/lib (ld.so nie szuka /usr/lib64; libtiff → libjpeg.so.62) ===" if [[ ! -L "$PAGAN_ROOT/usr/lib64" && -d "$PAGAN_ROOT/usr/lib64" ]]; then # zachowaj dev-symlink libjpeg.so z /usr/lib (→ .8); stary .pc też pomijamy rm -f "$PAGAN_ROOT/usr/lib64/libjpeg.so" "$PAGAN_ROOT/usr/lib64/pkgconfig/libjpeg.pc" cp -a "$PAGAN_ROOT/usr/lib64/." "$PAGAN_ROOT/usr/lib/" 2>/dev/null || true rm -rf "$PAGAN_ROOT/usr/lib64" fi ln -sfn lib "$PAGAN_ROOT/usr/lib64" echo "=== 5/7 /var/run, /var/lock → symlinki do tmpfs /run (taint var-run-bad) ===" rm -rf "$PAGAN_ROOT/var/run" ln -sfn ../run "$PAGAN_ROOT/var/run" rm -rf "$PAGAN_ROOT/var/lock" ln -sfn ../run/lock "$PAGAN_ROOT/var/lock" echo "=== 6/7 użytkownicy/grupy + systemd-owe binarki kontrolne ===" grep -q '^man:' "$PAGAN_ROOT/etc/passwd" || \ echo 'man:x:12:12:Manuals Reader:/var/cache/man:/usr/sbin/nologin' >> "$PAGAN_ROOT/etc/passwd" grep -q '^messagebus:' "$PAGAN_ROOT/etc/passwd" || \ echo 'messagebus:x:81:81:system message bus:/:/usr/sbin/nologin' >> "$PAGAN_ROOT/etc/passwd" for g in "man:x:12:" "clock:x:35:" "sgx:x:974:" "messagebus:x:81:"; do name="${g%%:*}" grep -q "^${name}:" "$PAGAN_ROOT/etc/group" || echo "$g" >> "$PAGAN_ROOT/etc/group" done for b in halt poweroff reboot shutdown; do ln -sf systemctl "$PAGAN_ROOT/usr/bin/$b" done ln -sf ../lib/systemd/systemd "$PAGAN_ROOT/usr/bin/init" # logind: zależał od dbus.socket (nie istnieje) – drop-in na dbus.service. # (tylko dla starego dbus bez aktywacji socketowej; przy standardowym dbus.socket # drop-in jest zbędny – socket aktywuje daemona przed dokończeniem connect) echo "=== 7/8 logind drop-in (After=dbus.service) + locale UTF-8 ===" if strings "$PAGAN_ROOT/usr/bin/dbus-daemon" 2>/dev/null | grep -q -- "--systemd-activation"; then rm -rf "$PAGAN_ROOT/etc/systemd/system/systemd-logind.service.d" else mkdir -p "$PAGAN_ROOT/etc/systemd/system/systemd-logind.service.d" cat > "$PAGAN_ROOT/etc/systemd/system/systemd-logind.service.d/override.conf" <<'EOF' [Unit] Wants=dbus.service After=dbus.service EOF fi for _loc in en_US.UTF-8 pl_PL.UTF-8; do mkdir -p "$PAGAN_ROOT/usr/lib/locale" chroot "$PAGAN_ROOT" /usr/bin/localedef -i "${_loc%.*}" -f UTF-8 "$_loc" || true done ls "$PAGAN_ROOT/usr/lib/locale/" 2>/dev/null || true # PAM + sddm + autologin – parzystość z finalize_build() w build-pagan.sh. # Stary /etc/pam.d/login (np. z shadow) odwołuje się do pam_selinux.so i # pam_console.so, których w tym systemie NIE MA → login: Permission denied, # getty@tty1 w crash-loopie i w końcu start-limit-hit. Bez tych plików NIE # da się zalogować na tty1/ttyS0. echo "=== 8/8 PAM (login/system-*) + autologin tty1 + sddm off ===" mkdir -p "$PAGAN_ROOT/etc/pam.d" cat > "$PAGAN_ROOT/etc/pam.d/other" <<'EOF' #%PAM-1.0 auth required pam_deny.so auth required pam_warn.so account required pam_deny.so account required pam_warn.so password required pam_deny.so password required pam_warn.so session required pam_deny.so session required pam_warn.so EOF cat > "$PAGAN_ROOT/etc/pam.d/system-auth" <<'EOF' #%PAM-1.0 auth required pam_env.so auth sufficient pam_unix.so nullok try_first_pass auth required pam_deny.so EOF cat > "$PAGAN_ROOT/etc/pam.d/system-account" <<'EOF' #%PAM-1.0 account required pam_unix.so EOF cat > "$PAGAN_ROOT/etc/pam.d/system-password" <<'EOF' #%PAM-1.0 password required pam_unix.so sha512 shadow nullok try_first_pass EOF cat > "$PAGAN_ROOT/etc/pam.d/system-session" <<'EOF' #%PAM-1.0 session required pam_limits.so session required pam_unix.so session optional pam_systemd.so EOF cat > "$PAGAN_ROOT/etc/pam.d/system-login" <<'EOF' #%PAM-1.0 auth include system-auth account include system-account password include system-password session include system-session EOF cat > "$PAGAN_ROOT/etc/pam.d/system-local-login" <<'EOF' #%PAM-1.0 auth include system-login account include system-login password include system-login session include system-login EOF cat > "$PAGAN_ROOT/etc/pam.d/sddm-autologin" <<'EOF' #%PAM-1.0 auth required pam_env.so auth required pam_permit.so account include system-local-login password include system-local-login session include system-local-login session optional pam_systemd.so EOF cat > "$PAGAN_ROOT/etc/pam.d/sddm" <<'EOF' #%PAM-1.0 auth include system-login account include system-login password include system-login session include system-login session optional pam_systemd.so EOF cat > "$PAGAN_ROOT/etc/pam.d/sddm-greeter" <<'EOF' #%PAM-1.0 auth required pam_env.so auth required pam_permit.so account required pam_permit.so password required pam_deny.so session required pam_unix.so session optional pam_systemd.so EOF # Nadpisanie domyślnego niespójnego /etc/pam.d/login (np. z shadow), które odwołuje się do SELinux/console cat > "$PAGAN_ROOT/etc/pam.d/login" <<'EOF' #%PAM-1.0 auth required pam_securetty.so auth requisite pam_nologin.so auth include system-local-login account include system-local-login password include system-local-login session include system-local-login session optional pam_loginuid.so EOF # Naprawa /etc/pam.d/sudo – starsze obrazy miały "account include system-auth", # co daje PUSTY stos account (system-auth ma tylko auth) i sudo pada: # "account validation failure, is your account locked?". cat > "$PAGAN_ROOT/etc/pam.d/sudo" <<'EOF' #%PAM-1.0 auth include system-auth account include system-account session required pam_env.so session include system-session EOF chmod 644 "$PAGAN_ROOT/etc/pam.d/sudo" # Upewnij sie, ze uzytkownik pagan nie ma wygaszonego hasla (wazne dla autologin) chroot "$PAGAN_ROOT" chage -E -1 -m 0 -M 99999 pagan 2>/dev/null || true echo "pagan:changeme" | chroot "$PAGAN_ROOT" chpasswd 2>/dev/null || true # Autologin na tty1 (root) dla automatycznego startu instalatora mkdir -p "$PAGAN_ROOT/etc/systemd/system/getty@tty1.service.d" cat > "$PAGAN_ROOT/etc/systemd/system/getty@tty1.service.d/autologin.conf" <<'EOF' [Service] ExecStart= ExecStart=-/sbin/agetty --autologin root --noclear %I $TERM EOF # Autostart sesji live po zalogowaniu na tty1 (bash): startx → .xinitrc. # Instalator to Calamares (ikona „Zainstaluj Pagan Linux” na pulpicie). mkdir -p "$PAGAN_ROOT/etc/profile.d" rm -f "$PAGAN_ROOT/etc/profile.d/pagan-installer.sh" 2>/dev/null || true cat > "$PAGAN_ROOT/etc/profile.d/pagan-live.sh" <<'EOF' if [ "$(tty 2>/dev/null)" = "/dev/tty1" ] && command -v startx >/dev/null 2>&1; then if [ -n "${DISPLAY:-}${WAYLAND_DISPLAY:-}" ]; then return 0 2>/dev/null || true fi clear echo "PaganLinux – uruchamiam sesję live (startx)..." startx fi EOF chmod +x "$PAGAN_ROOT/etc/profile.d/pagan-live.sh" # /etc/profile – bash login shell ładuje TYLKO /etc/profile; bez niego profile.d # (m.in. pagan-live.sh) nigdy się nie wykona i live wita gołym bashem. if [[ ! -s "$PAGAN_ROOT/etc/profile" ]]; then cat > "$PAGAN_ROOT/etc/profile" <<'EOF' # /etc/profile – systemowe zmienne środowiskowe i programy startowe export PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin export HISTCONTROL=ignoredups export HISTSIZE=1000 export HISTFILESIZE=2000 if [ "$PS1" ]; then umask 022 fi # Ładuj skrypty z /etc/profile.d (kolejność alfabetyczna) for script in /etc/profile.d/*.sh ; do if [ -r "$script" ]; then . "$script" fi done unset script EOF echo "[fix] /etc/profile utworzony (ładuje /etc/profile.d/*.sh)" fi if [[ ! -s "$PAGAN_ROOT/etc/bashrc" ]]; then cat > "$PAGAN_ROOT/etc/bashrc" <<'EOF' # /etc/bashrc – interaktywne shelle nie-loginowe (aliasy/funkcje) if [ "$PS1" ]; then umask 022 fi EOF echo "[fix] /etc/bashrc utworzony" fi # DNS dla live: bez resolv.conf netinstall nie ruszy (curl nie rozwiąże nazw) if [[ ! -s "$PAGAN_ROOT/etc/resolv.conf" ]]; then cat > "$PAGAN_ROOT/etc/resolv.conf" <<'EOF' nameserver 1.1.1.1 nameserver 8.8.8.8 EOF echo "[fix] /etc/resolv.conf utworzony (fallback DNS)" fi # mkfs.vfat: dosfstools 4.2 bez --enable-compat-symlinks nie tworzy symlinku if [[ -x "$PAGAN_ROOT/usr/sbin/mkfs.fat" && ! -e "$PAGAN_ROOT/usr/sbin/mkfs.vfat" ]]; then ln -sf mkfs.fat "$PAGAN_ROOT/usr/sbin/mkfs.vfat" ln -sf mkfs.fat "$PAGAN_ROOT/usr/sbin/mkfs.msdos" echo "[fix] symlinki mkfs.vfat/mkfs.msdos utworzone" fi # Domyślny start do trybu TUI (multi-user.target) zamiast odpalania menedżera logowania chroot "$PAGAN_ROOT" systemctl set-default multi-user.target 2>/dev/null || true chroot "$PAGAN_ROOT" systemctl disable sddm 2>/dev/null || true # Uprawnienia sudo dla grupy wheel mkdir -p "$PAGAN_ROOT/etc/sudoers.d" echo "%wheel ALL=(ALL:ALL) ALL" > "$PAGAN_ROOT/etc/sudoers.d/wheel" chmod 440 "$PAGAN_ROOT/etc/sudoers.d/wheel" 2>/dev/null || true # TYMCZASOWA usługa diagnostyczna – zrzuca stan boota + RĘCZNIE odpala Xorga, # żeby zobaczyć stderr/log Xorga (sddm go połyka). Domyślnie WYŁĄCZONA – # włącza się tylko przez PAGAN_DIAG=1 ./fix-rootfs.sh. NIGDY nie powinna # trafić do ISO (opóźnia boot o 10 s i samowolnie startuje/zabija Xorga). if [[ "${PAGAN_DIAG:-0}" == "1" ]]; then cat > "$PAGAN_ROOT/etc/pagan-diag.sh" <<'EOF' #!/bin/sh sleep 10 echo "===== PAGAN DIAG V2 =====" echo "-- /run/dbus:"; ls -la /run/dbus 2>&1 echo "-- dri:"; ls -la /dev/dri 2>&1 echo "-- locale:"; locale -a 2>&1 echo "-- mount:"; mount 2>&1 | grep -E "overlay|squashfs|/ " | head echo "-- procs:"; pgrep -a dbus 2>&1; pgrep -a sddm 2>&1; pgrep -a X 2>&1 echo "-- Xorg perms:"; ls -la /usr/bin/Xorg 2>&1 echo "-- journal sddm:"; journalctl -b -u sddm --no-pager 2>&1 | tail -20 echo "-- dmesg tail:"; dmesg 2>&1 | tail -12 echo "=== RĘCZNY START Xorg ===" /usr/bin/X -nolisten tcp -background none -seat seat0 vt2 -noreset \ -logfile /tmp/xorg-diag.log -logverbose 3 >/tmp/xorg-stderr.log 2>&1 & XPID=$! sleep 8 kill $XPID 2>/dev/null wait $XPID 2>/dev/null echo "-- Xorg stderr:"; cat /tmp/xorg-stderr.log 2>&1 | head -40 echo "-- Xorg logfile:"; cat /tmp/xorg-diag.log 2>&1 | head -60 echo "===== END DIAG =====" EOF chmod +x "$PAGAN_ROOT/etc/pagan-diag.sh" cat > "$PAGAN_ROOT/etc/systemd/system/pagan-diag.service" <<'EOF' [Unit] Description=Pagan boot diagnostics (TYMCZASOWA) After=multi-user.target [Service] Type=oneshot ExecStart=/bin/sh /etc/pagan-diag.sh EOF mkdir -p "$PAGAN_ROOT/etc/systemd/system/multi-user.target.wants" ln -sf /usr/lib/systemd/system/pagan-diag.service \ "$PAGAN_ROOT/etc/systemd/system/multi-user.target.wants/pagan-diag.service" echo "[diag] PAGAN_DIAG=1 – usługa diagnostyczna WŁĄCZONA (pamiętaj o wyłączeniu przed ISO!)" else # Domyślnie: upewnij się, że po poprzednich diagnozach nic nie zostało rm -f "$PAGAN_ROOT/etc/systemd/system/multi-user.target.wants/pagan-diag.service" \ "$PAGAN_ROOT/etc/systemd/system/pagan-diag.service" "$PAGAN_ROOT/etc/pagan-diag.sh" fi echo "=== Odświeżam ld.so.cache ===" ldconfig -r "$PAGAN_ROOT" 2>/dev/null || echo "(ldconfig -r niekrytyczne)" echo "=== Weryfikacja w chroot ===" mount --rbind /dev "$PAGAN_ROOT/dev" 2>/dev/null || true mount --make-rslave "$PAGAN_ROOT/dev" 2>/dev/null || true mount -t proc proc "$PAGAN_ROOT/proc" 2>/dev/null || true mount -t sysfs sysfs "$PAGAN_ROOT/sys" 2>/dev/null || true mount -t tmpfs tmpfs "$PAGAN_ROOT/run" 2>/dev/null || true rc=0 for b in /usr/bin/dbus-daemon /usr/bin/Xorg /usr/bin/sddm /usr/bin/kwin_wayland \ /usr/bin/NetworkManager /usr/bin/agetty /usr/bin/modprobe; do if [[ ! -x "$PAGAN_ROOT$b" && ! -L "$PAGAN_ROOT$b" ]]; then echo "BRAK binarki: $b" rc=1 continue fi missing=$(chroot "$PAGAN_ROOT" /usr/bin/ldd "$b" 2>&1 | grep "not found" || true) if [[ -z "$missing" ]]; then echo "OK $b" else echo "BRAKUJĄCE LIBKI dla $b:" echo "$missing" rc=1 fi done if chroot "$PAGAN_ROOT" /usr/bin/ldd /usr/lib/libtiff.so.6 2>&1 | grep -q "libjpeg.so.62"; then echo "OK libtiff.so.6 → libjpeg.so.62" else echo "UWAGA: libtiff.so.6 nie widzi libjpeg.so.62" rc=1 fi umount -R "$PAGAN_ROOT/dev" 2>/dev/null || true umount "$PAGAN_ROOT/proc" 2>/dev/null || true umount "$PAGAN_ROOT/sys" 2>/dev/null || true umount -R "$PAGAN_ROOT/run" 2>/dev/null || true echo "" if [[ $rc -eq 0 ]]; then echo "✅ Rootfs naprawiony. Można budować ISO:" echo " cd /home/patryks/pagbuild && sudo ./build-pagan.sh --de kde --iso" else echo "⚠️ Weryfikacja wykazała problemy (patrz wyżej)." fi exit $rc