mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
volume/mounts: pre-compile regular expressions
Compile the regular expression, instead of 'ad-hoc'. For this to work, I moved the splitting was moved out of parseMountRaw() into ParseMountRaw(), and the former was renamed to parseMount(). This function still receives the 'raw' string, as it's used to include the "raw" spec for inclusion in error messages. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
12f1b3ce43
commit
efb87ad106
2 changed files with 40 additions and 30 deletions
|
@ -3,6 +3,7 @@ package mounts // import "github.com/docker/docker/volume/mounts"
|
|||
import (
|
||||
"errors"
|
||||
"path"
|
||||
"regexp"
|
||||
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
)
|
||||
|
@ -24,6 +25,11 @@ func NewLCOWParser() Parser {
|
|||
// - Drive cannot be c: (explicitly checked in code, not RegEx)
|
||||
const rxLCOWDestination = `(?P<destination>/(?:[^\\/:*?"<>\r\n]+[/]?)*)`
|
||||
|
||||
var (
|
||||
lcowMountDestinationRegex = regexp.MustCompile(`^` + rxLCOWDestination + `$`)
|
||||
lcowSplitRawSpec = regexp.MustCompile(`^` + rxSource + rxLCOWDestination + rxMode + `$`)
|
||||
)
|
||||
|
||||
var lcowSpecificValidators mountValidator = func(m *mount.Mount) error {
|
||||
if path.Clean(m.Target) == "/" {
|
||||
return ErrVolumeTargetIsRoot
|
||||
|
@ -39,13 +45,17 @@ type lcowParser struct {
|
|||
}
|
||||
|
||||
func (p *lcowParser) ValidateMountConfig(mnt *mount.Mount) error {
|
||||
return p.validateMountConfigReg(mnt, rxLCOWDestination, lcowSpecificValidators)
|
||||
return p.validateMountConfigReg(mnt, lcowMountDestinationRegex, lcowSpecificValidators)
|
||||
}
|
||||
|
||||
func (p *lcowParser) ParseMountRaw(raw, volumeDriver string) (*MountPoint, error) {
|
||||
return p.parseMountRaw(raw, volumeDriver, rxLCOWDestination, false, lcowSpecificValidators)
|
||||
arr, err := p.windowsSplitRawSpec(raw, lcowSplitRawSpec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p.parseMount(arr, raw, volumeDriver, lcowMountDestinationRegex, false, lcowSpecificValidators)
|
||||
}
|
||||
|
||||
func (p *lcowParser) ParseMountSpec(cfg mount.Mount) (*MountPoint, error) {
|
||||
return p.parseMountSpec(cfg, rxLCOWDestination, false, lcowSpecificValidators)
|
||||
return p.parseMountSpec(cfg, lcowMountDestinationRegex, false, lcowSpecificValidators)
|
||||
}
|
||||
|
|
|
@ -78,12 +78,18 @@ const (
|
|||
rxMode = `(:(?P<mode>(?i)ro|rw))?`
|
||||
)
|
||||
|
||||
var (
|
||||
volumeNameRegexp = regexp.MustCompile(`^` + rxName + `$`)
|
||||
reservedNameRegexp = regexp.MustCompile(`^` + rxReservedNames + `$`)
|
||||
hostDirRegexp = regexp.MustCompile(`^` + rxHostDir + `$`)
|
||||
mountDestinationRegexp = regexp.MustCompile(`^` + rxDestination + `$`)
|
||||
windowsSplitRawSpecRegexp = regexp.MustCompile(`^` + rxSource + rxDestination + rxMode + `$`)
|
||||
)
|
||||
|
||||
type mountValidator func(mnt *mount.Mount) error
|
||||
|
||||
func (p *windowsParser) windowsSplitRawSpec(raw, destRegex string) ([]string, error) {
|
||||
specExp := regexp.MustCompile(`^` + rxSource + destRegex + rxMode + `$`)
|
||||
match := specExp.FindStringSubmatch(strings.ToLower(raw))
|
||||
|
||||
func (p *windowsParser) windowsSplitRawSpec(raw string, splitRegexp *regexp.Regexp) ([]string, error) {
|
||||
match := splitRegexp.FindStringSubmatch(strings.ToLower(raw))
|
||||
// Must have something back
|
||||
if len(match) == 0 {
|
||||
return nil, errInvalidSpec(raw)
|
||||
|
@ -92,7 +98,7 @@ func (p *windowsParser) windowsSplitRawSpec(raw, destRegex string) ([]string, er
|
|||
var split []string
|
||||
matchgroups := make(map[string]string)
|
||||
// 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])
|
||||
}
|
||||
if source, exists := matchgroups["source"]; exists {
|
||||
|
@ -115,11 +121,8 @@ func (p *windowsParser) windowsSplitRawSpec(raw, destRegex string) ([]string, er
|
|||
// 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.
|
||||
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"])
|
||||
}
|
||||
} else {
|
||||
|
@ -153,14 +156,14 @@ 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)) {
|
||||
func windowsValidateRegex(p string, r *regexp.Regexp) error {
|
||||
if r.MatchString(strings.ToLower(p)) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("invalid mount path: '%s'", p)
|
||||
}
|
||||
func windowsValidateAbsolute(p string) error {
|
||||
if err := windowsValidateRegex(p, rxDestination); err != nil {
|
||||
if err := windowsValidateRegex(p, mountDestinationRegexp); err != nil {
|
||||
return fmt.Errorf("invalid mount path: '%s' mount path must be absolute", p)
|
||||
}
|
||||
return nil
|
||||
|
@ -169,7 +172,7 @@ func windowsValidateAbsolute(p string) error {
|
|||
func windowsDetectMountType(p string) mount.Type {
|
||||
if strings.HasPrefix(p, `\\.\pipe\`) {
|
||||
return mount.TypeNamedPipe
|
||||
} else if regexp.MustCompile(`^` + rxHostDir + `$`).MatchString(p) {
|
||||
} else if hostDirRegexp.MatchString(p) {
|
||||
return mount.TypeBind
|
||||
} else {
|
||||
return mount.TypeVolume
|
||||
|
@ -182,18 +185,16 @@ func (p *windowsParser) ReadWrite(mode string) bool {
|
|||
|
||||
// ValidateVolumeName checks a volume name in a platform specific manner.
|
||||
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")
|
||||
}
|
||||
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 nil
|
||||
}
|
||||
func (p *windowsParser) ValidateMountConfig(mnt *mount.Mount) error {
|
||||
return p.validateMountConfigReg(mnt, rxDestination, windowsSpecificValidators)
|
||||
return p.validateMountConfigReg(mnt, mountDestinationRegexp, windowsSpecificValidators)
|
||||
}
|
||||
|
||||
type fileInfoProvider interface {
|
||||
|
@ -214,7 +215,7 @@ func (defaultFileInfoProvider) fileInfo(path string) (exist, isDir bool, err err
|
|||
return true, fi.IsDir(), nil
|
||||
}
|
||||
|
||||
func (p *windowsParser) validateMountConfigReg(mnt *mount.Mount, destRegex string, additionalValidators ...mountValidator) error {
|
||||
func (p *windowsParser) validateMountConfigReg(mnt *mount.Mount, destRegex *regexp.Regexp, additionalValidators ...mountValidator) error {
|
||||
|
||||
for _, v := range additionalValidators {
|
||||
if err := v(mnt); err != nil {
|
||||
|
@ -299,15 +300,14 @@ func (p *windowsParser) validateMountConfigReg(mnt *mount.Mount, destRegex strin
|
|||
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)
|
||||
arr, err := p.windowsSplitRawSpec(raw, windowsSplitRawSpecRegexp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p.parseMount(arr, raw, volumeDriver, mountDestinationRegexp, true, windowsSpecificValidators)
|
||||
}
|
||||
|
||||
func (p *windowsParser) parseMount(arr []string, raw, volumeDriver string, destRegex *regexp.Regexp, convertTargetToBackslash bool, additionalValidators ...mountValidator) (*MountPoint, error) {
|
||||
var spec mount.Mount
|
||||
var mode string
|
||||
switch len(arr) {
|
||||
|
@ -367,9 +367,9 @@ func (p *windowsParser) parseMountRaw(raw, volumeDriver, destRegex string, conve
|
|||
}
|
||||
|
||||
func (p *windowsParser) ParseMountSpec(cfg mount.Mount) (*MountPoint, error) {
|
||||
return p.parseMountSpec(cfg, rxDestination, true, windowsSpecificValidators)
|
||||
return p.parseMountSpec(cfg, mountDestinationRegexp, true, windowsSpecificValidators)
|
||||
}
|
||||
func (p *windowsParser) parseMountSpec(cfg mount.Mount, destRegex string, convertTargetToBackslash bool, additionalValidators ...mountValidator) (*MountPoint, error) {
|
||||
func (p *windowsParser) parseMountSpec(cfg mount.Mount, destRegex *regexp.Regexp, convertTargetToBackslash bool, additionalValidators ...mountValidator) (*MountPoint, error) {
|
||||
if err := p.validateMountConfigReg(&cfg, destRegex, additionalValidators...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue