From 885c290cf2a8d31c28e3c3ae004cfc247c23b3e8 Mon Sep 17 00:00:00 2001 From: Ethan Lowman <53835328+ethan-lowman-dd@users.noreply.github.com> Date: Wed, 9 Mar 2022 11:10:56 -0500 Subject: [PATCH] [Delegations prereq 9] Make fileSystemStore.GetMeta read metadata files dynamically (#231) * [Delegations prereq] Use a verify.DB for delegation in client Splitting up https://github.com/theupdateframework/go-tuf/pull/175 * stash * Add tests to make sure the top level targets 'delegation' edge has associated keys. Make NewDelegationsIterator return an error if the passed DB is missing the top level targets role * [Delegations prereq] Make signers addressible by key ID in LocalStore Splitting up https://github.com/theupdateframework/go-tuf/pull/175 * Clarify naming * Add local_store_test.go * Another test case * [Delegations prereq] Use a verify.DB for delegation in client Splitting up https://github.com/theupdateframework/go-tuf/pull/175 * stash * Add tests to make sure the top level targets 'delegation' edge has associated keys. Make NewDelegationsIterator return an error if the passed DB is missing the top level targets role * [Delegations prereq 9] Make fileSystemStore.GetMeta read metadata files dynamically --- local_store.go | 72 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 58 insertions(+), 14 deletions(-) diff --git a/local_store.go b/local_store.go index bd1175b6..86eceefd 100644 --- a/local_store.go +++ b/local_store.go @@ -3,8 +3,10 @@ package tuf import ( "bytes" "encoding/json" + "errors" "fmt" "io" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -12,6 +14,7 @@ import ( "github.com/theupdateframework/go-tuf/data" "github.com/theupdateframework/go-tuf/encrypted" + "github.com/theupdateframework/go-tuf/internal/roles" "github.com/theupdateframework/go-tuf/internal/sets" "github.com/theupdateframework/go-tuf/pkg/keys" "github.com/theupdateframework/go-tuf/util" @@ -218,25 +221,66 @@ func (f *fileSystemStore) stagedDir() string { return filepath.Join(f.dir, "staged") } +func isMetaFile(e os.DirEntry) (bool, error) { + name := e.Name() + if e.IsDir() || !(filepath.Ext(name) == ".json" && roles.IsTopLevelManifest(name)) { + return false, nil + } + + info, err := e.Info() + if err != nil { + return false, err + } + + return info.Mode().IsRegular(), nil +} + func (f *fileSystemStore) GetMeta() (map[string]json.RawMessage, error) { - meta := make(map[string]json.RawMessage) - var err error - notExists := func(path string) bool { - _, err := os.Stat(path) - return os.IsNotExist(err) - } - for _, name := range topLevelMetadata { - path := filepath.Join(f.stagedDir(), name) - if notExists(path) { - path = filepath.Join(f.repoDir(), name) - if notExists(path) { - continue - } + // Build a map of metadata names (e.g. root.json) to their full paths + // (whether in the committed repo dir, or in the staged repo dir). + metaPaths := map[string]string{} + + rd := f.repoDir() + committed, err := os.ReadDir(f.repoDir()) + if err != nil && !errors.Is(err, fs.ErrNotExist) { + return nil, fmt.Errorf("could not list repo dir: %w", err) + } + + for _, e := range committed { + imf, err := isMetaFile(e) + if err != nil { + return nil, err + } + if imf { + name := e.Name() + metaPaths[name] = filepath.Join(rd, name) } - meta[name], err = ioutil.ReadFile(path) + } + + sd := f.stagedDir() + staged, err := os.ReadDir(sd) + if err != nil && !errors.Is(err, fs.ErrNotExist) { + return nil, fmt.Errorf("could not list staged dir: %w", err) + } + + for _, e := range staged { + imf, err := isMetaFile(e) + if err != nil { + return nil, err + } + if imf { + name := e.Name() + metaPaths[name] = filepath.Join(sd, name) + } + } + + meta := make(map[string]json.RawMessage) + for name, path := range metaPaths { + f, err := ioutil.ReadFile(path) if err != nil { return nil, err } + meta[name] = f } return meta, nil }