blob: c52786774c57d32d86884e04d4277f8adef24a0a [file] [log] [blame]
// Copyright 2022 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 database
import (
"path/filepath"
"golang.org/x/exp/maps"
"golang.org/x/vuln/client"
"golang.org/x/vuln/osv"
"golang.org/x/vulndb/internal/derrors"
"golang.org/x/vulndb/internal/report"
)
// Load reads the contents of dbPath into a Database, and errors
// if the database has missing files (based on the module and ID indexes).
func Load(dbPath string) (_ *Database, err error) {
defer derrors.Wrap(&err, "Load(%q)", dbPath)
d := &Database{
Index: make(client.DBIndex),
IDsByAlias: make(IDsByAlias),
}
if err := report.UnmarshalFromFile(filepath.Join(dbPath, indexFile), &d.Index); err != nil {
return nil, err
}
d.EntriesByModule, err = loadEntriesByModule(dbPath, d.Index)
if err != nil {
return nil, err
}
d.EntriesByID, err = loadEntriesByID(dbPath)
if err != nil {
return nil, err
}
if err := report.UnmarshalFromFile(filepath.Join(dbPath, aliasesFile), &d.IDsByAlias); err != nil {
return nil, err
}
return d, nil
}
func loadEntriesByID(dbPath string) (EntriesByID, error) {
var ids []string
if err := report.UnmarshalFromFile(filepath.Join(dbPath, idDirectory, indexFile), &ids); err != nil {
return nil, err
}
entriesByID := make(EntriesByID, len(ids))
for _, id := range ids {
var entry osv.Entry
err := report.UnmarshalFromFile(filepath.Join(dbPath, idDirectory, id+".json"), &entry)
if err != nil {
return nil, err
}
entriesByID[id] = &entry
}
return entriesByID, nil
}
func loadEntriesByModule(dbPath string, index client.DBIndex) (EntriesByModule, error) {
entriesByModule := make(EntriesByModule, len(index))
for _, module := range maps.Keys(index) {
emodule, err := client.EscapeModulePath(module)
if err != nil {
return nil, err
}
fpath := filepath.Join(dbPath, emodule+".json")
var entries []*osv.Entry
err = report.UnmarshalFromFile(fpath, &entries)
if err != nil {
return nil, err
}
entriesByModule[module] = entries
}
return entriesByModule, nil
}