diff options
Diffstat (limited to 'pkg/image/fsck.go')
| -rw-r--r-- | pkg/image/fsck.go | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/pkg/image/fsck.go b/pkg/image/fsck.go new file mode 100644 index 000000000..4c619b828 --- /dev/null +++ b/pkg/image/fsck.go @@ -0,0 +1,59 @@ +// Copyright 2024 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package image + +import ( + "errors" + "fmt" + "io" + "os" + "os/exec" + "strconv" + "strings" + + "github.com/google/syzkaller/pkg/osutil" +) + +// Fsck runs fsckCmd against a file system image provided in r. It returns the +// fsck logs, whether the file system is clean and an error in case fsck could +// not be run. +func Fsck(r io.Reader, fsckCmd string) ([]byte, bool, error) { + // Write the image to a temporary file. + tempFile, err := os.CreateTemp("", "*.img") + if err != nil { + return nil, false, fmt.Errorf("failed to create temporary file: %w", err) + } + defer os.Remove(tempFile.Name()) + + _, err = io.Copy(tempFile, r) + if err != nil { + return nil, false, fmt.Errorf("failed to write data to temporary file: %w", err) + } + + if err := tempFile.Close(); err != nil { + return nil, false, fmt.Errorf("failed to close temporary file: %w", err) + } + + // And run the provided fsck command on it. + fsck := append(strings.Fields(fsckCmd), tempFile.Name()) + cmd := osutil.Command(fsck[0], fsck[1:]...) + if err := osutil.Sandbox(cmd, true, true); err != nil { + return nil, false, err + } + + exitCode := 0 + output, err := cmd.CombinedOutput() + if err != nil { + var exitError (*exec.ExitError) + ok := errors.As(err, &exitError) + if ok { + exitCode = exitError.ExitCode() + } else { + return nil, false, err + } + } + + prefix := fsckCmd + " exited with status code " + strconv.Itoa(exitCode) + "\n" + return append([]byte(prefix), output...), exitCode == 0, nil +} |
