github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/oci/devices_linux.go (about) 1 package oci // import "github.com/docker/docker/oci" 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "strings" 8 9 "github.com/opencontainers/runc/libcontainer/devices" 10 specs "github.com/opencontainers/runtime-spec/specs-go" 11 "golang.org/x/sys/unix" 12 ) 13 14 // Device transforms a libcontainer devices.Device to a specs.LinuxDevice object. 15 func Device(d *devices.Device) specs.LinuxDevice { 16 return specs.LinuxDevice{ 17 Type: string(d.Type), 18 Path: d.Path, 19 Major: d.Major, 20 Minor: d.Minor, 21 FileMode: fmPtr(int64(d.FileMode &^ unix.S_IFMT)), // strip file type, as OCI spec only expects file-mode to be included 22 UID: u32Ptr(int64(d.Uid)), 23 GID: u32Ptr(int64(d.Gid)), 24 } 25 } 26 27 func deviceCgroup(d *devices.Device) specs.LinuxDeviceCgroup { 28 return specs.LinuxDeviceCgroup{ 29 Allow: true, 30 Type: string(d.Type), 31 Major: &d.Major, 32 Minor: &d.Minor, 33 Access: string(d.Permissions), 34 } 35 } 36 37 // DevicesFromPath computes a list of devices and device permissions from paths (pathOnHost and pathInContainer) and cgroup permissions. 38 func DevicesFromPath(pathOnHost, pathInContainer, cgroupPermissions string) (devs []specs.LinuxDevice, devPermissions []specs.LinuxDeviceCgroup, err error) { 39 resolvedPathOnHost := pathOnHost 40 41 // check if it is a symbolic link 42 if src, e := os.Lstat(pathOnHost); e == nil && src.Mode()&os.ModeSymlink == os.ModeSymlink { 43 if linkedPathOnHost, e := filepath.EvalSymlinks(pathOnHost); e == nil { 44 resolvedPathOnHost = linkedPathOnHost 45 } 46 } 47 48 device, err := devices.DeviceFromPath(resolvedPathOnHost, cgroupPermissions) 49 // if there was no error, return the device 50 if err == nil { 51 device.Path = pathInContainer 52 return append(devs, Device(device)), append(devPermissions, deviceCgroup(device)), nil 53 } 54 55 // if the device is not a device node 56 // try to see if it's a directory holding many devices 57 if err == devices.ErrNotADevice { 58 // check if it is a directory 59 if src, e := os.Stat(resolvedPathOnHost); e == nil && src.IsDir() { 60 // mount the internal devices recursively 61 // TODO check if additional errors should be handled or logged 62 _ = filepath.Walk(resolvedPathOnHost, func(dpath string, f os.FileInfo, _ error) error { 63 childDevice, e := devices.DeviceFromPath(dpath, cgroupPermissions) 64 if e != nil { 65 // ignore the device 66 return nil 67 } 68 69 // add the device to userSpecified devices 70 childDevice.Path = strings.Replace(dpath, resolvedPathOnHost, pathInContainer, 1) 71 devs = append(devs, Device(childDevice)) 72 devPermissions = append(devPermissions, deviceCgroup(childDevice)) 73 74 return nil 75 }) 76 } 77 } 78 79 if len(devs) > 0 { 80 return devs, devPermissions, nil 81 } 82 83 return devs, devPermissions, fmt.Errorf("error gathering device information while adding custom device %q: %s", pathOnHost, err) 84 }