Harden backup and restore operations

This commit is contained in:
Mikei386
2026-07-13 19:47:43 +02:00
parent 6cbf170d65
commit bbf063c157
26 changed files with 914 additions and 184 deletions
+38 -4
View File
@@ -23,6 +23,18 @@ type Runner struct {
processes map[string]*os.Process
}
func (r *Runner) SetBinary(path string) {
r.mu.Lock()
r.Binary = path
r.mu.Unlock()
}
func (r *Runner) binary() string {
r.mu.Lock()
defer r.mu.Unlock()
return r.Binary
}
type Progress struct {
Percent float64
Bytes int64
@@ -43,7 +55,7 @@ var (
func (r *Runner) Run(ctx context.Context, runID string, job model.Job, callback func(Progress)) (Summary, error) {
args := Arguments(job)
cmd := exec.CommandContext(ctx, r.Binary, args...)
cmd := exec.CommandContext(ctx, r.binary(), args...)
cmd.Env = append(os.Environ(), "LC_ALL=C", "LANG=C")
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
cmd.Cancel = func() error {
@@ -92,9 +104,11 @@ func (r *Runner) Run(ctx context.Context, runID string, job model.Job, callback
})
close(done)
}()
errBytes, _ := io.ReadAll(io.LimitReader(stderr, 1024*1024))
stderrDone := make(chan []byte, 1)
go func() { stderrDone <- drainLimited(stderr, 1024*1024) }()
err = cmd.Wait()
<-done
errBytes := <-stderrDone
if err != nil {
if errors.Is(ctx.Err(), context.Canceled) {
return Summary{}, fmt.Errorf("cancelled: %w", ctx.Err())
@@ -117,7 +131,7 @@ func (r *Runner) Estimate(ctx context.Context, runID string, job model.Job) (Sum
args[index] = "--out-format="
}
}
cmd := exec.CommandContext(ctx, r.Binary, args...)
cmd := exec.CommandContext(ctx, r.binary(), args...)
cmd.Env = append(os.Environ(), "LC_ALL=C", "LANG=C")
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
cmd.Cancel = func() error {
@@ -158,9 +172,11 @@ func (r *Runner) Estimate(ctx context.Context, runID string, job model.Job) (Sum
})
close(done)
}()
errBytes, _ := io.ReadAll(io.LimitReader(stderr, 1024*1024))
stderrDone := make(chan []byte, 1)
go func() { stderrDone <- drainLimited(stderr, 1024*1024) }()
err = cmd.Wait()
<-done
errBytes := <-stderrDone
if err != nil {
if errors.Is(ctx.Err(), context.Canceled) {
return Summary{}, fmt.Errorf("cancelled: %w", ctx.Err())
@@ -258,6 +274,24 @@ func scanOutput(reader io.Reader, callback func(string)) {
}
}
func drainLimited(reader io.Reader, limit int) []byte {
result := make([]byte, 0, limit)
buffer := make([]byte, 32*1024)
for {
count, err := reader.Read(buffer)
if count > 0 && len(result) < limit {
keep := count
if keep > limit-len(result) {
keep = limit - len(result)
}
result = append(result, buffer[:keep]...)
}
if err != nil {
return result
}
}
}
func splitLinesAndCarriageReturns(data []byte, atEOF bool) (advance int, token []byte, err error) {
for i, value := range data {
if value == '\n' || value == '\r' {