1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00
moby--moby/daemon/graphdriver/vfs/driver.go
Josh Hawn b6db23cffe Use archive.CopyWithTar in vfs.Create
The vfs storage driver currently shells out to the `cp` binary on the host
system to perform an 'archive' copy of the base image to a new directory.
The archive option preserves the modified time of the files which are created
but there was an issue where it was unable to preserve the modified time of
copied symbolic links on some host systems with an outdated version of `cp`.

This change no longer relies on the host system implementation and instead
utilizes the `CopyWithTar` function found in `pkg/archive` which is used
to copy from source to destination directory using a Tar archive, which
should correctly preserve file attributes.

Docker-DCO-1.1-Signed-off-by: Josh Hawn <josh.hawn@docker.com> (github: jlhawn)
2014-10-27 11:38:22 -07:00

104 lines
2 KiB
Go

package vfs
import (
"bytes"
"fmt"
"os"
"os/exec"
"path"
"github.com/docker/docker/daemon/graphdriver"
"github.com/docker/docker/pkg/archive"
"github.com/docker/libcontainer/label"
)
func init() {
graphdriver.Register("vfs", Init)
}
func Init(home string, options []string) (graphdriver.Driver, error) {
d := &Driver{
home: home,
}
return graphdriver.NaiveDiffDriver(d), nil
}
type Driver struct {
home string
}
func (d *Driver) String() string {
return "vfs"
}
func (d *Driver) Status() [][2]string {
return nil
}
func (d *Driver) Cleanup() error {
return nil
}
func isGNUcoreutils() bool {
if stdout, err := exec.Command("cp", "--version").Output(); err == nil {
return bytes.Contains(stdout, []byte("GNU coreutils"))
}
return false
}
func (d *Driver) Create(id, parent string) error {
dir := d.dir(id)
if err := os.MkdirAll(path.Dir(dir), 0700); err != nil {
return err
}
if err := os.Mkdir(dir, 0755); err != nil {
return err
}
opts := []string{"level:s0"}
if _, mountLabel, err := label.InitLabels(opts); err == nil {
label.Relabel(dir, mountLabel, "")
}
if parent == "" {
return nil
}
parentDir, err := d.Get(parent, "")
if err != nil {
return fmt.Errorf("%s: %s", parent, err)
}
if err := archive.CopyWithTar(parentDir, dir); err != nil {
return err
}
return nil
}
func (d *Driver) dir(id string) string {
return path.Join(d.home, "dir", path.Base(id))
}
func (d *Driver) Remove(id string) error {
if _, err := os.Stat(d.dir(id)); err != nil {
return err
}
return os.RemoveAll(d.dir(id))
}
func (d *Driver) Get(id, mountLabel string) (string, error) {
dir := d.dir(id)
if st, err := os.Stat(dir); err != nil {
return "", err
} else if !st.IsDir() {
return "", fmt.Errorf("%s: not a directory", dir)
}
return dir, nil
}
func (d *Driver) Put(id string) {
// The vfs driver has no runtime resources (e.g. mounts)
// to clean up, so we don't need anything here
}
func (d *Driver) Exists(id string) bool {
_, err := os.Stat(d.dir(id))
return err == nil
}