devices_linux.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. package oci // import "github.com/docker/docker/oci"
  2. import (
  3. "fmt"
  4. "os"
  5. "path/filepath"
  6. "strings"
  7. coci "github.com/containerd/containerd/oci"
  8. specs "github.com/opencontainers/runtime-spec/specs-go"
  9. )
  10. func deviceCgroup(d *specs.LinuxDevice, permissions string) specs.LinuxDeviceCgroup {
  11. return specs.LinuxDeviceCgroup{
  12. Allow: true,
  13. Type: d.Type,
  14. Major: &d.Major,
  15. Minor: &d.Minor,
  16. Access: permissions,
  17. }
  18. }
  19. // DevicesFromPath computes a list of devices and device permissions from paths (pathOnHost and pathInContainer) and cgroup permissions.
  20. func DevicesFromPath(pathOnHost, pathInContainer, cgroupPermissions string) (devs []specs.LinuxDevice, devPermissions []specs.LinuxDeviceCgroup, err error) {
  21. resolvedPathOnHost := pathOnHost
  22. // check if it is a symbolic link
  23. if src, e := os.Lstat(pathOnHost); e == nil && src.Mode()&os.ModeSymlink == os.ModeSymlink {
  24. if linkedPathOnHost, e := filepath.EvalSymlinks(pathOnHost); e == nil {
  25. resolvedPathOnHost = linkedPathOnHost
  26. }
  27. }
  28. device, err := coci.DeviceFromPath(resolvedPathOnHost)
  29. // if there was no error, return the device
  30. if err == nil {
  31. device.Path = pathInContainer
  32. return append(devs, *device), append(devPermissions, deviceCgroup(device, cgroupPermissions)), nil
  33. }
  34. // if the device is not a device node
  35. // try to see if it's a directory holding many devices
  36. if err == coci.ErrNotADevice {
  37. // check if it is a directory
  38. if src, e := os.Stat(resolvedPathOnHost); e == nil && src.IsDir() {
  39. // mount the internal devices recursively
  40. // TODO check if additional errors should be handled or logged
  41. _ = filepath.Walk(resolvedPathOnHost, func(dpath string, f os.FileInfo, _ error) error {
  42. childDevice, e := coci.DeviceFromPath(dpath)
  43. if e != nil {
  44. // ignore the device
  45. return nil
  46. }
  47. // add the device to userSpecified devices
  48. childDevice.Path = strings.Replace(dpath, resolvedPathOnHost, pathInContainer, 1)
  49. devs = append(devs, *childDevice)
  50. devPermissions = append(devPermissions, deviceCgroup(childDevice, cgroupPermissions))
  51. return nil
  52. })
  53. }
  54. }
  55. if len(devs) > 0 {
  56. return devs, devPermissions, nil
  57. }
  58. return devs, devPermissions, fmt.Errorf("error gathering device information while adding custom device %q: %s", pathOnHost, err)
  59. }