Files
Lemon-miaow 109701a276 fix(ci): 修正分布式实现的 staticcheck 错误
迁移 CLI 不再遮蔽 BeginMigration 的错误,拒绝启动时正确返回失败。规范节点批准错误文案和归档 HTTP 状态常量;tar.Reader 已将旧普通文件类型归一化,无需引用已弃用常量。

验证:CI 固定版本 staticcheck 全量通过;cmd/felis、archivetransfer、backup、distributed 的 go test -race 通过。
2026-10-01 20:06:08 +08:00

70 lines
1.4 KiB
Go

package backup
import (
"archive/tar"
"compress/gzip"
"context"
"crypto/sha256"
"errors"
"fmt"
"io"
"os"
)
// VerifyRestored reads target files back and compares them with every regular archive entry.
// OpenRoot keeps a malicious path or existing symlink inside the world volume.
func VerifyRestored(ctx context.Context, ref, world string) error {
root, err := os.OpenRoot(world)
if err != nil {
return err
}
defer root.Close()
f, err := os.Open(ref)
if err != nil {
return err
}
defer f.Close()
gz, err := gzip.NewReader(f)
if err != nil {
return err
}
defer gz.Close()
tr := tar.NewReader(gz)
for {
if err := ctx.Err(); err != nil {
return err
}
h, err := tr.Next()
if errors.Is(err, io.EOF) {
return nil
}
if err != nil {
return err
}
if h.Typeflag != tar.TypeReg {
continue
}
dst, err := root.Open(h.Name)
if err != nil {
return err
}
st, err := dst.Stat()
if err != nil || !st.Mode().IsRegular() || st.Size() != h.Size {
dst.Close()
return fmt.Errorf("restored entry %q has the wrong type or size", h.Name)
}
sourceHash, targetHash := sha256.New(), sha256.New()
_, err = io.Copy(sourceHash, tr)
if err == nil {
_, err = io.Copy(targetHash, dst)
}
dst.Close()
if err != nil {
return err
}
if string(sourceHash.Sum(nil)) != string(targetHash.Sum(nil)) {
return fmt.Errorf("restored entry %q failed SHA-256 read-back", h.Name)
}
}
}