Skip to content
This repository was archived by the owner on Jan 15, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions image/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
Expand All @@ -35,10 +34,7 @@ func findConfig(w walker, d *v1.Descriptor) (*v1.Image, error) {
var c v1.Image
cpath := filepath.Join("blobs", string(d.Digest.Algorithm()), d.Digest.Hex())

switch err := w.walk(func(path string, info os.FileInfo, r io.Reader) error {
if info.IsDir() || filepath.Clean(path) != cpath {
return nil
}
switch err := w.find(cpath, func(path string, r io.Reader) error {
buf, err := ioutil.ReadAll(r)
if err != nil {
return errors.Wrapf(err, "%s: error reading config", path)
Expand Down
7 changes: 2 additions & 5 deletions image/descriptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,9 @@ func listReferences(w walker) ([]v1.Descriptor, error) {
func findDescriptor(w walker, names []string) ([]v1.Descriptor, error) {
var descs []v1.Descriptor
var index v1.Index
dpath := "index.json"

if err := w.walk(func(path string, info os.FileInfo, r io.Reader) error {
if info.IsDir() || filepath.Clean(path) != indexPath {
return nil
}

if err := w.find(dpath, func(path string, r io.Reader) error {
if err := json.NewDecoder(r).Decode(&index); err != nil {
return err
}
Expand Down
20 changes: 4 additions & 16 deletions image/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,7 @@ func findManifest(w walker, d *v1.Descriptor) (*v1.Manifest, error) {
var m v1.Manifest
mpath := filepath.Join("blobs", string(d.Digest.Algorithm()), d.Digest.Hex())

switch err := w.walk(func(path string, info os.FileInfo, r io.Reader) error {
if info.IsDir() || filepath.Clean(path) != mpath {
return nil
}

switch err := w.find(mpath, func(path string, r io.Reader) error {
buf, err := ioutil.ReadAll(r)
if err != nil {
return errors.Wrapf(err, "%s: error reading manifest", path)
Expand Down Expand Up @@ -108,18 +104,10 @@ func unpackManifest(m *v1.Manifest, w walker, dest string) (retErr error) {
}
}()
for _, d := range m.Layers {
switch err := w.walk(func(path string, info os.FileInfo, r io.Reader) error {
if info.IsDir() {
return nil
}

dd, err := filepath.Rel(filepath.Join("blobs", string(d.Digest.Algorithm())), filepath.Clean(path))
if err != nil || d.Digest.Hex() != dd {
return nil
}

lpath := filepath.Join("blobs", string(d.Digest.Algorithm()), d.Digest.Hex())
switch err := w.find(lpath, func(path string, r io.Reader) error {
if err := unpackLayer(d.MediaType, path, dest, r); err != nil {
return errors.Wrap(err, "error unpack: extracting layer")
return errors.Wrap(err, "unpack: error extracting layer")
}

return errEOW
Expand Down
82 changes: 82 additions & 0 deletions image/walker.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ var (
// walkFunc is a function type that gets called for each file or directory visited by the Walker.
type walkFunc func(path string, _ os.FileInfo, _ io.Reader) error

type findFunc func(path string, r io.Reader) error

// walker is the interface that defines how to access a given archival format
type walker interface {

Expand All @@ -43,6 +45,9 @@ type walker interface {
// get will copy an arbitrary blob, defined by desc, in to dst. returns
// the number of bytes copied on success.
get(desc v1.Descriptor, dst io.Writer) (int64, error)

// find calls findFunc for handling content of path
find(path string, ff findFunc) error
}

// tarWalker exposes access to image layouts in a tar file.
Expand Down Expand Up @@ -120,6 +125,34 @@ func (w *tarWalker) get(desc v1.Descriptor, dst io.Writer) (int64, error) {
return bytes, nil
}

func (w *tarWalker) find(path string, ff findFunc) error {
done := false

f := func(relpath string, info os.FileInfo, rdr io.Reader) error {
var err error
if done {
return nil
}

if filepath.Clean(relpath) == path && !info.IsDir() {
if err = ff(relpath, rdr); err != nil {
return err
}
done = true
}
return nil
}

if err := w.walk(f); err != nil {
return errors.Wrapf(err, "find failed: unable to walk")
}
if !done {
return os.ErrNotExist
}

return nil
}

type eofReader struct{}

func (eofReader) Read(_ []byte) (int, error) {
Expand Down Expand Up @@ -188,6 +221,27 @@ func (w *pathWalker) get(desc v1.Descriptor, dst io.Writer) (int64, error) {
return nbytes, nil
}

func (w *pathWalker) find(path string, ff findFunc) error {
name := filepath.Join(w.root, path)

info, err := os.Stat(name)
if err != nil {
return err
}

if info.IsDir() {
return fmt.Errorf("object is dir")
}

file, err := os.Open(name)
if err != nil {
return errors.Wrap(err, "unable to open file") // os.Open includes the path
}
defer file.Close()

return ff(name, file)
}

type zipWalker struct {
fileName string
}
Expand Down Expand Up @@ -249,3 +303,31 @@ func (w *zipWalker) get(desc v1.Descriptor, dst io.Writer) (int64, error) {

return bytes, nil
}

func (w *zipWalker) find(path string, ff findFunc) error {
done := false

f := func(relpath string, info os.FileInfo, rdr io.Reader) error {
var err error
if done {
return nil
}

if filepath.Clean(relpath) == path && !info.IsDir() {
if err = ff(relpath, rdr); err != nil {
return err
}
done = true
}
return nil
}

if err := w.walk(f); err != nil {
return errors.Wrapf(err, "find failed: unable to walk")
}
if !done {
return os.ErrNotExist
}

return nil
}