github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/runc/libcontainer/devices/devices_unix.go (about) 1 // +build linux freebsd 2 3 package devices 4 5 import ( 6 "errors" 7 "fmt" 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 "syscall" 12 13 "github.com/opencontainers/runc/libcontainer/configs" 14 ) 15 16 var ( 17 ErrNotADevice = errors.New("not a device node") 18 ) 19 20 // Testing dependencies 21 var ( 22 osLstat = os.Lstat 23 ioutilReadDir = ioutil.ReadDir 24 ) 25 26 // Given the path to a device and it's cgroup_permissions(which cannot be easily queried) look up the information about a linux device and return that information as a Device struct. 27 func DeviceFromPath(path, permissions string) (*configs.Device, error) { 28 fileInfo, err := osLstat(path) 29 if err != nil { 30 return nil, err 31 } 32 var ( 33 devType rune 34 mode = fileInfo.Mode() 35 fileModePermissionBits = os.FileMode.Perm(mode) 36 ) 37 switch { 38 case mode&os.ModeDevice == 0: 39 return nil, ErrNotADevice 40 case mode&os.ModeCharDevice != 0: 41 fileModePermissionBits |= syscall.S_IFCHR 42 devType = 'c' 43 default: 44 fileModePermissionBits |= syscall.S_IFBLK 45 devType = 'b' 46 } 47 stat_t, ok := fileInfo.Sys().(*syscall.Stat_t) 48 if !ok { 49 return nil, fmt.Errorf("cannot determine the device number for device %s", path) 50 } 51 devNumber := int(stat_t.Rdev) 52 return &configs.Device{ 53 Type: devType, 54 Path: path, 55 Major: Major(devNumber), 56 Minor: Minor(devNumber), 57 Permissions: permissions, 58 FileMode: fileModePermissionBits, 59 Uid: stat_t.Uid, 60 Gid: stat_t.Gid, 61 }, nil 62 } 63 64 func HostDevices() ([]*configs.Device, error) { 65 return getDevices("/dev") 66 } 67 68 func getDevices(path string) ([]*configs.Device, error) { 69 files, err := ioutilReadDir(path) 70 if err != nil { 71 return nil, err 72 } 73 out := []*configs.Device{} 74 for _, f := range files { 75 switch { 76 case f.IsDir(): 77 switch f.Name() { 78 case "pts", "shm", "fd", "mqueue": 79 continue 80 default: 81 sub, err := getDevices(filepath.Join(path, f.Name())) 82 if err != nil { 83 return nil, err 84 } 85 86 out = append(out, sub...) 87 continue 88 } 89 case f.Name() == "console": 90 continue 91 } 92 device, err := DeviceFromPath(filepath.Join(path, f.Name()), "rwm") 93 if err != nil { 94 if err == ErrNotADevice { 95 continue 96 } 97 return nil, err 98 } 99 out = append(out, device) 100 } 101 return out, nil 102 }