github.com/dougm/docker@v1.5.0/volumes/volume.go (about)

     1  package volumes
     2  
     3  import (
     4  	"encoding/json"
     5  	"io"
     6  	"io/ioutil"
     7  	"os"
     8  	"path"
     9  	"path/filepath"
    10  	"sync"
    11  
    12  	"github.com/docker/docker/pkg/archive"
    13  	"github.com/docker/docker/pkg/symlink"
    14  )
    15  
    16  type Volume struct {
    17  	ID          string
    18  	Path        string
    19  	IsBindMount bool
    20  	Writable    bool
    21  	containers  map[string]struct{}
    22  	configPath  string
    23  	repository  *Repository
    24  	lock        sync.Mutex
    25  }
    26  
    27  func (v *Volume) Export(resource, name string) (io.ReadCloser, error) {
    28  	if v.IsBindMount && filepath.Base(resource) == name {
    29  		name = ""
    30  	}
    31  
    32  	basePath, err := v.getResourcePath(resource)
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  	stat, err := os.Stat(basePath)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  	var filter []string
    41  	if !stat.IsDir() {
    42  		d, f := path.Split(basePath)
    43  		basePath = d
    44  		filter = []string{f}
    45  	} else {
    46  		filter = []string{path.Base(basePath)}
    47  		basePath = path.Dir(basePath)
    48  	}
    49  	return archive.TarWithOptions(basePath, &archive.TarOptions{
    50  		Compression:  archive.Uncompressed,
    51  		Name:         name,
    52  		IncludeFiles: filter,
    53  	})
    54  }
    55  
    56  func (v *Volume) IsDir() (bool, error) {
    57  	stat, err := os.Stat(v.Path)
    58  	if err != nil {
    59  		return false, err
    60  	}
    61  
    62  	return stat.IsDir(), nil
    63  }
    64  
    65  func (v *Volume) Containers() []string {
    66  	v.lock.Lock()
    67  
    68  	var containers []string
    69  	for c := range v.containers {
    70  		containers = append(containers, c)
    71  	}
    72  
    73  	v.lock.Unlock()
    74  	return containers
    75  }
    76  
    77  func (v *Volume) RemoveContainer(containerId string) {
    78  	v.lock.Lock()
    79  	delete(v.containers, containerId)
    80  	v.lock.Unlock()
    81  }
    82  
    83  func (v *Volume) AddContainer(containerId string) {
    84  	v.lock.Lock()
    85  	v.containers[containerId] = struct{}{}
    86  	v.lock.Unlock()
    87  }
    88  
    89  func (v *Volume) initialize() error {
    90  	v.lock.Lock()
    91  	defer v.lock.Unlock()
    92  
    93  	if _, err := os.Stat(v.Path); err != nil && os.IsNotExist(err) {
    94  		if err := os.MkdirAll(v.Path, 0755); err != nil {
    95  			return err
    96  		}
    97  	}
    98  
    99  	if err := os.MkdirAll(v.configPath, 0755); err != nil {
   100  		return err
   101  	}
   102  	jsonPath, err := v.jsonPath()
   103  	if err != nil {
   104  		return err
   105  	}
   106  	f, err := os.Create(jsonPath)
   107  	if err != nil {
   108  		return err
   109  	}
   110  	defer f.Close()
   111  
   112  	return v.toDisk()
   113  }
   114  
   115  func (v *Volume) ToDisk() error {
   116  	v.lock.Lock()
   117  	defer v.lock.Unlock()
   118  	return v.toDisk()
   119  }
   120  
   121  func (v *Volume) toDisk() error {
   122  	data, err := json.Marshal(v)
   123  	if err != nil {
   124  		return err
   125  	}
   126  
   127  	pth, err := v.jsonPath()
   128  	if err != nil {
   129  		return err
   130  	}
   131  
   132  	return ioutil.WriteFile(pth, data, 0666)
   133  }
   134  
   135  func (v *Volume) FromDisk() error {
   136  	v.lock.Lock()
   137  	defer v.lock.Unlock()
   138  	pth, err := v.jsonPath()
   139  	if err != nil {
   140  		return err
   141  	}
   142  
   143  	jsonSource, err := os.Open(pth)
   144  	if err != nil {
   145  		return err
   146  	}
   147  	defer jsonSource.Close()
   148  
   149  	dec := json.NewDecoder(jsonSource)
   150  
   151  	return dec.Decode(v)
   152  }
   153  
   154  func (v *Volume) jsonPath() (string, error) {
   155  	return v.getRootResourcePath("config.json")
   156  }
   157  func (v *Volume) getRootResourcePath(path string) (string, error) {
   158  	cleanPath := filepath.Join("/", path)
   159  	return symlink.FollowSymlinkInScope(filepath.Join(v.configPath, cleanPath), v.configPath)
   160  }
   161  
   162  func (v *Volume) getResourcePath(path string) (string, error) {
   163  	cleanPath := filepath.Join("/", path)
   164  	return symlink.FollowSymlinkInScope(filepath.Join(v.Path, cleanPath), v.Path)
   165  }