105 lines
2.1 KiB
Go
105 lines
2.1 KiB
Go
package osimage
|
|
|
|
import (
|
|
"context"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
func VerifyTargetSHA256(ctx context.Context, targetPath string, expectedSize int64,
|
|
bufferSize int, progress ProgressFunc) (string, error) {
|
|
if targetPath == "" {
|
|
return "", fmt.Errorf("target path is required")
|
|
}
|
|
if expectedSize <= 0 {
|
|
return "", fmt.Errorf("expected raw size is required for verification")
|
|
}
|
|
if bufferSize <= 0 {
|
|
bufferSize = 4 * 1024 * 1024
|
|
}
|
|
|
|
f, err := os.Open(targetPath)
|
|
if err != nil {
|
|
return "", fmt.Errorf("open target for verify: %w", err)
|
|
}
|
|
defer f.Close()
|
|
|
|
h := sha256.New()
|
|
buf := make([]byte, bufferSize)
|
|
|
|
var readTotal int64
|
|
limited := io.LimitReader(f, expectedSize)
|
|
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return "", ctx.Err()
|
|
default:
|
|
}
|
|
|
|
n, err := limited.Read(buf)
|
|
if n > 0 {
|
|
if _, werr := h.Write(buf[:n]); werr != nil {
|
|
return "", fmt.Errorf("hash target: %w", werr)
|
|
}
|
|
readTotal += int64(n)
|
|
if progress != nil {
|
|
progress(Progress{
|
|
Stage: "verify",
|
|
BytesComplete: readTotal,
|
|
BytesTotal: expectedSize,
|
|
})
|
|
}
|
|
}
|
|
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
return "", fmt.Errorf("read target: %w", err)
|
|
}
|
|
}
|
|
|
|
if readTotal != expectedSize {
|
|
return "", fmt.Errorf("verify size mismatch: got %d want %d", readTotal, expectedSize)
|
|
}
|
|
|
|
return hex.EncodeToString(h.Sum(nil)), nil
|
|
}
|
|
|
|
func ValidateApplyOptions(opts ApplyOptions) error {
|
|
if opts.URL == "" {
|
|
return fmt.Errorf("url is required")
|
|
}
|
|
if opts.TargetPath == "" {
|
|
return fmt.Errorf("target path is required")
|
|
}
|
|
if opts.ExpectedRawSHA256 == "" {
|
|
return fmt.Errorf("expected raw sha256 is required")
|
|
}
|
|
if opts.ExpectedRawSize <= 0 {
|
|
return fmt.Errorf("expected raw size must be > 0")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func VerifySHA256(got, expected string) error {
|
|
expected = NormalizeSHA256(expected)
|
|
if expected == "" {
|
|
return nil
|
|
}
|
|
got = NormalizeSHA256(got)
|
|
if got != expected {
|
|
return fmt.Errorf("sha256 mismatch: got %s want %s", got, expected)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func NormalizeSHA256(s string) string {
|
|
return strings.ToLower(strings.TrimSpace(s))
|
|
}
|