Review round 2: a media restart no longer starts an app the household stopped (R-721); the file manager's header name file appears whole (R-1100 race, 44/300 -> 0/300); both red-proved; unreleased
gates / gates (push) Successful in 1m22s

This commit is contained in:
2026-10-24 15:26:56 +02:00
parent 321df1f87a
commit b01bb4b88d
8 changed files with 163 additions and 31 deletions
+24 -10
View File
@@ -64,22 +64,36 @@ func LoadOrCreateFileBrowserSSOHeader(dataDir string) (string, error) {
return "", err
}
h := "X-Felhom-User-" + hex.EncodeToString(rb)
f, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o600)
// The name file appears WHOLE or not at all (review round 2, 2026-10-24): it is written to a private temp file
// first and then hard-linked into place — the link is the exclusive create, so a second writer never reads an
// empty, half-written file (measured: 44 of 300 runs of the parallel-writers check read "" with the old
// create-then-write; pinned by TestFileBrowserSSOHeader_R1100_ABoxSecret).
tmp, err := os.CreateTemp(dataDir, fileBrowserSSOHeaderFile+".tmp-*")
if err != nil {
return "", err
}
defer os.Remove(tmp.Name())
if err := tmp.Chmod(0o600); err != nil {
tmp.Close()
return "", err
}
if _, err := tmp.WriteString(h + "\n"); err != nil {
tmp.Close()
return "", err
}
if err := tmp.Sync(); err != nil {
tmp.Close()
return "", err
}
if err := tmp.Close(); err != nil {
return "", err
}
if err := os.Link(tmp.Name(), p); err != nil {
if os.IsExist(err) {
return LoadOrCreateFileBrowserSSOHeader(dataDir)
}
return "", err
}
if _, err := f.WriteString(h + "\n"); err != nil {
f.Close()
_ = os.Remove(p)
return "", err
}
if err := f.Close(); err != nil {
_ = os.Remove(p)
return "", err
}
return h, nil
}