summaryrefslogtreecommitdiff
path: root/vendor
diff options
context:
space:
mode:
Diffstat (limited to 'vendor')
-rw-r--r--vendor/github.com/containers/common/pkg/parse/parse.go157
-rw-r--r--vendor/github.com/containers/common/pkg/parse/parse_unix.go51
-rw-r--r--vendor/modules.txt1
3 files changed, 209 insertions, 0 deletions
diff --git a/vendor/github.com/containers/common/pkg/parse/parse.go b/vendor/github.com/containers/common/pkg/parse/parse.go
new file mode 100644
index 000000000..611b2e84b
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/parse/parse.go
@@ -0,0 +1,157 @@
+package parse
+
+// this package contains functions that parse and validate
+// user input and is shared either amongst container engine subcommands
+
+import (
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/pkg/errors"
+)
+
+// ValidateVolumeOpts validates a volume's options
+func ValidateVolumeOpts(options []string) ([]string, error) {
+ var foundRootPropagation, foundRWRO, foundLabelChange, bindType, foundExec, foundDev, foundSuid int
+ finalOpts := make([]string, 0, len(options))
+ for _, opt := range options {
+ switch opt {
+ case "noexec", "exec":
+ foundExec++
+ if foundExec > 1 {
+ return nil, errors.Errorf("invalid options %q, can only specify 1 'noexec' or 'exec' option", strings.Join(options, ", "))
+ }
+ case "nodev", "dev":
+ foundDev++
+ if foundDev > 1 {
+ return nil, errors.Errorf("invalid options %q, can only specify 1 'nodev' or 'dev' option", strings.Join(options, ", "))
+ }
+ case "nosuid", "suid":
+ foundSuid++
+ if foundSuid > 1 {
+ return nil, errors.Errorf("invalid options %q, can only specify 1 'nosuid' or 'suid' option", strings.Join(options, ", "))
+ }
+ case "rw", "ro":
+ foundRWRO++
+ if foundRWRO > 1 {
+ return nil, errors.Errorf("invalid options %q, can only specify 1 'rw' or 'ro' option", strings.Join(options, ", "))
+ }
+ case "z", "Z", "O":
+ foundLabelChange++
+ if foundLabelChange > 1 {
+ return nil, errors.Errorf("invalid options %q, can only specify 1 'z', 'Z', or 'O' option", strings.Join(options, ", "))
+ }
+ case "private", "rprivate", "shared", "rshared", "slave", "rslave", "unbindable", "runbindable":
+ foundRootPropagation++
+ if foundRootPropagation > 1 {
+ return nil, errors.Errorf("invalid options %q, can only specify 1 '[r]shared', '[r]private', '[r]slave' or '[r]unbindable' option", strings.Join(options, ", "))
+ }
+ case "bind", "rbind":
+ bindType++
+ if bindType > 1 {
+ return nil, errors.Errorf("invalid options %q, can only specify 1 '[r]bind' option", strings.Join(options, ", "))
+ }
+ case "cached", "delegated":
+ // The discarded ops are OS X specific volume options
+ // introduced in a recent Docker version.
+ // They have no meaning on Linux, so here we silently
+ // drop them. This matches Docker's behavior (the options
+ // are intended to be always safe to use, even not on OS
+ // X).
+ continue
+ default:
+ return nil, errors.Errorf("invalid option type %q", opt)
+ }
+ finalOpts = append(finalOpts, opt)
+ }
+ return finalOpts, nil
+}
+
+// Device parses device mapping string to a src, dest & permissions string
+// Valid values for device looklike:
+// '/dev/sdc"
+// '/dev/sdc:/dev/xvdc"
+// '/dev/sdc:/dev/xvdc:rwm"
+// '/dev/sdc:rm"
+func Device(device string) (src, dest, permissions string, err error) {
+ permissions = "rwm"
+ arr := strings.Split(device, ":")
+ switch len(arr) {
+ case 3:
+ if !isValidDeviceMode(arr[2]) {
+ return "", "", "", errors.Errorf("invalid device mode: %s", arr[2])
+ }
+ permissions = arr[2]
+ fallthrough
+ case 2:
+ if isValidDeviceMode(arr[1]) {
+ permissions = arr[1]
+ } else {
+ if arr[1] == "" || arr[1][0] != '/' {
+ return "", "", "", errors.Errorf("invalid device mode: %s", arr[1])
+ }
+ dest = arr[1]
+ }
+ fallthrough
+ case 1:
+ if len(arr[0]) > 0 {
+ src = arr[0]
+ break
+ }
+ fallthrough
+ default:
+ return "", "", "", errors.Errorf("invalid device specification: %s", device)
+ }
+
+ if dest == "" {
+ dest = src
+ }
+ return src, dest, permissions, nil
+}
+
+// isValidDeviceMode checks if the mode for device is valid or not.
+// isValid mode is a composition of r (read), w (write), and m (mknod).
+func isValidDeviceMode(mode string) bool {
+ var legalDeviceMode = map[rune]bool{
+ 'r': true,
+ 'w': true,
+ 'm': true,
+ }
+ if mode == "" {
+ return false
+ }
+ for _, c := range mode {
+ if !legalDeviceMode[c] {
+ return false
+ }
+ legalDeviceMode[c] = false
+ }
+ return true
+}
+
+// ValidateVolumeHostDir validates a volume mount's source directory
+func ValidateVolumeHostDir(hostDir string) error {
+ if hostDir == "" {
+ return errors.Errorf("host directory cannot be empty")
+ }
+ if filepath.IsAbs(hostDir) {
+ if _, err := os.Stat(hostDir); err != nil {
+ return errors.Wrapf(err, "error checking path %q", hostDir)
+ }
+ }
+ // If hostDir is not an absolute path, that means the user wants to create a
+ // named volume. This will be done later on in the code.
+ return nil
+}
+
+// ValidateVolumeCtrDir validates a volume mount's destination directory.
+func ValidateVolumeCtrDir(ctrDir string) error {
+ if ctrDir == "" {
+ return errors.Errorf("container directory cannot be empty")
+ }
+ if !filepath.IsAbs(ctrDir) {
+ return errors.Errorf("invalid container path %q, must be an absolute path", ctrDir)
+ }
+ return nil
+}
diff --git a/vendor/github.com/containers/common/pkg/parse/parse_unix.go b/vendor/github.com/containers/common/pkg/parse/parse_unix.go
new file mode 100644
index 000000000..880fbf674
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/parse/parse_unix.go
@@ -0,0 +1,51 @@
+// +build linux darwin
+
+package parse
+
+import (
+ "os"
+ "path/filepath"
+
+ "github.com/containers/storage/pkg/unshare"
+ "github.com/opencontainers/runc/libcontainer/configs"
+ "github.com/opencontainers/runc/libcontainer/devices"
+ "github.com/pkg/errors"
+)
+
+func DeviceFromPath(device string) ([]configs.Device, error) {
+ var devs []configs.Device
+ src, dst, permissions, err := Device(device)
+ if err != nil {
+ return nil, err
+ }
+ if unshare.IsRootless() && src != dst {
+ return nil, errors.Errorf("Renaming device %s to %s is not supported in rootless containers", src, dst)
+ }
+ srcInfo, err := os.Stat(src)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error getting info of source device %s", src)
+ }
+
+ if !srcInfo.IsDir() {
+
+ dev, err := devices.DeviceFromPath(src, permissions)
+ if err != nil {
+ return nil, errors.Wrapf(err, "%s is not a valid device", src)
+ }
+ dev.Path = dst
+ devs = append(devs, *dev)
+ return devs, nil
+ }
+
+ // If source device is a directory
+ srcDevices, err := devices.GetDevices(src)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error getting source devices from directory %s", src)
+ }
+ for _, d := range srcDevices {
+ d.Path = filepath.Join(dst, filepath.Base(d.Path))
+ d.Permissions = configs.DevicePermissions(permissions)
+ devs = append(devs, *d)
+ }
+ return devs, nil
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index e15b16188..a7c3b628a 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -97,6 +97,7 @@ github.com/containers/common/pkg/capabilities
github.com/containers/common/pkg/cgroupv2
github.com/containers/common/pkg/completion
github.com/containers/common/pkg/config
+github.com/containers/common/pkg/parse
github.com/containers/common/pkg/report
github.com/containers/common/pkg/report/camelcase
github.com/containers/common/pkg/retry