Skip to content

Commit d3c2351

Browse files
authored
Merge pull request #113 from darstahl/ResolveRoot
Resolve context root on context.Walk when root is symlink
2 parents a60600a + 5633c24 commit d3c2351

13 files changed

Lines changed: 293 additions & 9 deletions

context.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -572,8 +572,16 @@ func (c *context) Apply(resource Resource) error {
572572
// the context. Otherwise identical to filepath.Walk, the path argument is
573573
// corrected to be contained within the context.
574574
func (c *context) Walk(fn filepath.WalkFunc) error {
575-
return c.pathDriver.Walk(c.root, func(p string, fi os.FileInfo, err error) error {
576-
contained, err := c.contain(p)
575+
root := c.root
576+
fi, err := c.driver.Lstat(c.root)
577+
if err == nil && fi.Mode()&os.ModeSymlink != 0 {
578+
root, err = c.driver.Readlink(c.root)
579+
if err != nil {
580+
return err
581+
}
582+
}
583+
return c.pathDriver.Walk(root, func(p string, fi os.FileInfo, err error) error {
584+
contained, err := c.containWithRoot(p, root)
577585
return fn(contained, fi, err)
578586
})
579587
}
@@ -592,7 +600,15 @@ func (c *context) fullpath(p string) (string, error) {
592600
// contain cleans and santizes the filesystem path p to be an absolute path,
593601
// effectively relative to the context root.
594602
func (c *context) contain(p string) (string, error) {
595-
sanitized, err := c.pathDriver.Rel(c.root, p)
603+
return c.containWithRoot(p, c.root)
604+
}
605+
606+
// containWithRoot cleans and santizes the filesystem path p to be an absolute path,
607+
// effectively relative to the passed root. Extra care should be used when calling this
608+
// instead of contain. This is needed for Walk, as if context root is a symlink,
609+
// it must be evaluated prior to the Walk
610+
func (c *context) containWithRoot(p string, root string) (string, error) {
611+
sanitized, err := c.pathDriver.Rel(root, p)
596612
if err != nil {
597613
return "", err
598614
}

driver/driver.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,6 @@ func (d *driver) Lstat(p string) (os.FileInfo, error) {
122122
return os.Lstat(p)
123123
}
124124

125-
func (d *driver) Readlink(p string) (string, error) {
126-
return os.Readlink(p)
127-
}
128-
129125
func (d *driver) Mkdir(p string, mode os.FileMode) error {
130126
return os.Mkdir(p, mode)
131127
}

driver/driver_unix.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,8 @@ func (d *driver) LSetxattr(path string, attrMap map[string][]byte) error {
120120
func (d *driver) DeviceInfo(fi os.FileInfo) (maj uint64, min uint64, err error) {
121121
return devices.DeviceInfo(fi)
122122
}
123+
124+
// Readlink was forked on Windows to fix a Golang bug, use the "os" package here
125+
func (d *driver) Readlink(p string) (string, error) {
126+
return os.Readlink(p)
127+
}

driver/driver_windows.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package driver
33
import (
44
"os"
55

6+
"github.com/containerd/continuity/sysx"
67
"github.com/pkg/errors"
78
)
89

@@ -19,3 +20,9 @@ func (d *driver) Lchmod(path string, mode os.FileMode) (err error) {
1920
// TODO: Use Window's equivalent
2021
return os.Chmod(path, mode)
2122
}
23+
24+
// Readlink is forked in order to support Volume paths which are used
25+
// in container layers.
26+
func (d *driver) Readlink(p string) (string, error) {
27+
return sysx.Readlink(p)
28+
}

fs/fstest/compare.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,15 @@ func CheckDirectoryEqual(d1, d2 string) error {
3333

3434
diff := diffResourceList(m1.Resources, m2.Resources)
3535
if diff.HasDiff() {
36-
return errors.Errorf("directory diff between %s and %s\n%s", d1, d2, diff.String())
36+
if len(diff.Deletions) != 0 {
37+
return errors.Errorf("directory diff between %s and %s\n%s", d1, d2, diff.String())
38+
}
39+
// TODO: Also skip Recycle Bin contents in Windows layers which is used to store deleted files in some cases
40+
for _, add := range diff.Additions {
41+
if ok, _ := metadataFiles[add.Path()]; !ok {
42+
return errors.Errorf("directory diff between %s and %s\n%s", d1, d2, diff.String())
43+
}
44+
}
3745
}
3846

3947
return nil

fs/fstest/compare_unix.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// +build !windows
2+
3+
package fstest
4+
5+
var metadataFiles map[string]bool

fs/fstest/compare_windows.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package fstest
2+
3+
// TODO: Any more metadata files generated by Windows layers?
4+
var metadataFiles = map[string]bool{
5+
"\\System Volume Information": true,
6+
"\\WcSandboxState": true,
7+
}

fs/fstest/file_unix.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,10 @@ func Lchtimes(name string, atime, mtime time.Time) Applier {
2727
return unix.UtimesNanoAt(unix.AT_FDCWD, path, utimes[0:], unix.AT_SYMLINK_NOFOLLOW)
2828
})
2929
}
30+
31+
func Base() Applier {
32+
return applyFn(func(root string) error {
33+
// do nothing, as the base is not special
34+
return nil
35+
})
36+
}

fs/fstest/file_windows.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,18 @@ func Lchtimes(name string, atime, mtime time.Time) Applier {
1212
return errors.New("Not implemented")
1313
})
1414
}
15+
16+
// Base applies the files required to make a valid Windows container layer
17+
// that the filter will mount. It is used for testing the snapshotter
18+
func Base() Applier {
19+
return Apply(
20+
CreateDir("Windows", 0755),
21+
CreateDir("Windows/System32", 0755),
22+
CreateDir("Windows/System32/Config", 0755),
23+
CreateFile("Windows/System32/Config/SYSTEM", []byte("foo\n"), 0777),
24+
CreateFile("Windows/System32/Config/SOFTWARE", []byte("foo\n"), 0777),
25+
CreateFile("Windows/System32/Config/SAM", []byte("foo\n"), 0777),
26+
CreateFile("Windows/System32/Config/SECURITY", []byte("foo\n"), 0777),
27+
CreateFile("Windows/System32/Config/DEFAULT", []byte("foo\n"), 0777),
28+
)
29+
}

manifest.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ func BuildManifest(ctx Context) (*Manifest, error) {
6666
return fmt.Errorf("error walking %s: %v", p, err)
6767
}
6868

69-
if p == "/" {
69+
if p == string(os.PathSeparator) {
7070
// skip root
7171
return nil
7272
}

0 commit comments

Comments
 (0)