initial
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
package bsdaily
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func VerifyOutput(path string) error {
|
||||
slog.Info("running zstdmt integrity check")
|
||||
testCmd := exec.Command("zstdmt", "--test", path)
|
||||
var testStderr strings.Builder
|
||||
testCmd.Stderr = &testStderr
|
||||
if err := testCmd.Run(); err != nil {
|
||||
return fmt.Errorf("zstdmt --test failed: %w; stderr: %s", err, testStderr.String())
|
||||
}
|
||||
slog.Info("zstdmt integrity check passed")
|
||||
|
||||
slog.Info("verifying SQL content")
|
||||
catCmd := exec.Command("zstdcat", path)
|
||||
headCmd := exec.Command("head", "-20")
|
||||
|
||||
pipe, err := catCmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating zstdcat pipe: %w", err)
|
||||
}
|
||||
headCmd.Stdin = pipe
|
||||
|
||||
var headOut strings.Builder
|
||||
headCmd.Stdout = &headOut
|
||||
|
||||
if err := headCmd.Start(); err != nil {
|
||||
return fmt.Errorf("starting head: %w", err)
|
||||
}
|
||||
if err := catCmd.Start(); err != nil {
|
||||
return fmt.Errorf("starting zstdcat: %w", err)
|
||||
}
|
||||
|
||||
// head closes pipe early, zstdcat gets SIGPIPE - expected
|
||||
_ = headCmd.Wait()
|
||||
_ = catCmd.Wait()
|
||||
|
||||
content := headOut.String()
|
||||
if len(content) == 0 {
|
||||
return fmt.Errorf("decompressed content is empty")
|
||||
}
|
||||
|
||||
hasSQLMarker := false
|
||||
for _, marker := range []string{"BEGIN TRANSACTION", "CREATE TABLE", "INSERT INTO", "PRAGMA"} {
|
||||
if strings.Contains(content, marker) {
|
||||
hasSQLMarker = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !hasSQLMarker {
|
||||
return fmt.Errorf("decompressed content does not look like SQL; first 200 bytes: %s",
|
||||
content[:min(200, len(content))])
|
||||
}
|
||||
|
||||
slog.Info("SQL content verification passed")
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user