Skip to content

Commit

Permalink
local: avoid writing to content root on readonly store
Browse files Browse the repository at this point in the history
A contentstore can be created on top of readonly path and
should not fail unless there is an attempt to write into it.

Currently this fails because new ingest directory is created
always, meaning for example that you can't create a store to
read blobs from OCI layout without it contaminating the OCI
layout files.

Signed-off-by: Tonis Tiigi <[email protected]>
  • Loading branch information
tonistiigi committed Oct 25, 2024
1 parent 5a2da17 commit 3cc2343
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 12 deletions.
30 changes: 22 additions & 8 deletions plugins/content/local/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ type store struct {
ls LabelStore
integritySupported bool

locksMu sync.Mutex
locks map[string]*lock
locksMu sync.Mutex
locks map[string]*lock
ensureIngestRootOnce func() error
}

// NewStore returns a local content store
Expand All @@ -83,18 +84,16 @@ func NewStore(root string) (content.Store, error) {
// require labels and should use `NewStore`. `NewLabeledStore` is primarily
// useful for tests or standalone implementations.
func NewLabeledStore(root string, ls LabelStore) (content.Store, error) {
if err := os.MkdirAll(filepath.Join(root, "ingest"), 0777); err != nil {
return nil, err
}

supported, _ := fsverity.IsSupported(root)

return &store{
s := &store{
root: root,
ls: ls,
integritySupported: supported,
locks: map[string]*lock{},
}, nil
}
s.ensureIngestRootOnce = sync.OnceValue(s.ensureIngestRoot)
return s, nil
}

func (s *store) Info(ctx context.Context, dgst digest.Digest) (content.Info, error) {
Expand Down Expand Up @@ -301,6 +300,9 @@ func (s *store) Status(ctx context.Context, ref string) (content.Status, error)
func (s *store) ListStatuses(ctx context.Context, fs ...string) ([]content.Status, error) {
fp, err := os.Open(filepath.Join(s.root, "ingest"))
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
defer fp.Close()
Expand Down Expand Up @@ -350,6 +352,9 @@ func (s *store) ListStatuses(ctx context.Context, fs ...string) ([]content.Statu
func (s *store) WalkStatusRefs(ctx context.Context, fn func(string) error) error {
fp, err := os.Open(filepath.Join(s.root, "ingest"))
if err != nil {
if os.IsNotExist(err) {
return nil
}
return err
}
defer fp.Close()
Expand Down Expand Up @@ -536,6 +541,11 @@ func (s *store) writer(ctx context.Context, ref string, total int64, expected di
)

foundValidIngest := false

if err := s.ensureIngestRootOnce(); err != nil {
return nil, err
}

// ensure that the ingest path has been created.
if err := os.Mkdir(path, 0755); err != nil {
if !os.IsExist(err) {
Expand Down Expand Up @@ -646,6 +656,10 @@ func (s *store) ingestPaths(ref string) (string, string, string) {
return fp, rp, dp
}

func (s *store) ensureIngestRoot() error {
return os.MkdirAll(filepath.Join(s.root, "ingest"), 0777)
}

func readFileString(path string) (string, error) {
p, err := os.ReadFile(path)
return string(p), err
Expand Down
8 changes: 4 additions & 4 deletions plugins/content/local/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,6 @@ func TestContentWriter(t *testing.T) {
defer cleanup()
defer testutil.DumpDirOnFailure(t, tmpdir)

if _, err := os.Stat(filepath.Join(tmpdir, "ingest")); os.IsNotExist(err) {
t.Fatal("ingest dir should be created", err)
}

cw, err := cs.Writer(ctx, content.WithRef("myref"))
if err != nil {
t.Fatal(err)
Expand All @@ -120,6 +116,10 @@ func TestContentWriter(t *testing.T) {
t.Fatal(err)
}

if _, err := os.Stat(filepath.Join(tmpdir, "ingest")); os.IsNotExist(err) {
t.Fatal("ingest dir should be created", err)
}

// reopen, so we can test things
cw, err = cs.Writer(ctx, content.WithRef("myref"))
if err != nil {
Expand Down

0 comments on commit 3cc2343

Please sign in to comment.