podman
79 строк · 2.1 Кб
1package parse2
3import (4"fmt"5"path/filepath"6"strings"7
8"github.com/containers/common/pkg/parse"9"github.com/containers/storage/pkg/fileutils"10specs "github.com/opencontainers/runtime-spec/specs-go"11)
12
13// ValidateVolumeMountHostDir validates the host path of buildah --volume
14func ValidateVolumeMountHostDir(hostDir string) error {15if !filepath.IsAbs(hostDir) {16return fmt.Errorf("invalid host path, must be an absolute path %q", hostDir)17}18if err := fileutils.Exists(hostDir); err != nil {19return err20}21return nil22}
23
24// RevertEscapedColon converts "\:" to ":"
25func RevertEscapedColon(source string) string {26return strings.ReplaceAll(source, "\\:", ":")27}
28
29// SplitStringWithColonEscape splits string into slice by colon. Backslash-escaped colon (i.e. "\:") will not be regarded as separator
30func SplitStringWithColonEscape(str string) []string {31result := make([]string, 0, 3)32sb := &strings.Builder{}33for idx, r := range str {34if r == ':' {35// the colon is backslash-escaped36if idx-1 > 0 && str[idx-1] == '\\' {37sb.WriteRune(r)38} else {39// os.Stat will fail if path contains escaped colon40result = append(result, RevertEscapedColon(sb.String()))41sb.Reset()42}43} else {44sb.WriteRune(r)45}46}47if sb.Len() > 0 {48result = append(result, RevertEscapedColon(sb.String()))49}50return result51}
52
53// Volume parses the input of --volume
54func Volume(volume string) (specs.Mount, error) {55mount := specs.Mount{}56arr := SplitStringWithColonEscape(volume)57if len(arr) < 2 {58return mount, fmt.Errorf("incorrect volume format %q, should be host-dir:ctr-dir[:option]", volume)59}60if err := ValidateVolumeMountHostDir(arr[0]); err != nil {61return mount, err62}63if err := parse.ValidateVolumeCtrDir(arr[1]); err != nil {64return mount, err65}66mountOptions := ""67if len(arr) > 2 {68mountOptions = arr[2]69if _, err := parse.ValidateVolumeOpts(strings.Split(arr[2], ",")); err != nil {70return mount, err71}72}73mountOpts := strings.Split(mountOptions, ",")74mount.Source = arr[0]75mount.Destination = arr[1]76mount.Type = "rbind"77mount.Options = mountOpts78return mount, nil79}
80