MCPcopy
hub / github.com/lxc/incus / UnixDeviceCreate

Function UnixDeviceCreate

internal/server/device/device_utils_unix.go:108–254  ·  view source on GitHub ↗

UnixDeviceCreate creates a UNIX device (either block or char). If the supplied device config map contains a major and minor number for the device, then a stat is avoided, otherwise this info retrieved from the origin device. Similarly, if a mode is supplied in the device config map or defaultMode is

(s *state.State, idmapSet *idmap.Set, devicesPath string, prefix string, m deviceConfig.Device, defaultMode bool)

Source from the content-addressed store, hash-verified

106// defaults to root (0) but can be specified with the uid and gid fields in the device config map.
107// It returns a UnixDevice containing information about the device created.
108func UnixDeviceCreate(s *state.State, idmapSet *idmap.Set, devicesPath string, prefix string, m deviceConfig.Device, defaultMode bool) (*UnixDevice, error) {
109 var err error
110 d := UnixDevice{}
111
112 // Extra checks for nesting.
113 if s.OS.RunningInUserNS {
114 for key, value := range m {
115 if slices.Contains([]string{"major", "minor", "mode", "uid", "gid"}, key) && value != "" {
116 return nil, fmt.Errorf("The \"%s\" property may not be set when adding a device to a nested container", key)
117 }
118 }
119 }
120
121 srcPath := unixDeviceSourcePath(m)
122
123 // Get the major/minor of the device we want to create.
124 if m["major"] == "" && m["minor"] == "" {
125 // If no major and minor are set, use those from the device on the host.
126 _, d.Major, d.Minor, err = unixDeviceAttributes(srcPath)
127 if err != nil {
128 return nil, fmt.Errorf("Failed to get device attributes for %s: %w", srcPath, err)
129 }
130 } else if m["major"] == "" || m["minor"] == "" {
131 return nil, fmt.Errorf("Both major and minor must be supplied for device: %s", srcPath)
132 } else {
133 tmp, err := strconv.ParseUint(m["major"], 10, 32)
134 if err != nil {
135 return nil, fmt.Errorf("Bad major %s in device %s", m["major"], srcPath)
136 }
137
138 d.Major = uint32(tmp)
139
140 tmp, err = strconv.ParseUint(m["minor"], 10, 32)
141 if err != nil {
142 return nil, fmt.Errorf("Bad minor %s in device %s", m["minor"], srcPath)
143 }
144
145 d.Minor = uint32(tmp)
146 }
147
148 // Get the device mode (defaults to unixDefaultMode if not supplied).
149 d.Mode = os.FileMode(unixDefaultMode)
150 if m["mode"] != "" {
151 tmp, err := unixDeviceModeOct(m["mode"])
152 if err != nil {
153 return nil, fmt.Errorf("Bad mode %s in device %s", m["mode"], srcPath)
154 }
155
156 d.Mode = os.FileMode(tmp)
157 } else if !defaultMode {
158 // If not specified mode in device config, and default mode is false, then try and
159 // read the source device's mode and use that inside the instance.
160 d.Mode, err = internalIO.GetPathMode(srcPath)
161 if err != nil {
162 isErrno, errno := linux.GetErrno(err)
163 if !isErrno || !errors.Is(errno, unix.ENOENT) {
164 return nil, fmt.Errorf("Failed to retrieve mode of device %s: %w", srcPath, err)
165 }

Callers 2

unixDeviceSetupFunction · 0.85

Calls 15

GetErrnoFunction · 0.92
PathExistsFunction · 0.92
PathNameEncodeFunction · 0.92
DebugfFunction · 0.92
unixDeviceSourcePathFunction · 0.85
unixDeviceAttributesFunction · 0.85
unixDeviceModeOctFunction · 0.85
unixDeviceDestPathFunction · 0.85
deviceJoinPathFunction · 0.85
DiskMountFunction · 0.85
ErrorfMethod · 0.80
ShiftPathMethod · 0.80

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…