github.com/tsuna/docker@v1.7.0-rc3/daemon/volumes_linux.go (about)

     1  // +build !windows
     2  
     3  package daemon
     4  
     5  import (
     6  	"os"
     7  	"path/filepath"
     8  	"sort"
     9  	"strings"
    10  
    11  	"github.com/docker/docker/daemon/execdriver"
    12  	"github.com/docker/docker/pkg/system"
    13  	"github.com/docker/docker/volume"
    14  	"github.com/docker/docker/volume/local"
    15  )
    16  
    17  // copyOwnership copies the permissions and uid:gid of the source file
    18  // into the destination file
    19  func copyOwnership(source, destination string) error {
    20  	stat, err := system.Stat(source)
    21  	if err != nil {
    22  		return err
    23  	}
    24  
    25  	if err := os.Chown(destination, int(stat.Uid()), int(stat.Gid())); err != nil {
    26  		return err
    27  	}
    28  
    29  	return os.Chmod(destination, os.FileMode(stat.Mode()))
    30  }
    31  
    32  func (container *Container) setupMounts() ([]execdriver.Mount, error) {
    33  	var mounts []execdriver.Mount
    34  	for _, m := range container.MountPoints {
    35  		path, err := m.Setup()
    36  		if err != nil {
    37  			return nil, err
    38  		}
    39  
    40  		mounts = append(mounts, execdriver.Mount{
    41  			Source:      path,
    42  			Destination: m.Destination,
    43  			Writable:    m.RW,
    44  		})
    45  	}
    46  
    47  	mounts = sortMounts(mounts)
    48  	return append(mounts, container.networkMounts()...), nil
    49  }
    50  
    51  func sortMounts(m []execdriver.Mount) []execdriver.Mount {
    52  	sort.Sort(mounts(m))
    53  	return m
    54  }
    55  
    56  type mounts []execdriver.Mount
    57  
    58  func (m mounts) Len() int {
    59  	return len(m)
    60  }
    61  
    62  func (m mounts) Less(i, j int) bool {
    63  	return m.parts(i) < m.parts(j)
    64  }
    65  
    66  func (m mounts) Swap(i, j int) {
    67  	m[i], m[j] = m[j], m[i]
    68  }
    69  
    70  func (m mounts) parts(i int) int {
    71  	return len(strings.Split(filepath.Clean(m[i].Destination), string(os.PathSeparator)))
    72  }
    73  
    74  // migrateVolume links the contents of a volume created pre Docker 1.7
    75  // into the location expected by the local driver.
    76  // It creates a symlink from DOCKER_ROOT/vfs/dir/VOLUME_ID to DOCKER_ROOT/volumes/VOLUME_ID/_container_data.
    77  // It preserves the volume json configuration generated pre Docker 1.7 to be able to
    78  // downgrade from Docker 1.7 to Docker 1.6 without losing volume compatibility.
    79  func migrateVolume(id, vfs string) error {
    80  	l, err := getVolumeDriver(volume.DefaultDriverName)
    81  	if err != nil {
    82  		return err
    83  	}
    84  
    85  	newDataPath := l.(*local.Root).DataPath(id)
    86  	fi, err := os.Stat(newDataPath)
    87  	if err != nil && !os.IsNotExist(err) {
    88  		return err
    89  	}
    90  
    91  	if fi != nil && fi.IsDir() {
    92  		return nil
    93  	}
    94  
    95  	return os.Symlink(vfs, newDataPath)
    96  }
    97  
    98  // validVolumeLayout checks whether the volume directory layout
    99  // is valid to work with Docker post 1.7 or not.
   100  func validVolumeLayout(files []os.FileInfo) bool {
   101  	if len(files) == 1 && files[0].Name() == local.VolumeDataPathName && files[0].IsDir() {
   102  		return true
   103  	}
   104  
   105  	if len(files) != 2 {
   106  		return false
   107  	}
   108  
   109  	for _, f := range files {
   110  		if f.Name() == "config.json" ||
   111  			(f.Name() == local.VolumeDataPathName && f.Mode()&os.ModeSymlink == os.ModeSymlink) {
   112  			// Old volume configuration, we ignore it
   113  			continue
   114  		}
   115  		return false
   116  	}
   117  
   118  	return true
   119  }