mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
200f56315e
Currently, libcontainer/devices contains two things: 1. Device-related configuration data structures and accompanying methods. Those are used by runc itself, mostly by libct/cgroups. 2. A few functions (HostDevices, DeviceFromPath, GetDevices). Those are not used by runc directly, but have some external users (cri-o, microsoft/hcsshim), and they also have a few forks (containerd/pkg/oci, podman/pkg/util). This commit moves (1) to a new separate package, config (under libcontainer/cgroups/devices), adding a backward-compatible aliases (marked as deprecated so we will be able to remove those later). Alas it's not possible to move this to libcontainer/cgroups directly because some IDs (Type, Rule, Permissions) are too generic, and renaming them (to DeviceType, DeviceRule, DevicePermissions) will break backward compatibility (mostly due to Rule being embedded into Device). Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
113 lines
2.5 KiB
Go
113 lines
2.5 KiB
Go
//go:build !windows
|
|
|
|
package devices
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
// ErrNotADevice denotes that a file is not a valid linux device.
|
|
var ErrNotADevice = errors.New("not a device node")
|
|
|
|
// Testing dependencies
|
|
var (
|
|
unixLstat = unix.Lstat
|
|
osReadDir = os.ReadDir
|
|
)
|
|
|
|
// DeviceFromPath takes the path to a device and its cgroup_permissions (which
|
|
// cannot be easily queried) to look up the information about a linux device
|
|
// and returns that information as a Device struct.
|
|
func DeviceFromPath(path, permissions string) (*Device, error) {
|
|
var stat unix.Stat_t
|
|
err := unixLstat(path, &stat)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var (
|
|
devType Type
|
|
mode = stat.Mode
|
|
devNumber = uint64(stat.Rdev) //nolint:unconvert // Rdev is uint32 on e.g. MIPS.
|
|
major = unix.Major(devNumber)
|
|
minor = unix.Minor(devNumber)
|
|
)
|
|
switch mode & unix.S_IFMT {
|
|
case unix.S_IFBLK:
|
|
devType = BlockDevice
|
|
case unix.S_IFCHR:
|
|
devType = CharDevice
|
|
case unix.S_IFIFO:
|
|
devType = FifoDevice
|
|
default:
|
|
return nil, ErrNotADevice
|
|
}
|
|
return &Device{
|
|
Rule: Rule{
|
|
Type: devType,
|
|
Major: int64(major),
|
|
Minor: int64(minor),
|
|
Permissions: Permissions(permissions),
|
|
},
|
|
Path: path,
|
|
FileMode: os.FileMode(mode &^ unix.S_IFMT),
|
|
Uid: stat.Uid,
|
|
Gid: stat.Gid,
|
|
}, nil
|
|
}
|
|
|
|
// HostDevices returns all devices that can be found under /dev directory.
|
|
func HostDevices() ([]*Device, error) {
|
|
return GetDevices("/dev")
|
|
}
|
|
|
|
// GetDevices recursively traverses a directory specified by path
|
|
// and returns all devices found there.
|
|
func GetDevices(path string) ([]*Device, error) {
|
|
files, err := osReadDir(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var out []*Device
|
|
for _, f := range files {
|
|
switch {
|
|
case f.IsDir():
|
|
switch f.Name() {
|
|
// ".lxc" & ".lxd-mounts" added to address https://github.com/lxc/lxd/issues/2825
|
|
// ".udev" added to address https://github.com/opencontainers/runc/issues/2093
|
|
case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts", ".udev":
|
|
continue
|
|
default:
|
|
sub, err := GetDevices(filepath.Join(path, f.Name()))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
out = append(out, sub...)
|
|
continue
|
|
}
|
|
case f.Name() == "console":
|
|
continue
|
|
}
|
|
device, err := DeviceFromPath(filepath.Join(path, f.Name()), "rwm")
|
|
if err != nil {
|
|
if errors.Is(err, ErrNotADevice) {
|
|
continue
|
|
}
|
|
if os.IsNotExist(err) {
|
|
continue
|
|
}
|
|
return nil, err
|
|
}
|
|
if device.Type == FifoDevice {
|
|
continue
|
|
}
|
|
out = append(out, device)
|
|
}
|
|
return out, nil
|
|
}
|