diff --git a/client/leveldbstore/leveldbstore.go b/client/leveldbstore/leveldbstore.go index 578023ab..d9390494 100644 --- a/client/leveldbstore/leveldbstore.go +++ b/client/leveldbstore/leveldbstore.go @@ -4,6 +4,7 @@ import ( "encoding/json" "github.com/syndtr/goleveldb/leveldb" + "github.com/syndtr/goleveldb/leveldb/errors" "github.com/syndtr/goleveldb/leveldb/storage" tuf_client "github.com/theupdateframework/go-tuf/client" @@ -16,6 +17,10 @@ func FileLocalStore(path string) (tuf_client.LocalStore, error) { } db, err := leveldb.Open(fd, nil) + if err != nil && errors.IsCorrupted(err) { + db, err = leveldb.Recover(fd, nil) + } + return &fileLocalStore{fd: fd, db: db}, err } diff --git a/client/leveldbstore/leveldbstore_test.go b/client/leveldbstore/leveldbstore_test.go index 1a11cb32..5d29fff5 100644 --- a/client/leveldbstore/leveldbstore_test.go +++ b/client/leveldbstore/leveldbstore_test.go @@ -6,6 +6,7 @@ import ( "testing" . "gopkg.in/check.v1" + "os" ) type LocalStoreSuite struct{} @@ -81,3 +82,42 @@ func (LocalStoreSuite) TestDeleteMeta(c *C) { c.Fatalf("Metadata is not deleted!") } } + +func (LocalStoreSuite) TestCorruptManifest(c *C) { + tmp := c.MkDir() + path := filepath.Join(tmp, "tuf.db") + + store, err := FileLocalStore(path) + c.Assert(err, IsNil) + + // now break the manifest file + err = os.Truncate(filepath.Join(path, "MANIFEST-000000"), 1) + c.Assert(err, IsNil) + err = store.Close() + c.Assert(err, IsNil) + + store, err = FileLocalStore(path) + c.Assert(err, IsNil) + + type meta map[string]json.RawMessage + + assertGet := func(expected meta) { + actual, err := store.GetMeta() + c.Assert(err, IsNil) + c.Assert(meta(actual), DeepEquals, expected) + } + + // initial GetMeta should return empty meta + assertGet(meta{}) + + // SetMeta should persist + rootJSON := []byte(`{"_type":"Root"}`) + c.Assert(store.SetMeta("root.json", rootJSON), IsNil) + assertGet(meta{"root.json": rootJSON}) + + store.DeleteMeta("root.json") + m, _ := store.GetMeta() + if _, ok := m["root.json"]; ok { + c.Fatalf("Metadata is not deleted!") + } +}