github.com/slava-ustovytski/docker@v1.8.2-rc1/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  		if !container.trySetNetworkMount(m.Destination, path) {
    40  			mounts = append(mounts, execdriver.Mount{
    41  				Source:      path,
    42  				Destination: m.Destination,
    43  				Writable:    m.RW,
    44  			})
    45  		}
    46  	}
    47  
    48  	mounts = sortMounts(mounts)
    49  	return append(mounts, container.networkMounts()...), nil
    50  }
    51  
    52  func sortMounts(m []execdriver.Mount) []execdriver.Mount {
    53  	sort.Sort(mounts(m))
    54  	return m
    55  }
    56  
    57  type mounts []execdriver.Mount
    58  
    59  func (m mounts) Len() int {
    60  	return len(m)
    61  }
    62  
    63  func (m mounts) Less(i, j int) bool {
    64  	return m.parts(i) < m.parts(j)
    65  }
    66  
    67  func (m mounts) Swap(i, j int) {
    68  	m[i], m[j] = m[j], m[i]
    69  }
    70  
    71  func (m mounts) parts(i int) int {
    72  	return len(strings.Split(filepath.Clean(m[i].Destination), string(os.PathSeparator)))
    73  }
    74  
    75  // migrateVolume links the contents of a volume created pre Docker 1.7
    76  // into the location expected by the local driver.
    77  // It creates a symlink from DOCKER_ROOT/vfs/dir/VOLUME_ID to DOCKER_ROOT/volumes/VOLUME_ID/_container_data.
    78  // It preserves the volume json configuration generated pre Docker 1.7 to be able to
    79  // downgrade from Docker 1.7 to Docker 1.6 without losing volume compatibility.
    80  func migrateVolume(id, vfs string) error {
    81  	l, err := getVolumeDriver(volume.DefaultDriverName)
    82  	if err != nil {
    83  		return err
    84  	}
    85  
    86  	newDataPath := l.(*local.Root).DataPath(id)
    87  	fi, err := os.Stat(newDataPath)
    88  	if err != nil && !os.IsNotExist(err) {
    89  		return err
    90  	}
    91  
    92  	if fi != nil && fi.IsDir() {
    93  		return nil
    94  	}
    95  
    96  	return os.Symlink(vfs, newDataPath)
    97  }
    98  
    99  // validVolumeLayout checks whether the volume directory layout
   100  // is valid to work with Docker post 1.7 or not.
   101  func validVolumeLayout(files []os.FileInfo) bool {
   102  	if len(files) == 1 && files[0].Name() == local.VolumeDataPathName && files[0].IsDir() {
   103  		return true
   104  	}
   105  
   106  	if len(files) != 2 {
   107  		return false
   108  	}
   109  
   110  	for _, f := range files {
   111  		if f.Name() == "config.json" ||
   112  			(f.Name() == local.VolumeDataPathName && f.Mode()&os.ModeSymlink == os.ModeSymlink) {
   113  			// Old volume configuration, we ignore it
   114  			continue
   115  		}
   116  		return false
   117  	}
   118  
   119  	return true
   120  }