vendor/github.com/opencontainers/runc/libcontainer/devices/devices_linux.go
608702b9
 package devices
 
 import (
69989b7c
 	"errors"
 	"io/ioutil"
608702b9
 	"os"
69989b7c
 	"path/filepath"
608702b9
 
c86189d5
 	"github.com/opencontainers/runc/libcontainer/configs"
45d85c99
 
 	"golang.org/x/sys/unix"
608702b9
 )
 
69989b7c
 var (
7910cb52
 	ErrNotADevice = errors.New("not a device node")
69989b7c
 )
 
2531fba3
 // Testing dependencies
 var (
45d85c99
 	unixLstat     = unix.Lstat
2531fba3
 	ioutilReadDir = ioutil.ReadDir
 )
 
005506d3
 // Given the path to a device and its cgroup_permissions(which cannot be easily queried) look up the information about a linux device and return that information as a Device struct.
7910cb52
 func DeviceFromPath(path, permissions string) (*configs.Device, error) {
45d85c99
 	var stat unix.Stat_t
 	err := unixLstat(path, &stat)
69989b7c
 	if err != nil {
 		return nil, err
 	}
45d85c99
 
608702b9
 	var (
af248a3f
 		devNumber = stat.Rdev
 		major     = unix.Major(devNumber)
608702b9
 	)
45d85c99
 	if major == 0 {
7910cb52
 		return nil, ErrNotADevice
608702b9
 	}
45d85c99
 
 	var (
 		devType rune
 		mode    = stat.Mode
 	)
 	switch {
 	case mode&unix.S_IFBLK == unix.S_IFBLK:
 		devType = 'b'
 	case mode&unix.S_IFCHR == unix.S_IFCHR:
 		devType = 'c'
608702b9
 	}
7910cb52
 	return &configs.Device{
 		Type:        devType,
 		Path:        path,
af248a3f
 		Major:       int64(major),
 		Minor:       int64(unix.Minor(devNumber)),
7910cb52
 		Permissions: permissions,
45d85c99
 		FileMode:    os.FileMode(mode),
 		Uid:         stat.Uid,
 		Gid:         stat.Gid,
69989b7c
 	}, nil
608702b9
 }
 
7910cb52
 func HostDevices() ([]*configs.Device, error) {
 	return getDevices("/dev")
69989b7c
 }
 
7910cb52
 func getDevices(path string) ([]*configs.Device, error) {
2531fba3
 	files, err := ioutilReadDir(path)
69989b7c
 	if err != nil {
 		return nil, err
608702b9
 	}
7910cb52
 	out := []*configs.Device{}
69989b7c
 	for _, f := range files {
622e1005
 		switch {
 		case f.IsDir():
69989b7c
 			switch f.Name() {
005506d3
 			// ".lxc" & ".lxd-mounts" added to address https://github.com/lxc/lxd/issues/2825
 			case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts":
69989b7c
 				continue
 			default:
7910cb52
 				sub, err := getDevices(filepath.Join(path, f.Name()))
69989b7c
 				if err != nil {
 					return nil, err
 				}
 
 				out = append(out, sub...)
 				continue
 			}
622e1005
 		case f.Name() == "console":
 			continue
69989b7c
 		}
7910cb52
 		device, err := DeviceFromPath(filepath.Join(path, f.Name()), "rwm")
69989b7c
 		if err != nil {
7910cb52
 			if err == ErrNotADevice {
69989b7c
 				continue
 			}
005506d3
 			if os.IsNotExist(err) {
 				continue
 			}
69989b7c
 			return nil, err
 		}
 		out = append(out, device)
 	}
 	return out, nil
 }