//go:build !windows package backup import ( "os" "path/filepath" "syscall" "testing" ) const restoreRuntimeUID = 10001 func TestReplaceRestoreFilePreservesExistingOwner(t *testing.T) { requireRootForRestoreOwnershipTest(t) target := filepath.Join(t.TempDir(), "trust.json") if err := os.WriteFile(target, []byte("before"), 0o600); err != nil { t.Fatal(err) } if err := os.Chown(target, restoreRuntimeUID, restoreRuntimeUID); err != nil { t.Fatal(err) } if err := replaceRestoreFile(target, []byte("after"), 0o600); err != nil { t.Fatal(err) } assertRestoreOwner(t, target, restoreRuntimeUID, restoreRuntimeUID) } func TestReplaceRestoreFileUsesParentOwnerForNewTarget(t *testing.T) { requireRootForRestoreOwnershipTest(t) parent := filepath.Join(t.TempDir(), "agent") if err := os.Mkdir(parent, 0o700); err != nil { t.Fatal(err) } if err := os.Chown(parent, restoreRuntimeUID, restoreRuntimeUID); err != nil { t.Fatal(err) } target := filepath.Join(parent, "trust.json") if err := replaceRestoreFile(target, []byte("restored"), 0o600); err != nil { t.Fatal(err) } assertRestoreOwner(t, target, restoreRuntimeUID, restoreRuntimeUID) } func requireRootForRestoreOwnershipTest(t *testing.T) { t.Helper() if os.Geteuid() != 0 { t.Skip("numeric ownership assertions require root") } } func assertRestoreOwner(t *testing.T, path string, uid, gid uint32) { t.Helper() info, err := os.Stat(path) if err != nil { t.Fatal(err) } status, ok := info.Sys().(*syscall.Stat_t) if !ok { t.Fatal("restored file has no Unix stat metadata") } if status.Uid != uid || status.Gid != gid { t.Fatalf("restored owner = %d:%d, want %d:%d", status.Uid, status.Gid, uid, gid) } }