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