mirror of https://github.com/docker/docs.git
				
				
				
			
		
			
				
	
	
		
			166 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			166 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
| package volumes
 | |
| 
 | |
| import (
 | |
| 	"encoding/json"
 | |
| 	"io"
 | |
| 	"io/ioutil"
 | |
| 	"os"
 | |
| 	"path"
 | |
| 	"path/filepath"
 | |
| 	"sync"
 | |
| 
 | |
| 	"github.com/docker/docker/pkg/archive"
 | |
| 	"github.com/docker/docker/pkg/symlink"
 | |
| )
 | |
| 
 | |
| type Volume struct {
 | |
| 	ID          string
 | |
| 	Path        string
 | |
| 	IsBindMount bool
 | |
| 	Writable    bool
 | |
| 	containers  map[string]struct{}
 | |
| 	configPath  string
 | |
| 	repository  *Repository
 | |
| 	lock        sync.Mutex
 | |
| }
 | |
| 
 | |
| func (v *Volume) Export(resource, name string) (io.ReadCloser, error) {
 | |
| 	if v.IsBindMount && filepath.Base(resource) == name {
 | |
| 		name = ""
 | |
| 	}
 | |
| 
 | |
| 	basePath, err := v.getResourcePath(resource)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	stat, err := os.Stat(basePath)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	var filter []string
 | |
| 	if !stat.IsDir() {
 | |
| 		d, f := path.Split(basePath)
 | |
| 		basePath = d
 | |
| 		filter = []string{f}
 | |
| 	} else {
 | |
| 		filter = []string{path.Base(basePath)}
 | |
| 		basePath = path.Dir(basePath)
 | |
| 	}
 | |
| 	return archive.TarWithOptions(basePath, &archive.TarOptions{
 | |
| 		Compression:  archive.Uncompressed,
 | |
| 		Name:         name,
 | |
| 		IncludeFiles: filter,
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func (v *Volume) IsDir() (bool, error) {
 | |
| 	stat, err := os.Stat(v.Path)
 | |
| 	if err != nil {
 | |
| 		return false, err
 | |
| 	}
 | |
| 
 | |
| 	return stat.IsDir(), nil
 | |
| }
 | |
| 
 | |
| func (v *Volume) Containers() []string {
 | |
| 	v.lock.Lock()
 | |
| 
 | |
| 	var containers []string
 | |
| 	for c := range v.containers {
 | |
| 		containers = append(containers, c)
 | |
| 	}
 | |
| 
 | |
| 	v.lock.Unlock()
 | |
| 	return containers
 | |
| }
 | |
| 
 | |
| func (v *Volume) RemoveContainer(containerId string) {
 | |
| 	v.lock.Lock()
 | |
| 	delete(v.containers, containerId)
 | |
| 	v.lock.Unlock()
 | |
| }
 | |
| 
 | |
| func (v *Volume) AddContainer(containerId string) {
 | |
| 	v.lock.Lock()
 | |
| 	v.containers[containerId] = struct{}{}
 | |
| 	v.lock.Unlock()
 | |
| }
 | |
| 
 | |
| func (v *Volume) initialize() error {
 | |
| 	v.lock.Lock()
 | |
| 	defer v.lock.Unlock()
 | |
| 
 | |
| 	if _, err := os.Stat(v.Path); err != nil && os.IsNotExist(err) {
 | |
| 		if err := os.MkdirAll(v.Path, 0755); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if err := os.MkdirAll(v.configPath, 0755); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	jsonPath, err := v.jsonPath()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	f, err := os.Create(jsonPath)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	defer f.Close()
 | |
| 
 | |
| 	return v.toDisk()
 | |
| }
 | |
| 
 | |
| func (v *Volume) ToDisk() error {
 | |
| 	v.lock.Lock()
 | |
| 	defer v.lock.Unlock()
 | |
| 	return v.toDisk()
 | |
| }
 | |
| 
 | |
| func (v *Volume) toDisk() error {
 | |
| 	data, err := json.Marshal(v)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	pth, err := v.jsonPath()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	return ioutil.WriteFile(pth, data, 0666)
 | |
| }
 | |
| 
 | |
| func (v *Volume) FromDisk() error {
 | |
| 	v.lock.Lock()
 | |
| 	defer v.lock.Unlock()
 | |
| 	pth, err := v.jsonPath()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	jsonSource, err := os.Open(pth)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	defer jsonSource.Close()
 | |
| 
 | |
| 	dec := json.NewDecoder(jsonSource)
 | |
| 
 | |
| 	return dec.Decode(v)
 | |
| }
 | |
| 
 | |
| func (v *Volume) jsonPath() (string, error) {
 | |
| 	return v.getRootResourcePath("config.json")
 | |
| }
 | |
| func (v *Volume) getRootResourcePath(path string) (string, error) {
 | |
| 	cleanPath := filepath.Join("/", path)
 | |
| 	return symlink.FollowSymlinkInScope(filepath.Join(v.configPath, cleanPath), v.configPath)
 | |
| }
 | |
| 
 | |
| func (v *Volume) getResourcePath(path string) (string, error) {
 | |
| 	cleanPath := filepath.Join("/", path)
 | |
| 	return symlink.FollowSymlinkInScope(filepath.Join(v.Path, cleanPath), v.Path)
 | |
| }
 |