Skip to content

Commit 926c380

Browse files
castrojoCopilot
andcommitted
fix(bluefin): migrate legacy home paths for GNOME Trash
Rewrite persistent /var/home home fields to the bind-mounted /home layout before desktop services start, preventing GNOME path-based Trash operations from resolving inconsistently. Closes #1184 Assisted-by: GPT-5.6 Luna via GitHub Copilot Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 3ebbe02 commit 926c380

5 files changed

Lines changed: 134 additions & 0 deletions

File tree

docs/skills/actionadon.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,13 @@ Implications for agents:
9494
- [ ] Only queued work was claimed
9595
- [ ] No comments duplicated existing widget state
9696
- [ ] Hardware confirmation state was considered before treating the loop as closed
97+
98+
## Lessons Learned
99+
100+
### Legacy passwd home paths can break GNOME file operations (2026-07-31)
101+
102+
When Dakota changed `/home` from a symlink into a bind mount, upgrades could
103+
retain `/var/home/<user>` in `/etc/passwd`. That stale path can make GNOME
104+
path-based operations such as sending files to Trash resolve inconsistently.
105+
The boot-time migration must rewrite those fields to `/home/<user>` before user
106+
sessions and desktop services start.

elements/bluefin/deps.bst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ depends:
6565
- gnome-build-meta.bst:gnomeos-deps/wl-clipboard.bst
6666

6767
- bluefin/bindmounts.bst
68+
- bluefin/migrate-var-home-passwd.bst
6869

6970
- gnome-build-meta.bst:gnomeos-deps/snapd.bst
7071

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
kind: manual
2+
description: |
3+
One-shot, idempotent boot-time migration of legacy /var/home/<user> (and
4+
/var/roothome) passwd home fields to the post-#1117 bind-mount layout.
5+
Installs from before 2026-06-29 carry the old fields, which breaks snapd
6+
and makes path-identity comparisons disagree, which can break GNOME file
7+
operations such as sending files to Trash; see projectbluefin/dakota#1184.
8+
9+
Ships the migration script, its oneshot unit (ordered before
10+
systemd-user-sessions), and a preset to enable it.
11+
12+
sources:
13+
- kind: local
14+
path: files/migrate-var-home-passwd
15+
16+
build-depends:
17+
- freedesktop-sdk.bst:public-stacks/runtime-minimal.bst
18+
19+
variables:
20+
strip-binaries: ""
21+
22+
config:
23+
install-commands:
24+
- |
25+
install -Dm755 bluefin-migrate-var-home-passwd \
26+
"%{install-root}/usr/libexec/bluefin-migrate-var-home-passwd"
27+
- |
28+
install -Dm644 bluefin-migrate-var-home-passwd.service \
29+
"%{install-root}%{indep-libdir}/systemd/system/bluefin-migrate-var-home-passwd.service"
30+
- |
31+
PRESET="%{install-root}%{indep-libdir}/systemd/system-preset/80-bluefin-migrate-var-home-passwd.preset"
32+
install -Dm644 /dev/null "$PRESET"
33+
cat > "$PRESET" <<'PRESET'
34+
enable bluefin-migrate-var-home-passwd.service
35+
PRESET
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/usr/bin/bash
2+
# One-shot migration of legacy home fields in /etc/passwd: /var/home/<user>
3+
# -> /home/<user>, /var/roothome -> /root. Installs from before PR #1117
4+
# (2026-06-29) carry the old-layout fields, which breaks snapd and makes
5+
# bind-mount path-identity comparisons disagree. Full background:
6+
# projectbluefin/dakota#1170.
7+
#
8+
# The write is delegated to usermod (no -m: passwd field only, no data
9+
# moves) so locking and atomic replace are the canonical lckpwdf ones;
10+
# flock(2) would not interoperate. Deliberately no sentinel file: the grep
11+
# fast path is cheap and self-heals if a stale entry is ever reintroduced.
12+
#
13+
# MIGRATE_PREFIX=/some/dir operates on $MIGRATE_PREFIX/etc/passwd (passed
14+
# to usermod --prefix); tests only, leave unset in production.
15+
16+
set -euo pipefail
17+
18+
PREFIX="${MIGRATE_PREFIX:-}"
19+
PASSWD="${PREFIX}/etc/passwd"
20+
21+
log() { echo "bluefin-migrate-var-home-passwd: $*"; }
22+
23+
if [ ! -r "$PASSWD" ]; then
24+
log "no readable $PASSWD; nothing to do"
25+
exit 0
26+
fi
27+
28+
# Nothing to migrate -> exit before taking any lock.
29+
if ! grep -qE ':(/var/home/|/var/roothome)(:|$)' "$PASSWD"; then
30+
exit 0
31+
fi
32+
33+
declare -a UARGS=()
34+
[ -n "$PREFIX" ] && UARGS+=(--prefix "$PREFIX")
35+
36+
rc=0
37+
migrated=0
38+
39+
# The loop holds the original inode open while usermod renames in new ones,
40+
# so every decision is made against a consistent pre-migration snapshot.
41+
while IFS=: read -r login _ _ _ _ home _; do
42+
[ -n "$login" ] || continue
43+
case "$home" in
44+
/var/roothome)
45+
new="/root"
46+
;;
47+
/var/home/*)
48+
new="/home/${home#/var/home/}"
49+
;;
50+
*)
51+
continue
52+
;;
53+
esac
54+
55+
set +e
56+
usermod "${UARGS[@]}" -d "$new" "$login"
57+
uc=$?
58+
set -e
59+
if [ "$uc" -eq 0 ]; then
60+
log "migrated $login: $home -> $new"
61+
migrated=$((migrated + 1))
62+
else
63+
log "FAILED to migrate $login: $home -> $new (usermod rc=$uc)"
64+
rc=1
65+
fi
66+
done < "$PASSWD"
67+
68+
log "done; migrated ${migrated} user(s)"
69+
exit "$rc"
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[Unit]
2+
Description=Migrate legacy /var/home home paths in /etc/passwd to /home
3+
Documentation=https://github.com/projectbluefin/dakota/issues/1170
4+
After=local-fs.target
5+
# Must rewrite passwd before anything reads it for a session:
6+
# systemd-user-sessions gates all logins, accounts-daemon caches home fields.
7+
Before=systemd-user-sessions.service
8+
Before=accounts-daemon.service
9+
Before=display-manager.service
10+
Before=gdm.service
11+
ConditionPathExists=/etc/passwd
12+
13+
[Service]
14+
Type=oneshot
15+
RemainAfterExit=yes
16+
ExecStart=/usr/libexec/bluefin-migrate-var-home-passwd
17+
18+
[Install]
19+
WantedBy=multi-user.target

0 commit comments

Comments
 (0)