From 1ad6f9af1552cbe2119af6cda83db5b3908556db Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Wed, 19 Dec 2018 15:26:08 -0500 Subject: Allow users to specify a directory for additonal devices Podman will search through the directory and will add any device nodes that it finds. If no devices are found we return an error. Signed-off-by: Daniel J Walsh --- pkg/spec/config_linux.go | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ pkg/spec/spec.go | 4 ++-- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/pkg/spec/config_linux.go b/pkg/spec/config_linux.go index 5bf8eff43..f3e200262 100644 --- a/pkg/spec/config_linux.go +++ b/pkg/spec/config_linux.go @@ -3,7 +3,11 @@ package createconfig import ( + "fmt" "io/ioutil" + "os" + "path/filepath" + "strings" "github.com/docker/docker/profiles/seccomp" "github.com/opencontainers/runc/libcontainer/configs" @@ -27,6 +31,52 @@ func Device(d *configs.Device) spec.LinuxDevice { } } +// devicesFromPath computes a list of devices +func devicesFromPath(g *generate.Generator, devicePath string) error { + devs := strings.Split(devicePath, ":") + resolvedDevicePath := devs[0] + // check if it is a symbolic link + if src, err := os.Lstat(resolvedDevicePath); err == nil && src.Mode()&os.ModeSymlink == os.ModeSymlink { + if linkedPathOnHost, err := filepath.EvalSymlinks(resolvedDevicePath); err == nil { + resolvedDevicePath = linkedPathOnHost + } + } + st, err := os.Stat(resolvedDevicePath) + if err != nil { + return errors.Wrapf(err, "cannot stat %s", devicePath) + } + if st.IsDir() { + if len(devs) > 2 { + return errors.Wrapf(unix.EINVAL, "not allowed to specify destination with a directory %s", devicePath) + } + found := false + // mount the internal devices recursively + if err := filepath.Walk(resolvedDevicePath, func(dpath string, f os.FileInfo, e error) error { + + if f.Mode()&os.ModeDevice == os.ModeDevice { + found = true + device := dpath + + if len(devs) > 1 { + device = fmt.Sprintf("%s:%s", dpath, devs[1]) + } + if err := addDevice(g, device); err != nil { + return errors.Wrapf(err, "failed to add %s device", dpath) + } + } + return nil + }); err != nil { + return err + } + if !found { + return errors.Wrapf(unix.EINVAL, "no devices found in %s", devicePath) + } + return nil + } + + return addDevice(g, devicePath) +} + func addDevice(g *generate.Generator, device string) error { src, dst, permissions, err := ParseDevice(device) if err != nil { diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 05be00864..c90f16f7c 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -235,8 +235,8 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint } } } else { - for _, device := range config.Devices { - if err := addDevice(&g, device); err != nil { + for _, devicePath := range config.Devices { + if err := devicesFromPath(&g, devicePath); err != nil { return nil, err } } -- cgit v1.2.3-54-g00ecf