mirror of
https://github.com/containers/podman.git
synced 2025-07-03 17:27:18 +08:00
Add support for adding devices to container
Also add --quiet option to kpod create/run since this will help with writing tests. Signed-off-by: Daniel J Walsh <dwalsh@redhat.com> Closes: #140 Approved by: TomSweeneyRedHat
This commit is contained in:

committed by
Atomic Bot

parent
c0432eb0e8
commit
94a8107515
@ -362,6 +362,10 @@ var createFlags = []cli.Flag{
|
|||||||
Name: "publish-all, P",
|
Name: "publish-all, P",
|
||||||
Usage: "Publish all exposed ports to random ports on the host interface",
|
Usage: "Publish all exposed ports to random ports on the host interface",
|
||||||
},
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "quiet, q",
|
||||||
|
Usage: "Suppress output information when pulling images",
|
||||||
|
},
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "read-only",
|
Name: "read-only",
|
||||||
Usage: "Make containers root filesystem read-only",
|
Usage: "Make containers root filesystem read-only",
|
||||||
|
@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -14,7 +15,6 @@ import (
|
|||||||
"github.com/projectatomic/libpod/libpod"
|
"github.com/projectatomic/libpod/libpod"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type mountType string
|
type mountType string
|
||||||
@ -72,7 +72,7 @@ type createConfig struct {
|
|||||||
CgroupParent string // cgroup-parent
|
CgroupParent string // cgroup-parent
|
||||||
Command []string
|
Command []string
|
||||||
Detach bool // detach
|
Detach bool // detach
|
||||||
Devices []*pb.Device // device
|
Devices []string // device
|
||||||
DNSOpt []string //dns-opt
|
DNSOpt []string //dns-opt
|
||||||
DNSSearch []string //dns-search
|
DNSSearch []string //dns-search
|
||||||
DNSServers []string //dns
|
DNSServers []string //dns
|
||||||
@ -101,6 +101,7 @@ type createConfig struct {
|
|||||||
Privileged bool //privileged
|
Privileged bool //privileged
|
||||||
Publish []string //publish
|
Publish []string //publish
|
||||||
PublishAll bool //publish-all
|
PublishAll bool //publish-all
|
||||||
|
Quiet bool //quiet
|
||||||
ReadOnlyRootfs bool //read-only
|
ReadOnlyRootfs bool //read-only
|
||||||
Resources createResourceConfig
|
Resources createResourceConfig
|
||||||
Rm bool //rm
|
Rm bool //rm
|
||||||
@ -167,8 +168,11 @@ func createCmd(c *cli.Context) error {
|
|||||||
if createImage.LocalName == "" {
|
if createImage.LocalName == "" {
|
||||||
// The image wasnt found by the user input'd name or its fqname
|
// The image wasnt found by the user input'd name or its fqname
|
||||||
// Pull the image
|
// Pull the image
|
||||||
fmt.Printf("Trying to pull %s...", createImage.PullName)
|
var writer io.Writer
|
||||||
createImage.Pull()
|
if !createConfig.Quiet {
|
||||||
|
writer = os.Stdout
|
||||||
|
}
|
||||||
|
createImage.Pull(writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
runtimeSpec, err := createConfigToOCISpec(createConfig)
|
runtimeSpec, err := createConfigToOCISpec(createConfig)
|
||||||
@ -419,6 +423,7 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime) (*createConfig, er
|
|||||||
CgroupParent: c.String("cgroup-parent"),
|
CgroupParent: c.String("cgroup-parent"),
|
||||||
Command: command,
|
Command: command,
|
||||||
Detach: c.Bool("detach"),
|
Detach: c.Bool("detach"),
|
||||||
|
Devices: c.StringSlice("device"),
|
||||||
DNSOpt: c.StringSlice("dns-opt"),
|
DNSOpt: c.StringSlice("dns-opt"),
|
||||||
DNSSearch: c.StringSlice("dns-search"),
|
DNSSearch: c.StringSlice("dns-search"),
|
||||||
DNSServers: c.StringSlice("dns"),
|
DNSServers: c.StringSlice("dns"),
|
||||||
@ -447,6 +452,7 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime) (*createConfig, er
|
|||||||
Privileged: c.Bool("privileged"),
|
Privileged: c.Bool("privileged"),
|
||||||
Publish: c.StringSlice("publish"),
|
Publish: c.StringSlice("publish"),
|
||||||
PublishAll: c.Bool("publish-all"),
|
PublishAll: c.Bool("publish-all"),
|
||||||
|
Quiet: c.Bool("quiet"),
|
||||||
ReadOnlyRootfs: c.Bool("read-only"),
|
ReadOnlyRootfs: c.Bool("read-only"),
|
||||||
Resources: createResourceConfig{
|
Resources: createResourceConfig{
|
||||||
BlkioWeight: blkioWeight,
|
BlkioWeight: blkioWeight,
|
||||||
|
@ -2,6 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -44,7 +46,11 @@ func runCmd(c *cli.Context) error {
|
|||||||
if createImage.LocalName == "" {
|
if createImage.LocalName == "" {
|
||||||
// The image wasnt found by the user input'd name or its fqname
|
// The image wasnt found by the user input'd name or its fqname
|
||||||
// Pull the image
|
// Pull the image
|
||||||
createImage.Pull()
|
var writer io.Writer
|
||||||
|
if !createConfig.Quiet {
|
||||||
|
writer = os.Stdout
|
||||||
|
}
|
||||||
|
createImage.Pull(writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
runtimeSpec, err := createConfigToOCISpec(createConfig)
|
runtimeSpec, err := createConfigToOCISpec(createConfig)
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/docker/docker/daemon/caps"
|
"github.com/docker/docker/daemon/caps"
|
||||||
"github.com/docker/docker/pkg/mount"
|
"github.com/docker/docker/pkg/mount"
|
||||||
"github.com/docker/go-units"
|
"github.com/docker/go-units"
|
||||||
|
"github.com/opencontainers/runc/libcontainer/devices"
|
||||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/opencontainers/runtime-tools/generate"
|
"github.com/opencontainers/runtime-tools/generate"
|
||||||
"github.com/opencontainers/selinux/go-selinux/label"
|
"github.com/opencontainers/selinux/go-selinux/label"
|
||||||
@ -163,6 +164,25 @@ func setupCapabilities(config *createConfig, configSpec *spec.Spec) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addDevice(g *generate.Generator, device string) error {
|
||||||
|
dev, err := devices.DeviceFromPath(device, "rwm")
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "%s is not a valid device", device)
|
||||||
|
}
|
||||||
|
linuxdev := spec.LinuxDevice{
|
||||||
|
Path: dev.Path,
|
||||||
|
Type: string(dev.Type),
|
||||||
|
Major: dev.Major,
|
||||||
|
Minor: dev.Minor,
|
||||||
|
FileMode: &dev.FileMode,
|
||||||
|
UID: &dev.Uid,
|
||||||
|
GID: &dev.Gid,
|
||||||
|
}
|
||||||
|
g.AddDevice(linuxdev)
|
||||||
|
g.AddLinuxResourcesDevice(true, string(dev.Type), &dev.Major, &dev.Minor, dev.Permissions)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Parses information needed to create a container into an OCI runtime spec
|
// Parses information needed to create a container into an OCI runtime spec
|
||||||
func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
|
func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
|
||||||
g := generate.New()
|
g := generate.New()
|
||||||
@ -233,6 +253,13 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
|
|||||||
g.SetLinuxResourcesCPUMems(config.Resources.CPUsetMems)
|
g.SetLinuxResourcesCPUMems(config.Resources.CPUsetMems)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Devices
|
||||||
|
for _, device := range config.Devices {
|
||||||
|
if err := addDevice(&g, device); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SECURITY OPTS
|
// SECURITY OPTS
|
||||||
g.SetProcessNoNewPrivileges(config.NoNewPrivileges)
|
g.SetProcessNoNewPrivileges(config.NoNewPrivileges)
|
||||||
g.SetProcessApparmorProfile(config.ApparmorProfile)
|
g.SetProcessApparmorProfile(config.ApparmorProfile)
|
||||||
@ -321,7 +348,6 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
|
|||||||
Hooks: &configSpec.Hooks{},
|
Hooks: &configSpec.Hooks{},
|
||||||
//Annotations
|
//Annotations
|
||||||
Resources: &configSpec.LinuxResources{
|
Resources: &configSpec.LinuxResources{
|
||||||
Devices: config.GetDefaultDevices(),
|
|
||||||
BlockIO: &blkio,
|
BlockIO: &blkio,
|
||||||
//HugepageLimits:
|
//HugepageLimits:
|
||||||
Network: &configSpec.LinuxNetwork{
|
Network: &configSpec.LinuxNetwork{
|
||||||
@ -331,7 +357,6 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
|
|||||||
},
|
},
|
||||||
//CgroupsPath:
|
//CgroupsPath:
|
||||||
//Namespaces: []LinuxNamespace
|
//Namespaces: []LinuxNamespace
|
||||||
//Devices
|
|
||||||
// DefaultAction:
|
// DefaultAction:
|
||||||
// Architectures
|
// Architectures
|
||||||
// Syscalls:
|
// Syscalls:
|
||||||
|
@ -1018,6 +1018,7 @@ _podman_container_run() {
|
|||||||
--oom-kill-disable
|
--oom-kill-disable
|
||||||
--privileged
|
--privileged
|
||||||
--publish-all -P
|
--publish-all -P
|
||||||
|
--quiet
|
||||||
--read-only
|
--read-only
|
||||||
--tty -t
|
--tty -t
|
||||||
"
|
"
|
||||||
|
@ -373,6 +373,10 @@ port to a random port on the host within an *ephemeral port range* defined by
|
|||||||
`/proc/sys/net/ipv4/ip_local_port_range`. To find the mapping between the host
|
`/proc/sys/net/ipv4/ip_local_port_range`. To find the mapping between the host
|
||||||
ports and the exposed ports, use `podman port`.
|
ports and the exposed ports, use `podman port`.
|
||||||
|
|
||||||
|
**--quiet, -q**
|
||||||
|
|
||||||
|
Suppress output information when pulling images
|
||||||
|
|
||||||
**--read-only**=*true*|*false*
|
**--read-only**=*true*|*false*
|
||||||
Mount the container's root filesystem as read only.
|
Mount the container's root filesystem as read only.
|
||||||
|
|
||||||
|
@ -379,6 +379,10 @@ port to a random port on the host within an *ephemeral port range* defined by
|
|||||||
`/proc/sys/net/ipv4/ip_local_port_range`. To find the mapping between the host
|
`/proc/sys/net/ipv4/ip_local_port_range`. To find the mapping between the host
|
||||||
ports and the exposed ports, use `podman port`.
|
ports and the exposed ports, use `podman port`.
|
||||||
|
|
||||||
|
**--quiet, -q**
|
||||||
|
|
||||||
|
Suppress output information when pulling images
|
||||||
|
|
||||||
**--read-only**=*true*|*false*
|
**--read-only**=*true*|*false*
|
||||||
Mount the container's root filesystem as read only.
|
Mount the container's root filesystem as read only.
|
||||||
|
|
||||||
|
@ -397,7 +397,7 @@ func (k *Image) HasLatest() (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pull is a wrapper function to pull and image
|
// Pull is a wrapper function to pull and image
|
||||||
func (k *Image) Pull() error {
|
func (k *Image) Pull(writer io.Writer) error {
|
||||||
// If the image hasn't been decomposed yet
|
// If the image hasn't been decomposed yet
|
||||||
if !k.beenDecomposed {
|
if !k.beenDecomposed {
|
||||||
err := k.Decompose()
|
err := k.Decompose()
|
||||||
@ -405,7 +405,7 @@ func (k *Image) Pull() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
k.runtime.PullImage(k.PullName, CopyOptions{Writer: os.Stdout, SignaturePolicyPath: k.runtime.config.SignaturePolicyPath})
|
k.runtime.PullImage(k.PullName, CopyOptions{Writer: writer, SignaturePolicyPath: k.runtime.config.SignaturePolicyPath})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
27
test/podman_run_device.bats
Normal file
27
test/podman_run_device.bats
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/env bats
|
||||||
|
|
||||||
|
load helpers
|
||||||
|
|
||||||
|
function teardown() {
|
||||||
|
cleanup_test
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup() {
|
||||||
|
prepare_network_conf
|
||||||
|
copy_images
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "run baddevice test" {
|
||||||
|
run ${PODMAN_BINARY} ${PODMAN_OPTIONS} run -q --device /dev/baddevice ${ALPINE} ls /dev/kmsg
|
||||||
|
echo $output
|
||||||
|
[ "$status" -ne 0 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "run device test" {
|
||||||
|
run ${PODMAN_BINARY} ${PODMAN_OPTIONS} run -q --device /dev/kmsg ${ALPINE} ls --color=never /dev/kmsg
|
||||||
|
echo "$output"
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
device=$(echo $output | tr -d '\r')
|
||||||
|
echo "<$device>"
|
||||||
|
[ "$device" = "/dev/kmsg" ]
|
||||||
|
}
|
@ -1,14 +1,14 @@
|
|||||||
#
|
#
|
||||||
github.com/sirupsen/logrus v1.0.0
|
github.com/sirupsen/logrus v1.0.0
|
||||||
github.com/containers/image c8bcd6aa11c62637c5a7da1420f43dd6a15f0e8d
|
github.com/containers/image 9b4510f6d1627c8e53c3303a8fe48ca7842c2ace
|
||||||
github.com/docker/docker-credential-helpers d68f9aeca33f5fd3f08eeae5e9d175edf4e731d1
|
github.com/docker/docker-credential-helpers d68f9aeca33f5fd3f08eeae5e9d175edf4e731d1
|
||||||
github.com/ostreedev/ostree-go master
|
github.com/ostreedev/ostree-go master
|
||||||
github.com/containers/storage 9e0c323a4b425557f8310ee8d125634acd39d8f5
|
github.com/containers/storage 1824cf917a6b42d8c41179e807bb20a5fd6c0f0a
|
||||||
github.com/containernetworking/cni v0.4.0
|
github.com/containernetworking/cni v0.4.0
|
||||||
google.golang.org/grpc v1.0.4 https://github.com/grpc/grpc-go
|
google.golang.org/grpc v1.0.4 https://github.com/grpc/grpc-go
|
||||||
github.com/opencontainers/selinux b29023b86e4a69d1b46b7e7b4e2b6fda03f0b9cd
|
github.com/opencontainers/selinux b29023b86e4a69d1b46b7e7b4e2b6fda03f0b9cd
|
||||||
github.com/opencontainers/go-digest v1.0.0-rc0
|
github.com/opencontainers/go-digest v1.0.0-rc0
|
||||||
github.com/opencontainers/runtime-tools d3f7e9e9e631c7e87552d67dc7c86de33c3fb68a
|
github.com/opencontainers/runtime-tools v0.3.0
|
||||||
github.com/opencontainers/runc 45bde006ca8c90e089894508708bcf0e2cdf9e13
|
github.com/opencontainers/runc 45bde006ca8c90e089894508708bcf0e2cdf9e13
|
||||||
github.com/mrunalp/fileutils master
|
github.com/mrunalp/fileutils master
|
||||||
github.com/vishvananda/netlink master
|
github.com/vishvananda/netlink master
|
||||||
@ -97,3 +97,6 @@ github.com/pquerna/ffjson d49c2bc1aa135aad0c6f4fc2056623ec78f5d5ac
|
|||||||
github.com/stretchr/testify 4d4bfba8f1d1027c4fdbe371823030df51419987
|
github.com/stretchr/testify 4d4bfba8f1d1027c4fdbe371823030df51419987
|
||||||
github.com/pmezard/go-difflib 792786c7400a136282c1664665ae0a8db921c6c2
|
github.com/pmezard/go-difflib 792786c7400a136282c1664665ae0a8db921c6c2
|
||||||
github.com/containerd/continuity master
|
github.com/containerd/continuity master
|
||||||
|
github.com/xeipuuv/gojsonschema master
|
||||||
|
github.com/xeipuuv/gojsonreference master
|
||||||
|
github.com/xeipuuv/gojsonpointer master
|
||||||
|
100
vendor/github.com/opencontainers/runc/libcontainer/devices/devices_linux.go
generated
vendored
Normal file
100
vendor/github.com/opencontainers/runc/libcontainer/devices/devices_linux.go
generated
vendored
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
package devices
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/opencontainers/runc/libcontainer/configs"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrNotADevice = errors.New("not a device node")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Testing dependencies
|
||||||
|
var (
|
||||||
|
unixLstat = unix.Lstat
|
||||||
|
ioutilReadDir = ioutil.ReadDir
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
func DeviceFromPath(path, permissions string) (*configs.Device, error) {
|
||||||
|
var stat unix.Stat_t
|
||||||
|
err := unixLstat(path, &stat)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
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'
|
||||||
|
default:
|
||||||
|
return nil, ErrNotADevice
|
||||||
|
}
|
||||||
|
devNumber := int(stat.Rdev)
|
||||||
|
uid := stat.Uid
|
||||||
|
gid := stat.Gid
|
||||||
|
return &configs.Device{
|
||||||
|
Type: devType,
|
||||||
|
Path: path,
|
||||||
|
Major: Major(devNumber),
|
||||||
|
Minor: Minor(devNumber),
|
||||||
|
Permissions: permissions,
|
||||||
|
FileMode: os.FileMode(mode),
|
||||||
|
Uid: uid,
|
||||||
|
Gid: gid,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func HostDevices() ([]*configs.Device, error) {
|
||||||
|
return getDevices("/dev")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDevices(path string) ([]*configs.Device, error) {
|
||||||
|
files, err := ioutilReadDir(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out := []*configs.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
|
||||||
|
case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts":
|
||||||
|
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 err == ErrNotADevice {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out = append(out, device)
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
3
vendor/github.com/opencontainers/runc/libcontainer/devices/devices_unsupported.go
generated
vendored
Normal file
3
vendor/github.com/opencontainers/runc/libcontainer/devices/devices_unsupported.go
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package devices
|
24
vendor/github.com/opencontainers/runc/libcontainer/devices/number.go
generated
vendored
Normal file
24
vendor/github.com/opencontainers/runc/libcontainer/devices/number.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// +build linux freebsd
|
||||||
|
|
||||||
|
package devices
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This code provides support for manipulating linux device numbers. It should be replaced by normal syscall functions once http://code.google.com/p/go/issues/detail?id=8106 is solved.
|
||||||
|
|
||||||
|
You can read what they are here:
|
||||||
|
|
||||||
|
- http://www.makelinux.net/ldd3/chp-3-sect-2
|
||||||
|
- http://www.linux-tutorial.info/modules.php?name=MContent&pageid=94
|
||||||
|
|
||||||
|
Note! These are NOT the same as the MAJOR(dev_t device);, MINOR(dev_t device); and MKDEV(int major, int minor); functions as defined in <linux/kdev_t.h> as the representation of device numbers used by go is different than the one used internally to the kernel! - https://github.com/torvalds/linux/blob/master/include/linux/kdev_t.h#L9
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
func Major(devNumber int) int64 {
|
||||||
|
return int64((devNumber >> 8) & 0xfff)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Minor(devNumber int) int64 {
|
||||||
|
return int64((devNumber & 0xff) | ((devNumber >> 12) & 0xfff00))
|
||||||
|
}
|
Reference in New Issue
Block a user