fix: prevent writing non-report output to stdout (#2324)

Signed-off-by: Keith Zantow <kzantow@gmail.com>
This commit is contained in:
Keith Zantow
2023-11-16 17:45:25 -05:00
committed by GitHub
parent c7eb3f4c93
commit 1c787f436f
13 changed files with 407 additions and 94 deletions
+61
View File
@@ -0,0 +1,61 @@
package ui
import (
"io"
"os"
"time"
"github.com/anchore/syft/internal/log"
)
// capture replaces the provided *os.File and redirects output to the provided writer. The return value is a function,
// which is used to stop the current capturing of output and restore the original file.
// Example:
//
// restore := capture(&os.Stderr, writer)
// // here, stderr will be captured and redirected to the provided writer
// restore() // block until the output has all been sent to the writer and restore the original stderr
func capture(target **os.File, writer io.Writer, bufSize int) (close func()) {
original := *target
r, w, _ := os.Pipe()
*target = w
done := make(chan struct{}, 1)
go func() {
defer func() {
done <- struct{}{}
}()
buf := make([]byte, bufSize)
for {
if original == nil {
break
}
n, err := r.Read(buf)
if n > 0 {
_, _ = writer.Write(buf[0:n])
}
if err != nil {
break
}
}
}()
return func() {
if original != nil {
_ = w.Close()
select {
case <-done:
case <-time.After(1 * time.Second):
log.Debugf("stdout buffer timed out after 1 second")
}
*target = original
original = nil
}
}
}