github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/volume/volume_unix.go (about)

     1  // +build linux freebsd darwin solaris
     2  
     3  package volume
     4  
     5  import (
     6  	"fmt"
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  
    11  	mounttypes "github.com/docker/docker/api/types/mount"
    12  )
    13  
    14  var platformRawValidationOpts = []func(o *validateOpts){
    15  	// need to make sure to not error out if the bind source does not exist on unix
    16  	// this is supported for historical reasons, the path will be automatically
    17  	// created later.
    18  	func(o *validateOpts) { o.skipBindSourceCheck = true },
    19  }
    20  
    21  // read-write modes
    22  var rwModes = map[string]bool{
    23  	"rw": true,
    24  	"ro": true,
    25  }
    26  
    27  // label modes
    28  var labelModes = map[string]bool{
    29  	"Z": true,
    30  	"z": true,
    31  }
    32  
    33  // consistency modes
    34  var consistencyModes = map[mounttypes.Consistency]bool{
    35  	mounttypes.ConsistencyFull:      true,
    36  	mounttypes.ConsistencyCached:    true,
    37  	mounttypes.ConsistencyDelegated: true,
    38  }
    39  
    40  // BackwardsCompatible decides whether this mount point can be
    41  // used in old versions of Docker or not.
    42  // Only bind mounts and local volumes can be used in old versions of Docker.
    43  func (m *MountPoint) BackwardsCompatible() bool {
    44  	return len(m.Source) > 0 || m.Driver == DefaultDriverName
    45  }
    46  
    47  // HasResource checks whether the given absolute path for a container is in
    48  // this mount point. If the relative path starts with `../` then the resource
    49  // is outside of this mount point, but we can't simply check for this prefix
    50  // because it misses `..` which is also outside of the mount, so check both.
    51  func (m *MountPoint) HasResource(absolutePath string) bool {
    52  	relPath, err := filepath.Rel(m.Destination, absolutePath)
    53  	return err == nil && relPath != ".." && !strings.HasPrefix(relPath, fmt.Sprintf("..%c", filepath.Separator))
    54  }
    55  
    56  // IsVolumeNameValid checks a volume name in a platform specific manner.
    57  func IsVolumeNameValid(name string) (bool, error) {
    58  	return true, nil
    59  }
    60  
    61  // ValidMountMode will make sure the mount mode is valid.
    62  // returns if it's a valid mount mode or not.
    63  func ValidMountMode(mode string) bool {
    64  	if mode == "" {
    65  		return true
    66  	}
    67  
    68  	rwModeCount := 0
    69  	labelModeCount := 0
    70  	propagationModeCount := 0
    71  	copyModeCount := 0
    72  	consistencyModeCount := 0
    73  
    74  	for _, o := range strings.Split(mode, ",") {
    75  		switch {
    76  		case rwModes[o]:
    77  			rwModeCount++
    78  		case labelModes[o]:
    79  			labelModeCount++
    80  		case propagationModes[mounttypes.Propagation(o)]:
    81  			propagationModeCount++
    82  		case copyModeExists(o):
    83  			copyModeCount++
    84  		case consistencyModes[mounttypes.Consistency(o)]:
    85  			consistencyModeCount++
    86  		default:
    87  			return false
    88  		}
    89  	}
    90  
    91  	// Only one string for each mode is allowed.
    92  	if rwModeCount > 1 || labelModeCount > 1 || propagationModeCount > 1 || copyModeCount > 1 || consistencyModeCount > 1 {
    93  		return false
    94  	}
    95  	return true
    96  }
    97  
    98  // ReadWrite tells you if a mode string is a valid read-write mode or not.
    99  // If there are no specifications w.r.t read write mode, then by default
   100  // it returns true.
   101  func ReadWrite(mode string) bool {
   102  	if !ValidMountMode(mode) {
   103  		return false
   104  	}
   105  
   106  	for _, o := range strings.Split(mode, ",") {
   107  		if o == "ro" {
   108  			return false
   109  		}
   110  	}
   111  	return true
   112  }
   113  
   114  func validateNotRoot(p string) error {
   115  	p = filepath.Clean(convertSlash(p))
   116  	if p == "/" {
   117  		return fmt.Errorf("invalid specification: destination can't be '/'")
   118  	}
   119  	return nil
   120  }
   121  
   122  func validateCopyMode(mode bool) error {
   123  	return nil
   124  }
   125  
   126  func convertSlash(p string) string {
   127  	return filepath.ToSlash(p)
   128  }
   129  
   130  func splitRawSpec(raw string) ([]string, error) {
   131  	if strings.Count(raw, ":") > 2 {
   132  		return nil, errInvalidSpec(raw)
   133  	}
   134  
   135  	arr := strings.SplitN(raw, ":", 3)
   136  	if arr[0] == "" {
   137  		return nil, errInvalidSpec(raw)
   138  	}
   139  	return arr, nil
   140  }
   141  
   142  func clean(p string) string {
   143  	return filepath.Clean(p)
   144  }
   145  
   146  func validateStat(fi os.FileInfo) error {
   147  	return nil
   148  }