//go:build windows package backup import ( "os" "path/filepath" "github.com/aritmolab/thothii/tools/tht/internal/safeio" ) // replaceRestoreFile deliberately supports only owner-private Windows parents. The retained // native directory handle pins every ancestor, rejects reparse components, creates an owner-only // temporary file, and publishes it by an NT RootDirectory-relative atomic rename. Installations // whose restore targets do not satisfy that custody contract fail closed instead of falling back // to a path-based replacement. func replaceRestoreFile(target string, contents []byte, mode os.FileMode) (resultErr error) { if safeio.ValidateCanonicalPath(target) != nil || mode&os.ModeType != 0 || mode.Perm() == 0 || len(contents) == 0 { return safeio.ErrUnsafeFile } parent, found, err := safeio.OpenPrivateDirectory(filepath.Dir(target), false) if err != nil || !found || parent == nil { return safeio.ErrUnsafeFile } defer func() { if closeErr := parent.Close(); closeErr != nil { resultErr = safeio.ErrUnsafeFile } }() safeio.NotifyPrivateDirectoryTestHookForTest("after-restore-parent-open") if parent.Validate() != nil { return safeio.ErrUnsafeFile } created, err := parent.CreateRegular(filepath.Base(target), contents) if err != nil { return safeio.ErrUnsafeFile } if !created { if err := parent.ReplaceRegular(filepath.Base(target), contents); err != nil { return safeio.ErrUnsafeFile } } if parent.Validate() != nil { return safeio.ErrUnsafeFile } return nil }