diff --git a/filesystem.go b/filesystem.go index 5088590c3a..7a37807790 100644 --- a/filesystem.go +++ b/filesystem.go @@ -1,9 +1,10 @@ package docker import ( + "errors" "fmt" "os" - "os/exec" + "syscall" ) type Filesystem struct { @@ -23,6 +24,9 @@ func (fs *Filesystem) createMountPoints() error { } func (fs *Filesystem) Mount() error { + if fs.IsMounted() { + return errors.New("Mount: Filesystem already mounted") + } if err := fs.createMountPoints(); err != nil { return err } @@ -32,15 +36,33 @@ func (fs *Filesystem) Mount() error { roBranches += fmt.Sprintf("%v=ro:", layer) } branches := fmt.Sprintf("br:%v:%v", rwBranch, roBranches) - cmd := exec.Command("mount", "-t", "aufs", "-o", branches, "none", fs.RootFS) - if err := cmd.Run(); err != nil { - return err - } - return nil + return syscall.Mount("none", fs.RootFS, "aufs", 0, branches) } func (fs *Filesystem) Umount() error { - return exec.Command("umount", fs.RootFS).Run() + if !fs.IsMounted() { + return errors.New("Umount: Filesystem not mounted") + } + return syscall.Unmount(fs.RootFS, 0) +} + +func (fs *Filesystem) IsMounted() bool { + f, err := os.Open(fs.RootFS) + if err != nil { + if os.IsNotExist(err) { + return false + } + panic(err) + } + list, err := f.Readdirnames(1) + f.Close() + if err != nil { + return false + } + if len(list) > 0 { + return true + } + return false } func newFilesystem(rootfs string, rwpath string, layers []string) *Filesystem { diff --git a/filesystem_test.go b/filesystem_test.go index 18aa951852..9c3dd5cff0 100644 --- a/filesystem_test.go +++ b/filesystem_test.go @@ -1,7 +1,10 @@ package docker import ( + "bytes" "io/ioutil" + "os" + "path" "testing" ) @@ -15,7 +18,7 @@ func TestFilesystem(t *testing.T) { t.Fatal(err) } - filesystem := newFilesystem(rootfs, rwpath, []string{"/var/lib/docker/images/ubuntu", "/var/lib/docker/images/test"}) + filesystem := newFilesystem(rootfs, rwpath, []string{"/var/lib/docker/images/ubuntu"}) if err := filesystem.Umount(); err == nil { t.Errorf("Umount succeeded even though the filesystem was not mounted") @@ -25,6 +28,10 @@ func TestFilesystem(t *testing.T) { t.Fatal(err) } + if err := filesystem.Mount(); err == nil { + t.Errorf("Double mount succeeded") + } + if err := filesystem.Umount(); err != nil { t.Fatal(err) } @@ -33,3 +40,48 @@ func TestFilesystem(t *testing.T) { t.Errorf("Umount succeeded even though the filesystem was already umounted") } } + +func TestFilesystemMultiLayer(t *testing.T) { + // Create a fake layer + fakeLayer, err := ioutil.TempDir("", "docker-layer") + if err != nil { + t.Fatal(err) + } + data := []byte("hello world") + if err := ioutil.WriteFile(path.Join(fakeLayer, "test_file"), data, 0700); err != nil { + t.Fatal(err) + } + + // Create the layered filesystem and add our fake layer on top + rootfs, err := ioutil.TempDir("", "docker-test-root") + if err != nil { + t.Fatal(err) + } + rwpath, err := ioutil.TempDir("", "docker-test-rw") + if err != nil { + t.Fatal(err) + } + filesystem := newFilesystem(rootfs, rwpath, []string{"/var/lib/docker/images/ubuntu", fakeLayer}) + + // Mount it + if err := filesystem.Mount(); err != nil { + t.Fatal(err) + } + defer func() { + if err := filesystem.Umount(); err != nil { + t.Fatal(err) + } + }() + + // Check to see whether we can access our fake layer + if _, err := os.Stat(path.Join(rootfs, "test_file")); err != nil { + t.Fatal(err) + } + fsdata, err := ioutil.ReadFile(path.Join(rootfs, "test_file")) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(data, fsdata) { + t.Error(string(fsdata)) + } +}