gopls/internal/vulncheck: copy x/vuln/cmd/govulncheck/cache.go

This is a utility that manages vulnerability information
local cache.

Updates golang/vscode-go#2096
Updates golang/go#50577

Change-Id: I1903a529adda499d078156c3f1ba38bfab75a958
Reviewed-on: https://go-review.googlesource.com/c/tools/+/395574
Trust: Hyang-Ah Hana Kim <hyangah@gmail.com>
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
This commit is contained in:
Hana 2022-03-24 10:56:22 -04:00 committed by Hyang-Ah Hana Kim
parent 9fd677e179
commit 4460e9bc64
1 changed files with 124 additions and 0 deletions

View File

@ -0,0 +1,124 @@
// Copyright 2021 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 vulncheck
import (
"encoding/json"
"go/build"
"io/ioutil"
"os"
"path/filepath"
"time"
"golang.org/x/vuln/client"
"golang.org/x/vuln/osv"
)
// copy from x/vuln/cmd/govulncheck/cache.go
// NOTE: this cache implementation should be kept internal to the go tooling
// (i.e. cmd/go/internal/something) so that the vulndb cache is owned by the
// go command. Also it is currently NOT CONCURRENCY SAFE since it does not
// implement file locking. If ported to the stdlib it should use
// cmd/go/internal/lockedfile.
// The cache uses a single JSON index file for each vulnerability database
// which contains the map from packages to the time the last
// vulnerability for that package was added/modified and the time that
// the index was retrieved from the vulnerability database. The JSON
// format is as follows:
//
// $GOPATH/pkg/mod/cache/download/vulndb/{db hostname}/indexes/index.json
// {
// Retrieved time.Time
// Index client.DBIndex
// }
//
// Each package also has a JSON file which contains the array of vulnerability
// entries for the package. The JSON format is as follows:
//
// $GOPATH/pkg/mod/cache/download/vulndb/{db hostname}/{import path}/vulns.json
// []*osv.Entry
// fsCache is file-system cache implementing osv.Cache
// TODO: make cache thread-safe
type fsCache struct {
rootDir string
}
// use cfg.GOMODCACHE available in cmd/go/internal?
var defaultCacheRoot = filepath.Join(build.Default.GOPATH, "/pkg/mod/cache/download/vulndb")
func defaultCache() *fsCache {
return &fsCache{rootDir: defaultCacheRoot}
}
type cachedIndex struct {
Retrieved time.Time
Index client.DBIndex
}
func (c *fsCache) ReadIndex(dbName string) (client.DBIndex, time.Time, error) {
b, err := ioutil.ReadFile(filepath.Join(c.rootDir, dbName, "index.json"))
if err != nil {
if os.IsNotExist(err) {
return nil, time.Time{}, nil
}
return nil, time.Time{}, err
}
var index cachedIndex
if err := json.Unmarshal(b, &index); err != nil {
return nil, time.Time{}, err
}
return index.Index, index.Retrieved, nil
}
func (c *fsCache) WriteIndex(dbName string, index client.DBIndex, retrieved time.Time) error {
path := filepath.Join(c.rootDir, dbName)
if err := os.MkdirAll(path, 0755); err != nil {
return err
}
j, err := json.Marshal(cachedIndex{
Index: index,
Retrieved: retrieved,
})
if err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(path, "index.json"), j, 0666); err != nil {
return err
}
return nil
}
func (c *fsCache) ReadEntries(dbName string, p string) ([]*osv.Entry, error) {
b, err := ioutil.ReadFile(filepath.Join(c.rootDir, dbName, p, "vulns.json"))
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
var entries []*osv.Entry
if err := json.Unmarshal(b, &entries); err != nil {
return nil, err
}
return entries, nil
}
func (c *fsCache) WriteEntries(dbName string, p string, entries []*osv.Entry) error {
path := filepath.Join(c.rootDir, dbName, p)
if err := os.MkdirAll(path, 0777); err != nil {
return err
}
j, err := json.Marshal(entries)
if err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(path, "vulns.json"), j, 0666); err != nil {
return err
}
return nil
}