|
@@ -78,13 +78,18 @@ const (
|
|
rxMode = `(:(?P<mode>(?i)ro|rw))?`
|
|
rxMode = `(:(?P<mode>(?i)ro|rw))?`
|
|
)
|
|
)
|
|
|
|
|
|
-type mountValidator func(mnt *mount.Mount) error
|
|
|
|
|
|
+var (
|
|
|
|
+ volumeNameRegexp = regexp.MustCompile(`^` + rxName + `$`)
|
|
|
|
+ reservedNameRegexp = regexp.MustCompile(`^` + rxReservedNames + `$`)
|
|
|
|
+ hostDirRegexp = regexp.MustCompile(`^` + rxHostDir + `$`)
|
|
|
|
+ mountDestinationRegexp = regexp.MustCompile(`^` + rxDestination + `$`)
|
|
|
|
+ windowsSplitRawSpecRegexp = regexp.MustCompile(`^` + rxSource + rxDestination + rxMode + `$`)
|
|
|
|
+)
|
|
|
|
|
|
-func (p *windowsParser) windowsSplitRawSpec(raw, destRegex string) ([]string, error) {
|
|
|
|
- specExp := regexp.MustCompile(`^` + rxSource + destRegex + rxMode + `$`)
|
|
|
|
- match := specExp.FindStringSubmatch(strings.ToLower(raw))
|
|
|
|
|
|
+type mountValidator func(mnt *mount.Mount) error
|
|
|
|
|
|
- // Must have something back
|
|
|
|
|
|
+func (p *windowsParser) splitRawSpec(raw string, splitRegexp *regexp.Regexp) ([]string, error) {
|
|
|
|
+ match := splitRegexp.FindStringSubmatch(strings.ToLower(raw))
|
|
if len(match) == 0 {
|
|
if len(match) == 0 {
|
|
return nil, errInvalidSpec(raw)
|
|
return nil, errInvalidSpec(raw)
|
|
}
|
|
}
|
|
@@ -92,7 +97,7 @@ func (p *windowsParser) windowsSplitRawSpec(raw, destRegex string) ([]string, er
|
|
var split []string
|
|
var split []string
|
|
matchgroups := make(map[string]string)
|
|
matchgroups := make(map[string]string)
|
|
// Pull out the sub expressions from the named capture groups
|
|
// Pull out the sub expressions from the named capture groups
|
|
- for i, name := range specExp.SubexpNames() {
|
|
|
|
|
|
+ for i, name := range splitRegexp.SubexpNames() {
|
|
matchgroups[name] = strings.ToLower(match[i])
|
|
matchgroups[name] = strings.ToLower(match[i])
|
|
}
|
|
}
|
|
if source, exists := matchgroups["source"]; exists {
|
|
if source, exists := matchgroups["source"]; exists {
|
|
@@ -115,11 +120,8 @@ func (p *windowsParser) windowsSplitRawSpec(raw, destRegex string) ([]string, er
|
|
// situation where the user intention was to map a file into a container through
|
|
// situation where the user intention was to map a file into a container through
|
|
// a local volume, but this is not supported by the platform.
|
|
// a local volume, but this is not supported by the platform.
|
|
if matchgroups["source"] == "" && matchgroups["destination"] != "" {
|
|
if matchgroups["source"] == "" && matchgroups["destination"] != "" {
|
|
- volExp := regexp.MustCompile(`^` + rxName + `$`)
|
|
|
|
- reservedNameExp := regexp.MustCompile(`^` + rxReservedNames + `$`)
|
|
|
|
-
|
|
|
|
- if volExp.MatchString(matchgroups["destination"]) {
|
|
|
|
- if reservedNameExp.MatchString(matchgroups["destination"]) {
|
|
|
|
|
|
+ if volumeNameRegexp.MatchString(matchgroups["destination"]) {
|
|
|
|
+ if reservedNameRegexp.MatchString(matchgroups["destination"]) {
|
|
return nil, fmt.Errorf("volume name %q cannot be a reserved word for Windows filenames", matchgroups["destination"])
|
|
return nil, fmt.Errorf("volume name %q cannot be a reserved word for Windows filenames", matchgroups["destination"])
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
@@ -149,18 +151,18 @@ func windowsValidateNotRoot(p string) error {
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
-var windowsSpecificValidators mountValidator = func(mnt *mount.Mount) error {
|
|
|
|
- return windowsValidateNotRoot(mnt.Target)
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func windowsValidateRegex(p, r string) error {
|
|
|
|
- if regexp.MustCompile(`^` + r + `$`).MatchString(strings.ToLower(p)) {
|
|
|
|
- return nil
|
|
|
|
|
|
+var windowsValidators mountValidator = func(m *mount.Mount) error {
|
|
|
|
+ if err := windowsValidateNotRoot(m.Target); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ if !mountDestinationRegexp.MatchString(strings.ToLower(m.Target)) {
|
|
|
|
+ return fmt.Errorf("invalid mount path: '%s'", m.Target)
|
|
}
|
|
}
|
|
- return fmt.Errorf("invalid mount path: '%s'", p)
|
|
|
|
|
|
+ return nil
|
|
}
|
|
}
|
|
|
|
+
|
|
func windowsValidateAbsolute(p string) error {
|
|
func windowsValidateAbsolute(p string) error {
|
|
- if err := windowsValidateRegex(p, rxDestination); err != nil {
|
|
|
|
|
|
+ if !mountDestinationRegexp.MatchString(strings.ToLower(p)) {
|
|
return fmt.Errorf("invalid mount path: '%s' mount path must be absolute", p)
|
|
return fmt.Errorf("invalid mount path: '%s' mount path must be absolute", p)
|
|
}
|
|
}
|
|
return nil
|
|
return nil
|
|
@@ -169,7 +171,7 @@ func windowsValidateAbsolute(p string) error {
|
|
func windowsDetectMountType(p string) mount.Type {
|
|
func windowsDetectMountType(p string) mount.Type {
|
|
if strings.HasPrefix(p, `\\.\pipe\`) {
|
|
if strings.HasPrefix(p, `\\.\pipe\`) {
|
|
return mount.TypeNamedPipe
|
|
return mount.TypeNamedPipe
|
|
- } else if regexp.MustCompile(`^` + rxHostDir + `$`).MatchString(p) {
|
|
|
|
|
|
+ } else if hostDirRegexp.MatchString(p) {
|
|
return mount.TypeBind
|
|
return mount.TypeBind
|
|
} else {
|
|
} else {
|
|
return mount.TypeVolume
|
|
return mount.TypeVolume
|
|
@@ -182,18 +184,16 @@ func (p *windowsParser) ReadWrite(mode string) bool {
|
|
|
|
|
|
// ValidateVolumeName checks a volume name in a platform specific manner.
|
|
// ValidateVolumeName checks a volume name in a platform specific manner.
|
|
func (p *windowsParser) ValidateVolumeName(name string) error {
|
|
func (p *windowsParser) ValidateVolumeName(name string) error {
|
|
- nameExp := regexp.MustCompile(`^` + rxName + `$`)
|
|
|
|
- if !nameExp.MatchString(name) {
|
|
|
|
|
|
+ if !volumeNameRegexp.MatchString(name) {
|
|
return errors.New("invalid volume name")
|
|
return errors.New("invalid volume name")
|
|
}
|
|
}
|
|
- nameExp = regexp.MustCompile(`^` + rxReservedNames + `$`)
|
|
|
|
- if nameExp.MatchString(name) {
|
|
|
|
|
|
+ if reservedNameRegexp.MatchString(name) {
|
|
return fmt.Errorf("volume name %q cannot be a reserved word for Windows filenames", name)
|
|
return fmt.Errorf("volume name %q cannot be a reserved word for Windows filenames", name)
|
|
}
|
|
}
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
func (p *windowsParser) ValidateMountConfig(mnt *mount.Mount) error {
|
|
func (p *windowsParser) ValidateMountConfig(mnt *mount.Mount) error {
|
|
- return p.validateMountConfigReg(mnt, rxDestination, windowsSpecificValidators)
|
|
|
|
|
|
+ return p.validateMountConfigReg(mnt, windowsValidators)
|
|
}
|
|
}
|
|
|
|
|
|
type fileInfoProvider interface {
|
|
type fileInfoProvider interface {
|
|
@@ -214,20 +214,15 @@ func (defaultFileInfoProvider) fileInfo(path string) (exist, isDir bool, err err
|
|
return true, fi.IsDir(), nil
|
|
return true, fi.IsDir(), nil
|
|
}
|
|
}
|
|
|
|
|
|
-func (p *windowsParser) validateMountConfigReg(mnt *mount.Mount, destRegex string, additionalValidators ...mountValidator) error {
|
|
|
|
-
|
|
|
|
|
|
+func (p *windowsParser) validateMountConfigReg(mnt *mount.Mount, additionalValidators ...mountValidator) error {
|
|
|
|
+ if len(mnt.Target) == 0 {
|
|
|
|
+ return &errMountConfig{mnt, errMissingField("Target")}
|
|
|
|
+ }
|
|
for _, v := range additionalValidators {
|
|
for _, v := range additionalValidators {
|
|
if err := v(mnt); err != nil {
|
|
if err := v(mnt); err != nil {
|
|
return &errMountConfig{mnt, err}
|
|
return &errMountConfig{mnt, err}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- if len(mnt.Target) == 0 {
|
|
|
|
- return &errMountConfig{mnt, errMissingField("Target")}
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if err := windowsValidateRegex(mnt.Target, destRegex); err != nil {
|
|
|
|
- return &errMountConfig{mnt, err}
|
|
|
|
- }
|
|
|
|
|
|
|
|
switch mnt.Type {
|
|
switch mnt.Type {
|
|
case mount.TypeBind:
|
|
case mount.TypeBind:
|
|
@@ -298,16 +293,16 @@ func (p *windowsParser) validateMountConfigReg(mnt *mount.Mount, destRegex strin
|
|
}
|
|
}
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
-func (p *windowsParser) ParseMountRaw(raw, volumeDriver string) (*MountPoint, error) {
|
|
|
|
- return p.parseMountRaw(raw, volumeDriver, rxDestination, true, windowsSpecificValidators)
|
|
|
|
-}
|
|
|
|
|
|
|
|
-func (p *windowsParser) parseMountRaw(raw, volumeDriver, destRegex string, convertTargetToBackslash bool, additionalValidators ...mountValidator) (*MountPoint, error) {
|
|
|
|
- arr, err := p.windowsSplitRawSpec(raw, destRegex)
|
|
|
|
|
|
+func (p *windowsParser) ParseMountRaw(raw, volumeDriver string) (*MountPoint, error) {
|
|
|
|
+ arr, err := p.splitRawSpec(raw, windowsSplitRawSpecRegexp)
|
|
if err != nil {
|
|
if err != nil {
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
+ return p.parseMount(arr, raw, volumeDriver, true, windowsValidators)
|
|
|
|
+}
|
|
|
|
|
|
|
|
+func (p *windowsParser) parseMount(arr []string, raw, volumeDriver string, convertTargetToBackslash bool, additionalValidators ...mountValidator) (*MountPoint, error) {
|
|
var spec mount.Mount
|
|
var spec mount.Mount
|
|
var mode string
|
|
var mode string
|
|
switch len(arr) {
|
|
switch len(arr) {
|
|
@@ -356,7 +351,7 @@ func (p *windowsParser) parseMountRaw(raw, volumeDriver, destRegex string, conve
|
|
spec.VolumeOptions.NoCopy = !copyData
|
|
spec.VolumeOptions.NoCopy = !copyData
|
|
}
|
|
}
|
|
|
|
|
|
- mp, err := p.parseMountSpec(spec, destRegex, convertTargetToBackslash, additionalValidators...)
|
|
|
|
|
|
+ mp, err := p.parseMountSpec(spec, convertTargetToBackslash, additionalValidators...)
|
|
if mp != nil {
|
|
if mp != nil {
|
|
mp.Mode = mode
|
|
mp.Mode = mode
|
|
}
|
|
}
|
|
@@ -367,10 +362,11 @@ func (p *windowsParser) parseMountRaw(raw, volumeDriver, destRegex string, conve
|
|
}
|
|
}
|
|
|
|
|
|
func (p *windowsParser) ParseMountSpec(cfg mount.Mount) (*MountPoint, error) {
|
|
func (p *windowsParser) ParseMountSpec(cfg mount.Mount) (*MountPoint, error) {
|
|
- return p.parseMountSpec(cfg, rxDestination, true, windowsSpecificValidators)
|
|
|
|
|
|
+ return p.parseMountSpec(cfg, true, windowsValidators)
|
|
}
|
|
}
|
|
-func (p *windowsParser) parseMountSpec(cfg mount.Mount, destRegex string, convertTargetToBackslash bool, additionalValidators ...mountValidator) (*MountPoint, error) {
|
|
|
|
- if err := p.validateMountConfigReg(&cfg, destRegex, additionalValidators...); err != nil {
|
|
|
|
|
|
+
|
|
|
|
+func (p *windowsParser) parseMountSpec(cfg mount.Mount, convertTargetToBackslash bool, additionalValidators ...mountValidator) (*MountPoint, error) {
|
|
|
|
+ if err := p.validateMountConfigReg(&cfg, additionalValidators...); err != nil {
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
mp := &MountPoint{
|
|
mp := &MountPoint{
|
|
@@ -439,21 +435,23 @@ func (p *windowsParser) ParseVolumesFrom(spec string) (string, string, error) {
|
|
}
|
|
}
|
|
|
|
|
|
func (p *windowsParser) DefaultPropagationMode() mount.Propagation {
|
|
func (p *windowsParser) DefaultPropagationMode() mount.Propagation {
|
|
- return mount.Propagation("")
|
|
|
|
|
|
+ return ""
|
|
}
|
|
}
|
|
|
|
|
|
func (p *windowsParser) ConvertTmpfsOptions(opt *mount.TmpfsOptions, readOnly bool) (string, error) {
|
|
func (p *windowsParser) ConvertTmpfsOptions(opt *mount.TmpfsOptions, readOnly bool) (string, error) {
|
|
return "", fmt.Errorf("%s does not support tmpfs", runtime.GOOS)
|
|
return "", fmt.Errorf("%s does not support tmpfs", runtime.GOOS)
|
|
}
|
|
}
|
|
|
|
+
|
|
func (p *windowsParser) DefaultCopyMode() bool {
|
|
func (p *windowsParser) DefaultCopyMode() bool {
|
|
return false
|
|
return false
|
|
}
|
|
}
|
|
|
|
+
|
|
func (p *windowsParser) IsBackwardCompatible(m *MountPoint) bool {
|
|
func (p *windowsParser) IsBackwardCompatible(m *MountPoint) bool {
|
|
return false
|
|
return false
|
|
}
|
|
}
|
|
|
|
|
|
func (p *windowsParser) ValidateTmpfsMountDestination(dest string) error {
|
|
func (p *windowsParser) ValidateTmpfsMountDestination(dest string) error {
|
|
- return errors.New("Platform does not support tmpfs")
|
|
|
|
|
|
+ return errors.New("platform does not support tmpfs")
|
|
}
|
|
}
|
|
|
|
|
|
func (p *windowsParser) HasResource(m *MountPoint, absolutePath string) bool {
|
|
func (p *windowsParser) HasResource(m *MountPoint, absolutePath string) bool {
|