github.com/secure-build/gitlab-runner@v12.5.0+incompatible/executors/docker/internal/volumes/parser/windows_parser.go (about) 1 // +build windows 2 3 package parser 4 5 import ( 6 "regexp" 7 8 "gitlab.com/gitlab-org/gitlab-runner/helpers/path" 9 ) 10 11 // The specification of regular expression used for parsing Windows volumes 12 // specification was taken from: 13 // 14 // https://github.com/docker/engine/blob/a79fabbfe84117696a19671f4aa88b82d0f64fc1/volume/mounts/windows_parser.go 15 // 16 // The original source is licensed under Apache License 2.0 and the copyright for it 17 // goes to Docker, Inc. 18 19 const ( 20 // Spec should be in the format [source:]destination[:mode] 21 // 22 // Examples: c:\foo bar:d:rw 23 // c:\foo:d:\bar 24 // myname:d: 25 // d:\ 26 // 27 // Explanation of this regex! Thanks @thaJeztah on IRC and gist for help. See 28 // https://gist.github.com/thaJeztah/6185659e4978789fb2b2. A good place to 29 // test is https://regex-golang.appspot.com/assets/html/index.html 30 // 31 // Useful link for referencing named capturing groups: 32 // http://stackoverflow.com/questions/20750843/using-named-matches-from-go-regex 33 // 34 // There are three match groups: source, destination and mode. 35 // 36 37 // windowsHostDir is the first option of a source 38 windowsHostDir = `(?:\\\\\?\\)?[a-z]:[\\/](?:[^\\/:*?"<>|\r\n]+[\\/]?)*` 39 // windowsVolumeName is the second option of a source 40 windowsVolumeName = `[^\\/:*?"<>|\r\n]+` 41 // windowsPipe is a named path pipe (starts with `\\.\pipe\`, possibly with / instead of \) 42 windowsPipe = `[/\\]{2}.[/\\]pipe[/\\][^:*?"<>|\r\n]+` 43 // windowsSource is the combined possibilities for a source 44 windowsSource = `((?P<source>((` + windowsHostDir + `)|(` + windowsVolumeName + `)|(` + windowsPipe + `))):)?` 45 46 // Source. Can be either a host directory, a name, or omitted: 47 // HostDir: 48 // - Essentially using the folder solution from 49 // https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9781449327453/ch08s18.html 50 // but adding case insensitivity. 51 // - Must be an absolute path such as c:\path 52 // - Can include spaces such as `c:\program files` 53 // - And then followed by a colon which is not in the capture group 54 // - And can be optional 55 // Name: 56 // - Must not contain invalid NTFS filename characters (https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx) 57 // - And then followed by a colon which is not in the capture group 58 // - And can be optional 59 60 // windowsDestination is the regex expression for the mount destination 61 windowsDestination = `(?P<destination>((?:\\\\\?\\)?([a-z]):((?:[\\/][^\\/:*?"<>\r\n]+)*[\\/]?))|(` + windowsPipe + `))` 62 63 // windowsMode is the regex expression for the mode of the mount 64 // Mode (optional): 65 // - Hopefully self explanatory in comparison to above regex's. 66 // - Colon is not in the capture group 67 windowsMode = `(:(?P<mode>(?i)ro|rw))?` 68 ) 69 70 type windowsParser struct { 71 baseParser 72 } 73 74 func NewWindowsParser() Parser { 75 return &windowsParser{ 76 baseParser: baseParser{ 77 path: path.NewWindowsPath(), 78 }, 79 } 80 } 81 82 func (p *windowsParser) ParseVolume(spec string) (*Volume, error) { 83 specExp := regexp.MustCompile(`(?i)^` + windowsSource + windowsDestination + windowsMode + `$`) 84 85 parts, err := p.matchesToVolumeSpecParts(spec, specExp) 86 if err != nil { 87 return nil, err 88 } 89 90 return newVolume(parts["source"], parts["destination"], parts["mode"], ""), nil 91 }