mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #3184 from creack/fix-volumes-on-host
Fix volumes on host
This commit is contained in:
commit
621523a041
8 changed files with 159 additions and 15 deletions
29
container.go
29
container.go
|
@ -774,14 +774,14 @@ func (container *Container) getBindMap() (map[string]BindMap, error) {
|
|||
}
|
||||
binds[path.Clean(dst)] = bindMap
|
||||
}
|
||||
return binds, nil
|
||||
return binds, nil
|
||||
}
|
||||
|
||||
func (container *Container) createVolumes() error {
|
||||
binds, err := container.getBindMap()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
binds, err := container.getBindMap()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
volumesDriver := container.runtime.volumes.driver
|
||||
// Create the requested volumes if they don't exist
|
||||
for volPath := range container.Config.Volumes {
|
||||
|
@ -824,26 +824,25 @@ func (container *Container) createVolumes() error {
|
|||
}
|
||||
container.Volumes[volPath] = srcPath
|
||||
container.VolumesRW[volPath] = srcRW
|
||||
|
||||
// Create the mountpoint
|
||||
rootVolPath := path.Join(container.RootfsPath(), volPath)
|
||||
if volIsDir {
|
||||
if err := os.MkdirAll(rootVolPath, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
volPath = path.Join(container.RootfsPath(), volPath)
|
||||
rootVolPath, err := utils.FollowSymlinkInScope(volPath, container.RootfsPath())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
volPath = path.Join(container.RootfsPath(), volPath)
|
||||
if _, err := os.Stat(volPath); err != nil {
|
||||
if _, err := os.Stat(rootVolPath); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if volIsDir {
|
||||
if err := os.MkdirAll(volPath, 0755); err != nil {
|
||||
if err := os.MkdirAll(rootVolPath, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := os.MkdirAll(path.Dir(volPath), 0755); err != nil {
|
||||
if err := os.MkdirAll(path.Dir(rootVolPath), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
if f, err := os.OpenFile(volPath, os.O_CREATE, 0755); err != nil {
|
||||
if f, err := os.OpenFile(rootVolPath, os.O_CREATE, 0755); err != nil {
|
||||
return err
|
||||
} else {
|
||||
f.Close()
|
||||
|
|
57
utils/fs.go
57
utils/fs.go
|
@ -1,8 +1,10 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
|
@ -33,3 +35,58 @@ func TreeSize(dir string) (size int64, err error) {
|
|||
})
|
||||
return
|
||||
}
|
||||
|
||||
// FollowSymlink will follow an existing link and scope it to the root
|
||||
// path provided.
|
||||
func FollowSymlinkInScope(link, root string) (string, error) {
|
||||
prev := "/"
|
||||
|
||||
root, err := filepath.Abs(root)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
link, err = filepath.Abs(link)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(filepath.Dir(link), root) {
|
||||
return "", fmt.Errorf("%s is not within %s", link, root)
|
||||
}
|
||||
|
||||
for _, p := range strings.Split(link, "/") {
|
||||
prev = filepath.Join(prev, p)
|
||||
prev = filepath.Clean(prev)
|
||||
|
||||
for {
|
||||
stat, err := os.Lstat(prev)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
break
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
if stat.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||
dest, err := os.Readlink(prev)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
switch dest[0] {
|
||||
case '/':
|
||||
prev = filepath.Join(root, dest)
|
||||
case '.':
|
||||
prev, _ = filepath.Abs(prev)
|
||||
|
||||
if prev = filepath.Clean(filepath.Join(filepath.Dir(prev), dest)); len(prev) < len(root) {
|
||||
prev = filepath.Join(root, filepath.Base(dest))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return prev, nil
|
||||
}
|
||||
|
|
83
utils/fs_test.go
Normal file
83
utils/fs_test.go
Normal file
|
@ -0,0 +1,83 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func abs(t *testing.T, p string) string {
|
||||
o, err := filepath.Abs(p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func TestFollowSymLinkNormal(t *testing.T) {
|
||||
link := "testdata/fs/a/d/c/data"
|
||||
|
||||
rewrite, err := FollowSymlinkInScope(link, "testdata")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if expected := abs(t, "testdata/b/c/data"); expected != rewrite {
|
||||
t.Fatalf("Expected %s got %s", expected, rewrite)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFollowSymLinkRandomString(t *testing.T) {
|
||||
if _, err := FollowSymlinkInScope("toto", "testdata"); err == nil {
|
||||
t.Fatal("Random string should fail but didn't")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFollowSymLinkLastLink(t *testing.T) {
|
||||
link := "testdata/fs/a/d"
|
||||
|
||||
rewrite, err := FollowSymlinkInScope(link, "testdata")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if expected := abs(t, "testdata/b"); expected != rewrite {
|
||||
t.Fatalf("Expected %s got %s", expected, rewrite)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFollowSymLinkRelativeLink(t *testing.T) {
|
||||
link := "testdata/fs/a/e/c/data"
|
||||
|
||||
rewrite, err := FollowSymlinkInScope(link, "testdata")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if expected := abs(t, "testdata/fs/b/c/data"); expected != rewrite {
|
||||
t.Fatalf("Expected %s got %s", expected, rewrite)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFollowSymLinkRelativeLinkScope(t *testing.T) {
|
||||
link := "testdata/fs/a/f"
|
||||
|
||||
rewrite, err := FollowSymlinkInScope(link, "testdata")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if expected := abs(t, "testdata/test"); expected != rewrite {
|
||||
t.Fatalf("Expected %s got %s", expected, rewrite)
|
||||
}
|
||||
|
||||
link = "testdata/fs/b/h"
|
||||
|
||||
rewrite, err = FollowSymlinkInScope(link, "testdata")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if expected := abs(t, "testdata/root"); expected != rewrite {
|
||||
t.Fatalf("Expected %s got %s", expected, rewrite)
|
||||
}
|
||||
}
|
1
utils/testdata/fs/a/d
vendored
Symbolic link
1
utils/testdata/fs/a/d
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
/b
|
1
utils/testdata/fs/a/e
vendored
Symbolic link
1
utils/testdata/fs/a/e
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../b
|
1
utils/testdata/fs/a/f
vendored
Symbolic link
1
utils/testdata/fs/a/f
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../../../test
|
1
utils/testdata/fs/b/h
vendored
Symbolic link
1
utils/testdata/fs/b/h
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../g
|
1
utils/testdata/fs/g
vendored
Symbolic link
1
utils/testdata/fs/g
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../../../../../../../../../../../root
|
Loading…
Reference in a new issue