Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

descriptor validation #29

Merged
merged 1 commit into from Oct 6, 2016
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 6 additions & 20 deletions image/descriptor.go
Expand Up @@ -105,28 +105,14 @@ func (d *descriptor) validate(w walker, mts []string) error {
if !found {
return fmt.Errorf("invalid descriptor MediaType %q", d.MediaType)
}
switch err := w.walk(func(path string, info os.FileInfo, r io.Reader) error {
if info.IsDir() {
return nil
}

filename, err := filepath.Rel(filepath.Join("blobs", d.algo()), filepath.Clean(path))
if err != nil || d.hash() != filename {
return nil
}

if err := d.validateContent(r); err != nil {
return err
}
return errEOW
}); err {
case nil:
return fmt.Errorf("%s: not found", d.Digest)
case errEOW:
return nil
default:
return errors.Wrapf(err, "%s: validation failed", d.Digest)
rc, err := w.Get(*d)
if err != nil {
return err
}
defer rc.Close()

return d.validateContent(rc)
}

func (d *descriptor) validateContent(r io.Reader) error {
Expand Down
6 changes: 3 additions & 3 deletions image/image.go
Expand Up @@ -40,7 +40,7 @@ func Validate(tarFile string, refs []string, out *log.Logger) error {
}
defer f.Close()

return validate(newTarWalker(f), refs, out)
return validate(newTarWalker(tarFile, f), refs, out)
}

var validRefMediaTypes = []string{
Expand Down Expand Up @@ -111,7 +111,7 @@ func Unpack(tarFile, dest, ref string) error {
}
defer f.Close()

return unpack(newTarWalker(f), dest, ref)
return unpack(newTarWalker(tarFile, f), dest, ref)
}

func unpack(w walker, dest, refName string) error {
Expand Down Expand Up @@ -153,7 +153,7 @@ func CreateRuntimeBundle(tarFile, dest, ref, root string) error {
}
defer f.Close()

return createRuntimeBundle(newTarWalker(f), dest, ref, root)
return createRuntimeBundle(newTarWalker(tarFile, f), dest, ref, root)
}

func createRuntimeBundle(w walker, dest, refName, rootfs string) error {
Expand Down
84 changes: 84 additions & 0 deletions image/reader.go
@@ -0,0 +1,84 @@
// Copyright 2016 The Linux Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package image

import (
"archive/tar"
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
)

type reader interface {
Get(desc descriptor) (io.ReadCloser, error)
}

type tarReader struct {
name string
}

func (r *tarReader) Get(desc descriptor) (io.ReadCloser, error) {
f, err := os.Open(r.name)
if err != nil {
return nil, err
}
defer f.Close()

tr := tar.NewReader(f)
loop:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the named loop entirely needed? I'm not opposed to them, but I don't see any inner loops to distinguish from

Copy link
Contributor Author

@xiekeyang xiekeyang Sep 23, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vbatts

loop:
        for {
                hdr, err := tr.Next()
                switch err {
                case io.EOF:
                        break loop
                case nil:
                // success, continue below
                default:
                        return nil, err 
                }   
                if hdr.Name == filepath.Join("blobs", desc.algo(), desc.hash()) &&
                        !hdr.FileInfo().IsDir() {
                        buf, err := ioutil.ReadAll(tr)
                        if err != nil {
                                return nil, err 
                        }   
                        return ioutil.NopCloser(bytes.NewReader(buf)), nil 
                }   
        }   

break is located in switch-case block, but it want to break the for-loop. So it should point the label( as break loop). Otherwise, the break will jump out switch-case block.
Of course, we can use if checking instead of switch-case, which not use label. But it is same effect.
If my explain has covered your question?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. My apologies.

for {
hdr, err := tr.Next()
switch err {
case io.EOF:
break loop
case nil:
// success, continue below
default:
return nil, err
}
if hdr.Name == filepath.Join("blobs", desc.algo(), desc.hash()) &&
!hdr.FileInfo().IsDir() {
buf, err := ioutil.ReadAll(tr)
if err != nil {
return nil, err
}
return ioutil.NopCloser(bytes.NewReader(buf)), nil
}
}

return nil, fmt.Errorf("object not found")
}

type layoutReader struct {
root string
}

func (r *layoutReader) Get(desc descriptor) (io.ReadCloser, error) {
name := filepath.Join(r.root, "blobs", desc.algo(), desc.hash())

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

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

return os.Open(name)
}
9 changes: 6 additions & 3 deletions image/walker.go
Expand Up @@ -35,15 +35,17 @@ type walkFunc func(path string, _ os.FileInfo, _ io.Reader) error
// calling walk for each file or directory in the tree.
type walker interface {
walk(walkFunc) error
reader
}

type tarWalker struct {
r io.ReadSeeker
tarReader
}

// newTarWalker returns a Walker that walks through .tar files.
func newTarWalker(r io.ReadSeeker) walker {
return &tarWalker{r}
func newTarWalker(tarFile string, r io.ReadSeeker) walker {
return &tarWalker{r, tarReader{name: tarFile}}
}

func (w *tarWalker) walk(f walkFunc) error {
Expand Down Expand Up @@ -82,12 +84,13 @@ func (eofReader) Read(_ []byte) (int, error) {

type pathWalker struct {
root string
layoutReader
}

// newPathWalker returns a Walker that walks through directories
// starting at the given root path. It does not follow symlinks.
func newPathWalker(root string) walker {
return &pathWalker{root}
return &pathWalker{root, layoutReader{root: root}}
}

func (w *pathWalker) walk(f walkFunc) error {
Expand Down