]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libudev/libudev-device.c
tree-wide: make sure net/if.h is included before any linux/ header
[thirdparty/systemd.git] / src / libudev / libudev-device.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
eb1f0e66 2
edda10f2
FS
3/* Make sure the net/if.h header is included before any linux/ one */
4#include <net/if.h>
07630cea 5#include <ctype.h>
eb1f0e66 6#include <dirent.h>
07630cea 7#include <errno.h>
93b0f384 8#include <fcntl.h>
07630cea 9#include <linux/sockios.h>
07630cea
LP
10#include <stdbool.h>
11#include <stddef.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
3e0a2c9a
KS
15#include <sys/ioctl.h>
16#include <sys/socket.h>
07630cea
LP
17#include <sys/stat.h>
18#include <unistd.h>
eb1f0e66 19
b4bbcaa9 20#include "libudev.h"
f4ac4d1a 21#include "sd-device.h"
f4ac4d1a 22
b5efdb8a 23#include "alloc-util.h"
07630cea
LP
24#include "device-private.h"
25#include "device-util.h"
f4ac4d1a 26#include "libudev-device-internal.h"
538bdb48 27#include "libudev-list-internal.h"
6bedfcbb 28#include "parse-util.h"
5ea78a39 29#include "time-util.h"
b2661839 30
ce1d6d7f
KS
31/**
32 * SECTION:libudev-device
33 * @short_description: kernel sys devices
34 *
35 * Representation of kernel sys devices. Devices are uniquely identified
36 * by their syspath, every device has exactly one path in the kernel sys
5eec7de6 37 * filesystem. Devices usually belong to a kernel subsystem, and have
214a6c79 38 * a unique name inside that subsystem.
ce1d6d7f
KS
39 */
40
538bdb48
YW
41/**
42 * udev_device:
43 *
44 * Opaque object representing one kernel sys device.
45 */
46struct udev_device {
47 struct udev *udev;
48
49 /* real device object */
50 sd_device *device;
51
52 /* legacy */
53 unsigned n_ref;
54
55 struct udev_device *parent;
56 bool parent_set;
57
58 struct udev_list *properties;
59 uint64_t properties_generation;
3b684be0
LP
60 struct udev_list *all_tags, *current_tags;
61 uint64_t all_tags_generation, current_tags_generation;
538bdb48
YW
62 struct udev_list *devlinks;
63 uint64_t devlinks_generation;
64 bool properties_read:1;
3b684be0
LP
65 bool all_tags_read:1;
66 bool current_tags_read:1;
538bdb48
YW
67 bool devlinks_read:1;
68 struct udev_list *sysattrs;
69 bool sysattrs_read;
70};
71
905555dc 72/**
a3321f68 73 * udev_device_get_seqnum:
905555dc
KS
74 * @udev_device: udev device
75 *
76 * This is only valid if the device was received through a monitor. Devices read from
77 * sys do not have a sequence number.
78 *
79 * Returns: the kernel event sequence number, or 0 if there is no sequence number available.
80 **/
40769ccc
YW
81_public_ unsigned long long udev_device_get_seqnum(struct udev_device *udev_device) {
82 uint64_t seqnum;
905555dc 83
f4ac4d1a 84 assert_return_errno(udev_device, 0, EINVAL);
905555dc 85
a1130022 86 if (sd_device_get_seqnum(udev_device->device, &seqnum) < 0)
f4ac4d1a 87 return 0;
905555dc 88
40769ccc 89 return seqnum;
905555dc
KS
90}
91
92/**
93 * udev_device_get_devnum:
94 * @udev_device: udev device
95 *
21dbe43a
KS
96 * Get the device major/minor number.
97 *
98 * Returns: the dev_t number.
905555dc 99 **/
76387b9a 100_public_ dev_t udev_device_get_devnum(struct udev_device *udev_device) {
f4ac4d1a
TG
101 dev_t devnum;
102 int r;
905555dc 103
f4ac4d1a 104 assert_return_errno(udev_device, makedev(0, 0), EINVAL);
905555dc 105
f4ac4d1a 106 r = sd_device_get_devnum(udev_device->device, &devnum);
fd05c424 107 if (r == -ENOENT)
f4ac4d1a 108 return makedev(0, 0);
fd05c424
YW
109 if (r < 0)
110 return_with_errno(makedev(0, 0), r);
905555dc 111
f4ac4d1a 112 return devnum;
905555dc
KS
113}
114
115/**
116 * udev_device_get_driver:
117 * @udev_device: udev device
118 *
21dbe43a
KS
119 * Get the kernel driver name.
120 *
121 * Returns: the driver name string, or #NULL if there is no driver attached.
905555dc 122 **/
76387b9a 123_public_ const char *udev_device_get_driver(struct udev_device *udev_device) {
f4ac4d1a
TG
124 const char *driver;
125 int r;
126
127 assert_return_errno(udev_device, NULL, EINVAL);
905555dc 128
f4ac4d1a 129 r = sd_device_get_driver(udev_device->device, &driver);
fd05c424
YW
130 if (r < 0)
131 return_with_errno(NULL, r);
905555dc 132
f4ac4d1a 133 return driver;
905555dc
KS
134}
135
136/**
137 * udev_device_get_devtype:
138 * @udev_device: udev device
139 *
140 * Retrieve the devtype string of the udev device.
141 *
87ac8d99 142 * Returns: the devtype name of the udev device, or #NULL if it cannot be determined
905555dc 143 **/
76387b9a 144_public_ const char *udev_device_get_devtype(struct udev_device *udev_device) {
f4ac4d1a
TG
145 const char *devtype;
146 int r;
147
148 assert_return_errno(udev_device, NULL, EINVAL);
149
150 r = sd_device_get_devtype(udev_device->device, &devtype);
fd05c424 151 if (r == -ENOENT)
912541b0 152 return NULL;
fd05c424
YW
153 if (r < 0)
154 return_with_errno(NULL, r);
905555dc 155
f4ac4d1a 156 return devtype;
905555dc
KS
157}
158
159/**
160 * udev_device_get_subsystem:
161 * @udev_device: udev device
162 *
163 * Retrieve the subsystem string of the udev device. The string does not
164 * contain any "/".
165 *
87ac8d99 166 * Returns: the subsystem name of the udev device, or #NULL if it cannot be determined
905555dc 167 **/
76387b9a 168_public_ const char *udev_device_get_subsystem(struct udev_device *udev_device) {
f4ac4d1a
TG
169 const char *subsystem;
170 int r;
df546eb5 171
f4ac4d1a 172 assert_return_errno(udev_device, NULL, EINVAL);
fc8d61c5 173
f4ac4d1a 174 r = sd_device_get_subsystem(udev_device->device, &subsystem);
fd05c424
YW
175 if (r < 0)
176 return_with_errno(NULL, r);
fc8d61c5 177
f4ac4d1a 178 return subsystem;
fc8d61c5
KS
179}
180
181/**
182 * udev_device_get_property_value:
183 * @udev_device: udev device
184 * @key: property name
185 *
21dbe43a
KS
186 * Get the value of a given property.
187 *
188 * Returns: the property string, or #NULL if there is no such property.
fc8d61c5 189 **/
76387b9a 190_public_ const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key) {
fd05c424 191 const char *value;
f4ac4d1a 192 int r;
912541b0 193
f4ac4d1a 194 assert_return_errno(udev_device && key, NULL, EINVAL);
912541b0 195
f4ac4d1a 196 r = sd_device_get_property_value(udev_device->device, key, &value);
fd05c424
YW
197 if (r < 0)
198 return_with_errno(NULL, r);
912541b0 199
f4ac4d1a 200 return value;
99214844
KS
201}
202
02e7ae2f 203struct udev_device *udev_device_new(struct udev *udev, sd_device *device) {
3b684be0 204 _cleanup_(udev_list_freep) struct udev_list *properties = NULL, *all_tags = NULL, *current_tags = NULL, *sysattrs = NULL, *devlinks = NULL;
912541b0 205 struct udev_device *udev_device;
912541b0 206
02e7ae2f
YW
207 assert(device);
208
dcf557f7
YW
209 properties = udev_list_new(true);
210 if (!properties)
211 return_with_errno(NULL, ENOMEM);
3b684be0
LP
212 all_tags = udev_list_new(true);
213 if (!all_tags)
214 return_with_errno(NULL, ENOMEM);
215 current_tags = udev_list_new(true);
216 if (!current_tags)
dcf557f7
YW
217 return_with_errno(NULL, ENOMEM);
218 sysattrs = udev_list_new(true);
219 if (!sysattrs)
220 return_with_errno(NULL, ENOMEM);
221 devlinks = udev_list_new(true);
222 if (!devlinks)
223 return_with_errno(NULL, ENOMEM);
224
71074e3a 225 udev_device = new(struct udev_device, 1);
fd05c424
YW
226 if (!udev_device)
227 return_with_errno(NULL, ENOMEM);
71074e3a
YW
228
229 *udev_device = (struct udev_device) {
230 .n_ref = 1,
231 .udev = udev,
02e7ae2f 232 .device = sd_device_ref(device),
dcf557f7 233 .properties = TAKE_PTR(properties),
3b684be0
LP
234 .all_tags = TAKE_PTR(all_tags),
235 .current_tags = TAKE_PTR(current_tags),
dcf557f7
YW
236 .sysattrs = TAKE_PTR(sysattrs),
237 .devlinks = TAKE_PTR(devlinks),
71074e3a
YW
238 };
239
912541b0 240 return udev_device;
eb1f0e66
KS
241}
242
243/**
8753fadf 244 * udev_device_new_from_syspath:
eb1f0e66 245 * @udev: udev library context
8753fadf 246 * @syspath: sys device path including sys directory
eb1f0e66 247 *
8753fadf 248 * Create new udev device, and fill in information from the sys
214a6c79 249 * device and the udev database entry. The syspath is the absolute
8753fadf 250 * path to the device, including the sys mount point.
eb1f0e66
KS
251 *
252 * The initial refcount is 1, and needs to be decremented to
be7de409 253 * release the resources of the udev device.
eb1f0e66
KS
254 *
255 * Returns: a new udev device, or #NULL, if it does not exist
256 **/
f4ac4d1a 257_public_ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) {
02e7ae2f 258 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
f4ac4d1a 259 int r;
912541b0 260
02e7ae2f 261 r = sd_device_new_from_syspath(&device, syspath);
fd05c424
YW
262 if (r < 0)
263 return_with_errno(NULL, r);
912541b0 264
02e7ae2f 265 return udev_device_new(udev, device);
eb1f0e66
KS
266}
267
1e511322
KS
268/**
269 * udev_device_new_from_devnum:
270 * @udev: udev library context
271 * @type: char or block device
272 * @devnum: device major/minor number
273 *
274 * Create new udev device, and fill in information from the sys
dbba7e40
KS
275 * device and the udev database entry. The device is looked-up
276 * by its major/minor number and type. Character and block device
277 * numbers are not unique across the two types.
1e511322
KS
278 *
279 * The initial refcount is 1, and needs to be decremented to
280 * release the resources of the udev device.
281 *
282 * Returns: a new udev device, or #NULL, if it does not exist
283 **/
76387b9a 284_public_ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum) {
02e7ae2f 285 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
f4ac4d1a
TG
286 int r;
287
02e7ae2f 288 r = sd_device_new_from_devnum(&device, type, devnum);
fd05c424
YW
289 if (r < 0)
290 return_with_errno(NULL, r);
4c9dff47 291
02e7ae2f 292 return udev_device_new(udev, device);
4c9dff47
KS
293}
294
dbf61afb
KS
295/**
296 * udev_device_new_from_device_id:
297 * @udev: udev library context
298 * @id: text string identifying a kernel device
299 *
300 * Create new udev device, and fill in information from the sys
301 * device and the udev database entry. The device is looked-up
302 * by a special string:
303 * b8:2 - block device major:minor
304 * c128:1 - char device major:minor
305 * n3 - network device ifindex
306 * +sound:card29 - kernel driver core subsystem:device name
307 *
308 * The initial refcount is 1, and needs to be decremented to
309 * release the resources of the udev device.
310 *
311 * Returns: a new udev device, or #NULL, if it does not exist
312 **/
76387b9a 313_public_ struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id) {
02e7ae2f 314 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
f4ac4d1a
TG
315 int r;
316
02e7ae2f 317 r = sd_device_new_from_device_id(&device, id);
fd05c424
YW
318 if (r < 0)
319 return_with_errno(NULL, r);
f4ac4d1a 320
02e7ae2f 321 return udev_device_new(udev, device);
cad40a5f
KS
322}
323
1e511322
KS
324/**
325 * udev_device_new_from_subsystem_sysname:
326 * @udev: udev library context
214a6c79 327 * @subsystem: the subsystem of the device
1e511322
KS
328 * @sysname: the name of the device
329 *
dbba7e40
KS
330 * Create new udev device, and fill in information from the sys device
331 * and the udev database entry. The device is looked up by the subsystem
332 * and name string of the device, like "mem" / "zero", or "block" / "sda".
1e511322
KS
333 *
334 * The initial refcount is 1, and needs to be decremented to
335 * release the resources of the udev device.
336 *
337 * Returns: a new udev device, or #NULL, if it does not exist
338 **/
76387b9a 339_public_ struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname) {
02e7ae2f 340 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
f4ac4d1a 341 int r;
912541b0 342
02e7ae2f 343 r = sd_device_new_from_subsystem_sysname(&device, subsystem, sysname);
fd05c424
YW
344 if (r < 0)
345 return_with_errno(NULL, r);
912541b0 346
02e7ae2f 347 return udev_device_new(udev, device);
90d80c2e
KS
348}
349
fc8d61c5
KS
350/**
351 * udev_device_new_from_environment
352 * @udev: udev library context
353 *
354 * Create new udev device, and fill in information from the
0025868c 355 * current process environment. This only works reliably if
fc8d61c5
KS
356 * the process is called from a udev rule. It is usually used
357 * for tools executed from IMPORT= rules.
358 *
359 * The initial refcount is 1, and needs to be decremented to
360 * release the resources of the udev device.
361 *
362 * Returns: a new udev device, or #NULL, if it does not exist
363 **/
76387b9a 364_public_ struct udev_device *udev_device_new_from_environment(struct udev *udev) {
02e7ae2f 365 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
f4ac4d1a 366 int r;
fc8d61c5 367
02e7ae2f 368 r = device_new_from_strv(&device, environ);
fd05c424
YW
369 if (r < 0)
370 return_with_errno(NULL, r);
fc8d61c5 371
02e7ae2f 372 return udev_device_new(udev, device);
fc8d61c5
KS
373}
374
76387b9a 375static struct udev_device *device_new_from_parent(struct udev_device *child) {
02e7ae2f 376 sd_device *parent;
f4ac4d1a
TG
377 int r;
378
379 assert_return_errno(child, NULL, EINVAL);
380
02e7ae2f 381 r = sd_device_get_parent(child->device, &parent);
fd05c424
YW
382 if (r < 0)
383 return_with_errno(NULL, r);
aa0e72ea 384
02e7ae2f 385 return udev_device_new(child->udev, parent);
4ad3a37f
KS
386}
387
1e511322
KS
388/**
389 * udev_device_get_parent:
390 * @udev_device: the device to start searching from
391 *
392 * Find the next parent device, and fill in information from the sys
393 * device and the udev database entry.
394 *
572ce4f7
ZJS
395 * Returned device is not referenced. It is attached to the child
396 * device, and will be cleaned up when the child device is cleaned up.
1e511322 397 *
214a6c79 398 * It is not necessarily just the upper level directory, empty or not
1e511322
KS
399 * recognized sys directories are ignored.
400 *
401 * It can be called as many times as needed, without caring about
402 * references.
403 *
404 * Returns: a new udev device, or #NULL, if it no parent exist.
405 **/
76387b9a 406_public_ struct udev_device *udev_device_get_parent(struct udev_device *udev_device) {
f4ac4d1a
TG
407 assert_return_errno(udev_device, NULL, EINVAL);
408
912541b0
KS
409 if (!udev_device->parent_set) {
410 udev_device->parent_set = true;
f4ac4d1a 411 udev_device->parent = device_new_from_parent(udev_device);
912541b0 412 }
f4ac4d1a
TG
413
414 /* TODO: errno will differ here in case parent == NULL */
415 return udev_device->parent;
b2d9e4f2
KS
416}
417
1e511322
KS
418/**
419 * udev_device_get_parent_with_subsystem_devtype:
420 * @udev_device: udev device to start searching from
214a6c79 421 * @subsystem: the subsystem of the device
1e511322
KS
422 * @devtype: the type (DEVTYPE) of the device
423 *
424 * Find the next parent device, with a matching subsystem and devtype
425 * value, and fill in information from the sys device and the udev
426 * database entry.
427 *
79ef2e97 428 * If devtype is #NULL, only subsystem is checked, and any devtype will
54d4f54e
MP
429 * match.
430 *
572ce4f7
ZJS
431 * Returned device is not referenced. It is attached to the child
432 * device, and will be cleaned up when the child device is cleaned up.
1e511322
KS
433 *
434 * It can be called as many times as needed, without caring about
435 * references.
436 *
8d6bc73a 437 * Returns: a new udev device, or #NULL if no matching parent exists.
1e511322 438 **/
76387b9a 439_public_ struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype) {
f4ac4d1a
TG
440 sd_device *parent;
441 int r;
bf8b2ae1 442
f4ac4d1a
TG
443 assert_return_errno(udev_device, NULL, EINVAL);
444
445 /* this relies on the fact that finding the subdevice of a parent or the
446 parent of a subdevice commute */
447
448 /* first find the correct sd_device */
449 r = sd_device_get_parent_with_subsystem_devtype(udev_device->device, subsystem, devtype, &parent);
fd05c424
YW
450 if (r < 0)
451 return_with_errno(NULL, r);
883012d4 452
bbb04088 453 /* then walk the chain of udev_device parents until the corresponding
f4ac4d1a 454 one is found */
fd05c424 455 while ((udev_device = udev_device_get_parent(udev_device)))
f4ac4d1a
TG
456 if (udev_device->device == parent)
457 return udev_device;
aa0e72ea 458
fd05c424 459 return_with_errno(NULL, ENOENT);
bf8b2ae1
MH
460}
461
eb1f0e66
KS
462/**
463 * udev_device_get_udev:
7d8787b3 464 * @udev_device: udev device
eb1f0e66
KS
465 *
466 * Retrieve the udev library context the device was created with.
467 *
468 * Returns: the udev library context
469 **/
76387b9a 470_public_ struct udev *udev_device_get_udev(struct udev_device *udev_device) {
f4ac4d1a
TG
471 assert_return_errno(udev_device, NULL, EINVAL);
472
912541b0 473 return udev_device->udev;
eb1f0e66
KS
474}
475
3c6ac219
YW
476static struct udev_device *udev_device_free(struct udev_device *udev_device) {
477 assert(udev_device);
478
479 sd_device_unref(udev_device->device);
480 udev_device_unref(udev_device->parent);
481
dcf557f7
YW
482 udev_list_free(udev_device->properties);
483 udev_list_free(udev_device->sysattrs);
3b684be0
LP
484 udev_list_free(udev_device->all_tags);
485 udev_list_free(udev_device->current_tags);
dcf557f7 486 udev_list_free(udev_device->devlinks);
3c6ac219
YW
487
488 return mfree(udev_device);
489}
490
eb1f0e66
KS
491/**
492 * udev_device_ref:
493 * @udev_device: udev device
494 *
495 * Take a reference of a udev device.
496 *
497 * Returns: the passed udev device
498 **/
eb1f0e66
KS
499
500/**
501 * udev_device_unref:
502 * @udev_device: udev device
503 *
504 * Drop a reference of a udev device. If the refcount reaches zero,
be7de409 505 * the resources of the device will be released.
eb1f0e66 506 *
725d7e6c 507 * Returns: #NULL
eb1f0e66 508 **/
3c6ac219 509DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_device, udev_device, udev_device_free);
eb1f0e66
KS
510
511/**
512 * udev_device_get_devpath:
513 * @udev_device: udev device
514 *
11d543c1
KS
515 * Retrieve the kernel devpath value of the udev device. The path
516 * does not contain the sys mount point, and starts with a '/'.
eb1f0e66 517 *
11d543c1 518 * Returns: the devpath of the udev device
eb1f0e66 519 **/
76387b9a 520_public_ const char *udev_device_get_devpath(struct udev_device *udev_device) {
f4ac4d1a
TG
521 const char *devpath;
522 int r;
523
524 assert_return_errno(udev_device, NULL, EINVAL);
525
526 r = sd_device_get_devpath(udev_device->device, &devpath);
fd05c424
YW
527 if (r < 0)
528 return_with_errno(NULL, r);
f4ac4d1a
TG
529
530 return devpath;
eb1f0e66
KS
531}
532
11d543c1
KS
533/**
534 * udev_device_get_syspath:
535 * @udev_device: udev device
536 *
537 * Retrieve the sys path of the udev device. The path is an
538 * absolute path and starts with the sys mount point.
539 *
540 * Returns: the sys path of the udev device
541 **/
76387b9a 542_public_ const char *udev_device_get_syspath(struct udev_device *udev_device) {
f4ac4d1a
TG
543 const char *syspath;
544 int r;
545
546 assert_return_errno(udev_device, NULL, EINVAL);
547
548 r = sd_device_get_syspath(udev_device->device, &syspath);
fd05c424
YW
549 if (r < 0)
550 return_with_errno(NULL, r);
f4ac4d1a
TG
551
552 return syspath;
11d543c1
KS
553}
554
1e511322
KS
555/**
556 * udev_device_get_sysname:
557 * @udev_device: udev device
558 *
21dbe43a
KS
559 * Get the kernel device name in /sys.
560 *
61233823 561 * Returns: the name string of the device
1e511322 562 **/
76387b9a 563_public_ const char *udev_device_get_sysname(struct udev_device *udev_device) {
f4ac4d1a
TG
564 const char *sysname;
565 int r;
566
567 assert_return_errno(udev_device, NULL, EINVAL);
568
569 r = sd_device_get_sysname(udev_device->device, &sysname);
fd05c424
YW
570 if (r < 0)
571 return_with_errno(NULL, r);
f4ac4d1a
TG
572
573 return sysname;
4ad3a37f
KS
574}
575
1e511322
KS
576/**
577 * udev_device_get_sysnum:
578 * @udev_device: udev device
579 *
21dbe43a
KS
580 * Get the instance number of the device.
581 *
c5315881 582 * Returns: the trailing number string of the device name
1e511322 583 **/
76387b9a 584_public_ const char *udev_device_get_sysnum(struct udev_device *udev_device) {
f4ac4d1a
TG
585 const char *sysnum;
586 int r;
587
588 assert_return_errno(udev_device, NULL, EINVAL);
589
590 r = sd_device_get_sysnum(udev_device->device, &sysnum);
fd05c424 591 if (r == -ENOENT)
912541b0 592 return NULL;
fd05c424
YW
593 if (r < 0)
594 return_with_errno(NULL, r);
f4ac4d1a
TG
595
596 return sysnum;
517814e7
KS
597}
598
eb1f0e66 599/**
fb762bb9 600 * udev_device_get_devnode:
eb1f0e66
KS
601 * @udev_device: udev device
602 *
603 * Retrieve the device node file name belonging to the udev device.
ba6929f6 604 * The path is an absolute path, and starts with the device directory.
eb1f0e66
KS
605 *
606 * Returns: the device node file name of the udev device, or #NULL if no device node exists
607 **/
76387b9a 608_public_ const char *udev_device_get_devnode(struct udev_device *udev_device) {
f4ac4d1a
TG
609 const char *devnode;
610 int r;
611
612 assert_return_errno(udev_device, NULL, EINVAL);
613
614 r = sd_device_get_devname(udev_device->device, &devnode);
fd05c424
YW
615 if (r < 0)
616 return_with_errno(NULL, r);
f4ac4d1a
TG
617
618 return devnode;
eb1f0e66
KS
619}
620
eb1f0e66 621/**
0de33a61 622 * udev_device_get_devlinks_list_entry:
eb1f0e66 623 * @udev_device: udev device
eb1f0e66 624 *
bf7ad0ea
KS
625 * Retrieve the list of device links pointing to the device file of
626 * the udev device. The next list entry can be retrieved with
bb061708 627 * udev_list_entry_get_next(), which returns #NULL if no more entries exist.
bf7ad0ea 628 * The devlink path can be retrieved from the list entry by
e345e267 629 * udev_list_entry_get_name(). The path is an absolute path, and starts with
bf7ad0ea 630 * the device directory.
eb1f0e66 631 *
bf7ad0ea 632 * Returns: the first entry of the device node link list
eb1f0e66 633 **/
76387b9a 634_public_ struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device) {
f4ac4d1a 635 assert_return_errno(udev_device, NULL, EINVAL);
eb1f0e66 636
378f61eb
TG
637 if (device_get_devlinks_generation(udev_device->device) != udev_device->devlinks_generation ||
638 !udev_device->devlinks_read) {
dcf557f7 639 udev_list_cleanup(udev_device->devlinks);
f4ac4d1a
TG
640
641 FOREACH_DEVICE_DEVLINK(udev_device->device, devlink)
dcf557f7 642 if (!udev_list_entry_add(udev_device->devlinks, devlink, NULL))
3f14e721 643 return_with_errno(NULL, ENOMEM);
f4ac4d1a 644
378f61eb 645 udev_device->devlinks_read = true;
f4ac4d1a
TG
646 udev_device->devlinks_generation = device_get_devlinks_generation(udev_device->device);
647 }
648
dcf557f7 649 return udev_list_get_entry(udev_device->devlinks);
979ff016
KS
650}
651
eb1f0e66 652/**
f4ac4d1a 653 * udev_device_get_event_properties_entry:
eb1f0e66 654 * @udev_device: udev device
eb1f0e66 655 *
bf7ad0ea 656 * Retrieve the list of key/value device properties of the udev
bb061708 657 * device. The next list entry can be retrieved with udev_list_entry_get_next(),
bf7ad0ea 658 * which returns #NULL if no more entries exist. The property name
bb061708
KS
659 * can be retrieved from the list entry by udev_list_entry_get_name(),
660 * the property value by udev_list_entry_get_value().
eb1f0e66 661 *
bf7ad0ea 662 * Returns: the first entry of the property list
eb1f0e66 663 **/
76387b9a 664_public_ struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device) {
f4ac4d1a
TG
665 assert_return_errno(udev_device, NULL, EINVAL);
666
378f61eb
TG
667 if (device_get_properties_generation(udev_device->device) != udev_device->properties_generation ||
668 !udev_device->properties_read) {
dcf557f7 669 udev_list_cleanup(udev_device->properties);
f4ac4d1a
TG
670
671 FOREACH_DEVICE_PROPERTY(udev_device->device, key, value)
dcf557f7 672 if (!udev_list_entry_add(udev_device->properties, key, value))
3f14e721 673 return_with_errno(NULL, ENOMEM);
f4ac4d1a 674
378f61eb 675 udev_device->properties_read = true;
f4ac4d1a 676 udev_device->properties_generation = device_get_properties_generation(udev_device->device);
912541b0 677 }
f4ac4d1a 678
dcf557f7 679 return udev_list_get_entry(udev_device->properties);
eb1f0e66 680}
11d543c1 681
1e511322
KS
682/**
683 * udev_device_get_action:
684 * @udev_device: udev device
685 *
686 * This is only valid if the device was received through a monitor. Devices read from
64db4c3c
BN
687 * sys do not have an action string. Usual actions are: add, remove, change, move,
688 * online, offline.
1e511322
KS
689 *
690 * Returns: the kernel action value, or #NULL if there is no action value available.
691 **/
f4ac4d1a 692_public_ const char *udev_device_get_action(struct udev_device *udev_device) {
a1130022 693 sd_device_action_t action;
f4ac4d1a
TG
694
695 assert_return_errno(udev_device, NULL, EINVAL);
696
a1130022 697 if (sd_device_get_action(udev_device->device, &action) < 0)
912541b0 698 return NULL;
f4ac4d1a 699
40769ccc 700 return device_action_to_string(action);
c4f5f942
KS
701}
702
9c6a11b1
KS
703/**
704 * udev_device_get_usec_since_initialized:
705 * @udev_device: udev device
706 *
707 * Return the number of microseconds passed since udev set up the
708 * device for the first time.
709 *
710 * This is only implemented for devices with need to store properties
711 * in the udev database. All other devices return 0 here.
712 *
713 * Returns: the number of microseconds since the device was first seen.
714 **/
76387b9a 715_public_ unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device) {
f4ac4d1a
TG
716 usec_t ts;
717 int r;
9c6a11b1 718
f4ac4d1a
TG
719 assert_return(udev_device, -EINVAL);
720
721 r = sd_device_get_usec_since_initialized(udev_device->device, &ts);
fd05c424
YW
722 if (r < 0)
723 return_with_errno(0, r);
9c6a11b1 724
f4ac4d1a 725 return ts;
9c6a11b1
KS
726}
727
1e511322
KS
728/**
729 * udev_device_get_sysattr_value:
730 * @udev_device: udev device
731 * @sysattr: attribute name
732 *
456719b6 733 * The retrieved value is cached in the device. Repeated calls will return the same
1e511322
KS
734 * value and not open the attribute again.
735 *
736 * Returns: the content of a sys attribute file, or #NULL if there is no sys attribute value.
737 **/
76387b9a 738_public_ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) {
f4ac4d1a
TG
739 const char *value;
740 int r;
912541b0 741
f4ac4d1a 742 assert_return_errno(udev_device, NULL, EINVAL);
912541b0 743
f4ac4d1a 744 r = sd_device_get_sysattr_value(udev_device->device, sysattr, &value);
fd05c424
YW
745 if (r < 0)
746 return_with_errno(NULL, r);
912541b0 747
f4ac4d1a 748 return value;
93b0f384 749}
517814e7 750
946f1825
HR
751/**
752 * udev_device_set_sysattr_value:
753 * @udev_device: udev device
754 * @sysattr: attribute name
755 * @value: new value to be set
756 *
757 * Update the contents of the sys attribute and the cached value of the device.
758 *
759 * Returns: Negative error code on failure or 0 on success.
760 **/
8aae9a66 761_public_ int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, const char *value) {
f4ac4d1a 762 int r;
f180ad25 763
f4ac4d1a 764 assert_return(udev_device, -EINVAL);
f180ad25 765
f4ac4d1a
TG
766 r = sd_device_set_sysattr_value(udev_device->device, sysattr, value);
767 if (r < 0)
768 return r;
f180ad25 769
f4ac4d1a 770 return 0;
f180ad25
TE
771}
772
773/**
774 * udev_device_get_sysattr_list_entry:
775 * @udev_device: udev device
776 *
777 * Retrieve the list of available sysattrs, with value being empty;
20bee04c
KS
778 * This just return all available sysfs attributes for a particular
779 * device without reading their values.
f180ad25
TE
780 *
781 * Returns: the first entry of the property list
782 **/
76387b9a 783_public_ struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device) {
f4ac4d1a 784 assert_return_errno(udev_device, NULL, EINVAL);
f180ad25 785
f4ac4d1a 786 if (!udev_device->sysattrs_read) {
dcf557f7 787 udev_list_cleanup(udev_device->sysattrs);
11d543c1 788
f4ac4d1a 789 FOREACH_DEVICE_SYSATTR(udev_device->device, sysattr)
dcf557f7 790 if (!udev_list_entry_add(udev_device->sysattrs, sysattr, NULL))
3f14e721 791 return_with_errno(NULL, ENOMEM);
11d543c1 792
f4ac4d1a 793 udev_device->sysattrs_read = true;
912541b0 794 }
f4ac4d1a 795
dcf557f7 796 return udev_list_get_entry(udev_device->sysattrs);
4281da1f
KS
797}
798
48a0170b
KS
799/**
800 * udev_device_get_is_initialized:
801 * @udev_device: udev device
802 *
803 * Check if udev has already handled the device and has set up
804 * device node permissions and context, or has renamed a network
805 * device.
806 *
9c6a11b1 807 * This is only implemented for devices with a device node
48a0170b
KS
808 * or network interfaces. All other devices return 1 here.
809 *
810 * Returns: 1 if the device is set up. 0 otherwise.
811 **/
76387b9a 812_public_ int udev_device_get_is_initialized(struct udev_device *udev_device) {
5a937ea2 813 int r;
48a0170b 814
f4ac4d1a 815 assert_return(udev_device, -EINVAL);
48a0170b 816
5a937ea2 817 r = sd_device_get_is_initialized(udev_device->device);
fd05c424
YW
818 if (r < 0)
819 return_with_errno(0, r);
8e3ba377 820
5a937ea2 821 return r;
28460195
KS
822}
823
f712894d
KS
824/**
825 * udev_device_get_tags_list_entry:
826 * @udev_device: udev device
827 *
828 * Retrieve the list of tags attached to the udev device. The next
bb061708 829 * list entry can be retrieved with udev_list_entry_get_next(),
f712894d 830 * which returns #NULL if no more entries exist. The tag string
bb061708 831 * can be retrieved from the list entry by udev_list_entry_get_name().
f712894d
KS
832 *
833 * Returns: the first entry of the tag list
834 **/
76387b9a 835_public_ struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device) {
f4ac4d1a
TG
836 assert_return_errno(udev_device, NULL, EINVAL);
837
3b684be0
LP
838 if (device_get_tags_generation(udev_device->device) != udev_device->all_tags_generation ||
839 !udev_device->all_tags_read) {
3b684be0 840 udev_list_cleanup(udev_device->all_tags);
f4ac4d1a
TG
841
842 FOREACH_DEVICE_TAG(udev_device->device, tag)
3b684be0
LP
843 if (!udev_list_entry_add(udev_device->all_tags, tag, NULL))
844 return_with_errno(NULL, ENOMEM);
845
846 udev_device->all_tags_read = true;
847 udev_device->all_tags_generation = device_get_tags_generation(udev_device->device);
848 }
849
850 return udev_list_get_entry(udev_device->all_tags);
851}
852
853_public_ struct udev_list_entry *udev_device_get_current_tags_list_entry(struct udev_device *udev_device) {
854 assert_return_errno(udev_device, NULL, EINVAL);
855
856 if (device_get_tags_generation(udev_device->device) != udev_device->current_tags_generation ||
857 !udev_device->current_tags_read) {
3b684be0
LP
858 udev_list_cleanup(udev_device->current_tags);
859
860 FOREACH_DEVICE_CURRENT_TAG(udev_device->device, tag)
861 if (!udev_list_entry_add(udev_device->current_tags, tag, NULL))
3f14e721 862 return_with_errno(NULL, ENOMEM);
f4ac4d1a 863
3b684be0
LP
864 udev_device->current_tags_read = true;
865 udev_device->current_tags_generation = device_get_tags_generation(udev_device->device);
f4ac4d1a
TG
866 }
867
3b684be0 868 return udev_list_get_entry(udev_device->current_tags);
28460195
KS
869}
870
21dbe43a
KS
871/**
872 * udev_device_has_tag:
873 * @udev_device: udev device
874 * @tag: tag name
875 *
876 * Check if a given device has a certain tag associated.
877 *
878 * Returns: 1 if the tag is found. 0 otherwise.
879 **/
33a03e6e 880_public_ int udev_device_has_tag(struct udev_device *udev_device, const char *tag) {
f4ac4d1a 881 assert_return(udev_device, 0);
fa639f3a 882
33a03e6e 883 return sd_device_has_tag(udev_device->device, tag) > 0;
1cd0a770 884}
538bdb48 885
3b684be0
LP
886_public_ int udev_device_has_current_tag(struct udev_device *udev_device, const char *tag) {
887 assert_return(udev_device, 0);
888
889 return sd_device_has_current_tag(udev_device->device, tag) > 0;
890}
891
538bdb48
YW
892sd_device *udev_device_get_sd_device(struct udev_device *udev_device) {
893 assert(udev_device);
894
895 return udev_device->device;
896}