fix(backup): use platform private staging controls

This commit is contained in:
2026-08-18 07:39:51 +02:00
parent 4d230b87af
commit e20bf33e2a
4 changed files with 95 additions and 24 deletions
+3 -23
View File
@@ -20,6 +20,7 @@ import (
"strings"
"github.com/aritmolab/thothii/tools/tht/internal/config"
"github.com/aritmolab/thothii/tools/tht/internal/safeio"
)
var archiveDrivePath = regexp.MustCompile(`^[A-Za-z]:/`)
@@ -267,7 +268,7 @@ func (result PreflightResult) StageArchive(ctx context.Context) (_ *stagedArchiv
if result.stagingRoot == "" || result.freeBytes == nil {
return nil, errors.New("backup archive has no controlled staging reservation")
}
if err := ensurePrivateStagingRoot(result.stagingRoot); err != nil {
if err := safeio.EnsurePrivateDirectory(result.stagingRoot); err != nil {
return nil, fmt.Errorf("create private restore staging root: %w", err)
}
freeBytes, err := result.freeBytes(result.stagingRoot)
@@ -281,7 +282,7 @@ func (result PreflightResult) StageArchive(ctx context.Context) (_ *stagedArchiv
if err != nil {
return nil, errors.New("create private restore staging directory")
}
if err := os.Chmod(directory, 0o700); err != nil {
if err := safeio.ProtectPrivateDirectory(directory); err != nil {
_ = os.Remove(directory)
return nil, errors.New("protect private restore staging directory")
}
@@ -342,27 +343,6 @@ func (result PreflightResult) StageArchive(ctx context.Context) (_ *stagedArchiv
return staged, nil
}
func ensurePrivateStagingRoot(root string) error {
if !filepath.IsAbs(root) || filepath.Clean(root) != root {
return errors.New("restore staging root is invalid")
}
if err := os.Mkdir(root, 0o700); err != nil && !errors.Is(err, os.ErrExist) {
return errors.New("restore staging root is unavailable")
}
info, err := os.Lstat(root)
if err != nil || !info.IsDir() || info.Mode()&os.ModeSymlink != 0 {
return errors.New("restore staging root is unsafe")
}
if err := os.Chmod(root, 0o700); err != nil {
return errors.New("restore staging root cannot be protected")
}
info, err = os.Lstat(root)
if err != nil || !info.IsDir() || info.Mode()&os.ModeSymlink != 0 || info.Mode().Perm() != 0o700 {
return errors.New("restore staging root protection is invalid")
}
return nil
}
// Close removes only the staging file and directory created by StageArchive.
func (staged *stagedArchive) Close() error {
if staged == nil {