| // Copyright 2024 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package main |
| |
| import ( |
| "bytes" |
| "context" |
| "encoding/json" |
| "os" |
| "path/filepath" |
| "time" |
| |
| "golang.org/x/vulndb/cmd/vulnreport/log" |
| "golang.org/x/vulndb/internal/cve5" |
| ) |
| |
| type fileWriter struct{ wfs } |
| |
| func (f *fileWriter) setup(_ context.Context, env environment) error { |
| f.wfs = env.WFS() |
| return nil |
| } |
| |
| func (f *fileWriter) write(r *yamlReport) error { |
| w := bytes.NewBuffer(make([]byte, 0)) |
| if err := r.Encode(w); err != nil { |
| return err |
| } |
| modified, err := f.WriteFile(r.Filename, w.Bytes()) |
| if err != nil { |
| return err |
| } |
| return ok(r.Filename, modified) |
| } |
| |
| func (f *fileWriter) writeOSV(r *yamlReport) error { |
| if r.IsExcluded() { |
| return nil |
| } |
| |
| entry, err := r.ToOSV(time.Time{}) |
| if err != nil { |
| return err |
| } |
| |
| return writeJSON(f, r.OSVFilename(), entry) |
| } |
| |
| func (f *fileWriter) writeCVE(r *yamlReport) error { |
| if r.CVEMetadata == nil { |
| return nil |
| } |
| |
| cve, err := cve5.FromReport(r.Report) |
| if err != nil { |
| return err |
| } |
| return writeJSON(f, r.CVEFilename(), cve) |
| } |
| |
| func (f *fileWriter) writeDerived(r *yamlReport) error { |
| if err := f.writeOSV(r); err != nil { |
| return err |
| } |
| return f.writeCVE(r) |
| } |
| |
| func writeJSON(wfs wfs, fname string, v any) error { |
| j, err := json.MarshalIndent(v, "", " ") |
| if err != nil { |
| return err |
| } |
| modified, err := wfs.WriteFile(fname, j) |
| if err != nil { |
| return err |
| } |
| return ok(fname, modified) |
| } |
| |
| func ok(fname string, modified bool) error { |
| if modified { |
| log.Out(filepath.ToSlash(fname)) |
| } |
| return nil |
| } |
| |
| // a simple representation of a writeable file system |
| type wfs interface { |
| WriteFile(string, []byte) (bool, error) |
| } |
| |
| type defaultWFS struct{} |
| |
| var _ wfs = &defaultWFS{} |
| |
| func (defaultWFS) WriteFile(filename string, b []byte) (bool, error) { |
| // writing the file would not change its contents |
| if existing, err := os.ReadFile(filename); err == nil && bytes.Equal(existing, b) { |
| return false, nil |
| } |
| return true, os.WriteFile(filename, b, 0644) |
| } |