]> git.ipfire.org Git - thirdparty/systemd.git/blame - libudev/libudev-device.c
libudev: enumerate - allow to filter-out not-already-initialized devices
[thirdparty/systemd.git] / libudev / libudev-device.c
CommitLineData
eb1f0e66
KS
1/*
2 * libudev - interface to udev device information
3 *
fbb31cd6 4 * Copyright (C) 2008-2010 Kay Sievers <kay.sievers@vrfy.org>
eb1f0e66 5 *
4061ab9f
KS
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
eb1f0e66
KS
10 */
11
eb1f0e66
KS
12#include <stdio.h>
13#include <stdlib.h>
14#include <stddef.h>
15#include <unistd.h>
fc8d61c5 16#include <stdbool.h>
eb1f0e66
KS
17#include <errno.h>
18#include <string.h>
19#include <dirent.h>
93b0f384 20#include <fcntl.h>
517814e7 21#include <ctype.h>
eb1f0e66
KS
22#include <sys/stat.h>
23
24#include "libudev.h"
25#include "libudev-private.h"
eb1f0e66 26
ce1d6d7f
KS
27/**
28 * SECTION:libudev-device
29 * @short_description: kernel sys devices
30 *
31 * Representation of kernel sys devices. Devices are uniquely identified
32 * by their syspath, every device has exactly one path in the kernel sys
33 * filesystem. Devices usually belong to a kernel subsystem, and and have
214a6c79 34 * a unique name inside that subsystem.
ce1d6d7f
KS
35 */
36
1e511322
KS
37/**
38 * udev_device:
39 *
ce1d6d7f 40 * Opaque object representing one kernel sys device.
1e511322 41 */
11d543c1 42struct udev_device {
11d543c1 43 struct udev *udev;
b2d9e4f2 44 struct udev_device *parent_device;
11d543c1 45 char *syspath;
4ad3a37f 46 const char *devpath;
517814e7
KS
47 char *sysname;
48 const char *sysnum;
99214844 49 char *devnode;
11d543c1 50 char *subsystem;
bf8b2ae1 51 char *devtype;
979ff016 52 char *driver;
c4f5f942 53 char *action;
c4f5f942 54 char *devpath_old;
2ffc9cc1 55 char *sysname_old;
cb14f454 56 char *knodename;
4281da1f 57 char *id_filename;
6493e655 58 char **envp;
c2654402
KS
59 char *monitor_buf;
60 size_t monitor_buf_len;
b99028c9
KS
61 struct udev_list_node devlinks_list;
62 struct udev_list_node properties_list;
63 struct udev_list_node sysattr_list;
28460195 64 struct udev_list_node tags_list;
6bd1c78a 65 unsigned long long int seqnum;
b99028c9
KS
66 int event_timeout;
67 int timeout;
e88a82b5 68 int devlink_priority;
b99028c9
KS
69 int refcount;
70 dev_t devnum;
fc416258 71 int ifindex;
d7ce7539 72 int watch_handle;
fc8d61c5 73 int maj, min;
28460195
KS
74 bool parent_set;
75 bool subsystem_set;
76 bool devtype_set;
77 bool devlinks_uptodate;
78 bool envp_uptodate;
79 bool tags_uptodate;
80 bool driver_set;
81 bool info_loaded;
82 bool db_loaded;
83 bool uevent_loaded;
48a0170b 84 bool is_initialized;
11d543c1
KS
85};
86
fc8d61c5
KS
87struct udev_list_entry *udev_device_add_property(struct udev_device *udev_device, const char *key, const char *value)
88{
28460195 89 udev_device->envp_uptodate = false;
fc8d61c5
KS
90 if (value == NULL) {
91 struct udev_list_entry *list_entry;
92
93 list_entry = udev_device_get_properties_list_entry(udev_device);
94 list_entry = udev_list_entry_get_by_name(list_entry, key);
95 if (list_entry != NULL)
96 udev_list_entry_delete(list_entry);
97 return NULL;
98 }
99 return udev_list_entry_add(udev_device->udev, &udev_device->properties_list, key, value, 1, 0);
100}
101
102static struct udev_list_entry *udev_device_add_property_from_string(struct udev_device *udev_device, const char *property)
103{
104 char name[UTIL_LINE_SIZE];
105 char *val;
106
107 util_strscpy(name, sizeof(name), property);
108 val = strchr(name, '=');
109 if (val == NULL)
110 return NULL;
111 val[0] = '\0';
112 val = &val[1];
113 if (val[0] == '\0')
114 val = NULL;
115 return udev_device_add_property(udev_device, name, val);
116}
117
118/*
119 * parse property string, and if needed, update internal values accordingly
120 *
121 * udev_device_add_property_from_string_parse_finish() needs to be
122 * called after adding properties, and its return value checked
123 *
124 * udev_device_set_info_loaded() needs to be set, to avoid trying
125 * to use a device without a DEVPATH set
126 */
127void udev_device_add_property_from_string_parse(struct udev_device *udev_device, const char *property)
128{
129 if (strncmp(property, "DEVPATH=", 8) == 0) {
130 char path[UTIL_PATH_SIZE];
131
132 util_strscpyl(path, sizeof(path), udev_get_sys_path(udev_device->udev), &property[8], NULL);
133 udev_device_set_syspath(udev_device, path);
134 } else if (strncmp(property, "SUBSYSTEM=", 10) == 0) {
135 udev_device_set_subsystem(udev_device, &property[10]);
136 } else if (strncmp(property, "DEVTYPE=", 8) == 0) {
137 udev_device_set_devtype(udev_device, &property[8]);
138 } else if (strncmp(property, "DEVNAME=", 8) == 0) {
139 if (property[8] == '/')
140 udev_device_set_devnode(udev_device, &property[8]);
141 else
142 udev_device_set_knodename(udev_device, &property[8]);
143 } else if (strncmp(property, "DEVLINKS=", 9) == 0) {
144 char devlinks[UTIL_PATH_SIZE];
145 char *slink;
146 char *next;
147
148 util_strscpy(devlinks, sizeof(devlinks), &property[9]);
149 slink = devlinks;
150 next = strchr(slink, ' ');
151 while (next != NULL) {
152 next[0] = '\0';
153 udev_device_add_devlink(udev_device, slink, 0);
154 slink = &next[1];
155 next = strchr(slink, ' ');
156 }
157 if (slink[0] != '\0')
158 udev_device_add_devlink(udev_device, slink, 0);
28460195
KS
159 } else if (strncmp(property, "TAGS=", 5) == 0) {
160 char tags[UTIL_PATH_SIZE];
161 char *next;
162
163 util_strscpy(tags, sizeof(tags), &property[5]);
164 next = strchr(tags, ':');
165 if (next != NULL) {
166 next++;
167 while (next[0] != '\0') {
168 char *tag;
169
170 tag = next;
171 next = strchr(tag, ':');
172 if (next == NULL)
173 break;
174 next[0] = '\0';
175 next++;
176 udev_device_add_tag(udev_device, tag);
177 }
178 }
fc8d61c5
KS
179 } else if (strncmp(property, "DRIVER=", 7) == 0) {
180 udev_device_set_driver(udev_device, &property[7]);
181 } else if (strncmp(property, "ACTION=", 7) == 0) {
182 udev_device_set_action(udev_device, &property[7]);
183 } else if (strncmp(property, "MAJOR=", 6) == 0) {
184 udev_device->maj = strtoull(&property[6], NULL, 10);
185 } else if (strncmp(property, "MINOR=", 6) == 0) {
186 udev_device->min = strtoull(&property[6], NULL, 10);
187 } else if (strncmp(property, "DEVPATH_OLD=", 12) == 0) {
188 udev_device_set_devpath_old(udev_device, &property[12]);
189 } else if (strncmp(property, "SEQNUM=", 7) == 0) {
190 udev_device_set_seqnum(udev_device, strtoull(&property[7], NULL, 10));
191 } else if (strncmp(property, "TIMEOUT=", 8) == 0) {
192 udev_device_set_timeout(udev_device, strtoull(&property[8], NULL, 10));
fc416258
KS
193 } else if (strncmp(property, "IFINDEX=", 8) == 0) {
194 udev_device_set_ifindex(udev_device, strtoull(&property[8], NULL, 10));
fc8d61c5
KS
195 } else {
196 udev_device_add_property_from_string(udev_device, property);
197 }
198}
199
200int udev_device_add_property_from_string_parse_finish(struct udev_device *udev_device)
201{
202 if (udev_device->maj > 0)
203 udev_device_set_devnum(udev_device, makedev(udev_device->maj, udev_device->min));
204 udev_device->maj = 0;
205 udev_device->min = 0;
206
207 if (udev_device->devpath == NULL || udev_device->subsystem == NULL)
208 return -EINVAL;
209 return 0;
210}
211
212/**
213 * udev_device_get_property_value:
214 * @udev_device: udev device
215 * @key: property name
216 *
217 * Returns: the value of a device property, or #NULL if there is no such property.
218 **/
219const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key)
220{
221 struct udev_list_entry *list_entry;
222
223 if (udev_device == NULL)
224 return NULL;
225 if (key == NULL)
226 return NULL;
227
228 list_entry = udev_device_get_properties_list_entry(udev_device);
229 list_entry = udev_list_entry_get_by_name(list_entry, key);
230 return udev_list_entry_get_value(list_entry);
231}
232
77b852f3 233int udev_device_read_db(struct udev_device *udev_device)
e88a82b5 234{
4281da1f 235 const char *id;
3eb46ec6
KS
236 char filename[UTIL_PATH_SIZE];
237 char line[UTIL_LINE_SIZE];
e88a82b5 238 FILE *f;
e88a82b5 239
28460195
KS
240 if (udev_device->db_loaded)
241 return 0;
24d10766 242 udev_device->db_loaded = true;
28460195 243
4281da1f
KS
244 id = udev_device_get_id_filename(udev_device);
245 if (id == NULL)
246 return -1;
247 util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/.udev/db/", id, NULL);
0c5c4804 248 f = fopen(filename, "re");
e88a82b5 249 if (f == NULL) {
24d10766 250 info(udev_device->udev, "no db file to read %s: %m\n", filename);
e88a82b5
KS
251 return -1;
252 }
48a0170b 253 udev_device->is_initialized = true;
bfd88b1d 254
e88a82b5
KS
255 while (fgets(line, sizeof(line), f)) {
256 ssize_t len;
257 const char *val;
24d10766 258 struct udev_list_entry *entry;
e88a82b5
KS
259
260 len = strlen(line);
261 if (len < 4)
262 break;
263 line[len-1] = '\0';
264 val = &line[2];
e88a82b5
KS
265 switch(line[0]) {
266 case 'N':
065db052 267 util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/", val, NULL);
517814e7 268 udev_device_set_devnode(udev_device, filename);
e88a82b5 269 break;
e88a82b5 270 case 'S':
065db052 271 util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/", val, NULL);
6c29f2b9 272 udev_device_add_devlink(udev_device, filename, 0);
e88a82b5
KS
273 break;
274 case 'L':
8cd2e972 275 udev_device_set_devlink_priority(udev_device, atoi(val));
e88a82b5 276 break;
e88a82b5 277 case 'E':
24d10766
KS
278 entry = udev_device_add_property_from_string(udev_device, val);
279 udev_list_entry_set_flags(entry, 1);
e88a82b5 280 break;
28460195
KS
281 case 'G':
282 udev_device_add_tag(udev_device, val);
283 break;
d7ce7539
SJR
284 case 'W':
285 udev_device_set_watch_handle(udev_device, atoi(val));
286 break;
e88a82b5
KS
287 }
288 }
289 fclose(f);
290
cd42b50d 291 info(udev_device->udev, "device %p filled with db file data\n", udev_device);
04f5d75f 292 return 0;
e88a82b5
KS
293}
294
bd85566c 295int udev_device_read_uevent_file(struct udev_device *udev_device)
99214844
KS
296{
297 char filename[UTIL_PATH_SIZE];
298 FILE *f;
299 char line[UTIL_LINE_SIZE];
300 int maj = 0;
301 int min = 0;
302
28460195
KS
303 if (udev_device->uevent_loaded)
304 return 0;
305
065db052 306 util_strscpyl(filename, sizeof(filename), udev_device->syspath, "/uevent", NULL);
0c5c4804 307 f = fopen(filename, "re");
99214844
KS
308 if (f == NULL)
309 return -1;
bfd88b1d 310 udev_device->uevent_loaded = true;
99214844
KS
311
312 while (fgets(line, sizeof(line), f)) {
313 char *pos;
314
315 pos = strchr(line, '\n');
316 if (pos == NULL)
317 continue;
318 pos[0] = '\0';
319
bf8b2ae1
MH
320 if (strncmp(line, "DEVTYPE=", 8) == 0)
321 udev_device_set_devtype(udev_device, &line[8]);
322 else if (strncmp(line, "MAJOR=", 6) == 0)
99214844
KS
323 maj = strtoull(&line[6], NULL, 10);
324 else if (strncmp(line, "MINOR=", 6) == 0)
325 min = strtoull(&line[6], NULL, 10);
fc416258
KS
326 else if (strncmp(line, "IFINDEX=", 8) == 0)
327 udev_device_set_ifindex(udev_device, strtoull(&line[8], NULL, 10));
cb14f454
KS
328 else if (strncmp(line, "DEVNAME=", 8) == 0)
329 udev_device_set_knodename(udev_device, &line[8]);
99214844 330
8cd2e972 331 udev_device_add_property_from_string(udev_device, line);
99214844
KS
332 }
333
334 udev_device->devnum = makedev(maj, min);
99214844
KS
335 fclose(f);
336 return 0;
337}
338
8cd2e972 339void udev_device_set_info_loaded(struct udev_device *device)
99214844 340{
28460195 341 device->info_loaded = true;
99214844
KS
342}
343
a5710160 344struct udev_device *udev_device_new(struct udev *udev)
eb1f0e66
KS
345{
346 struct udev_device *udev_device;
ebacd6ec 347 struct udev_list_entry *list_entry;
eb1f0e66 348
ba6929f6
KS
349 if (udev == NULL)
350 return NULL;
351
b29a5e4a 352 udev_device = calloc(1, sizeof(struct udev_device));
eb1f0e66
KS
353 if (udev_device == NULL)
354 return NULL;
eb1f0e66
KS
355 udev_device->refcount = 1;
356 udev_device->udev = udev;
517814e7 357 udev_list_init(&udev_device->devlinks_list);
8cd2e972 358 udev_list_init(&udev_device->properties_list);
69239210 359 udev_list_init(&udev_device->sysattr_list);
28460195 360 udev_list_init(&udev_device->tags_list);
979ff016 361 udev_device->event_timeout = -1;
d7ce7539 362 udev_device->watch_handle = -1;
ebacd6ec
KS
363 /* copy global properties */
364 udev_list_entry_foreach(list_entry, udev_get_properties_list_entry(udev))
365 udev_device_add_property(udev_device,
366 udev_list_entry_get_name(list_entry),
367 udev_list_entry_get_value(list_entry));
86b57788 368 dbg(udev_device->udev, "udev_device: %p created\n", udev_device);
eb1f0e66
KS
369 return udev_device;
370}
371
372/**
8753fadf 373 * udev_device_new_from_syspath:
eb1f0e66 374 * @udev: udev library context
8753fadf 375 * @syspath: sys device path including sys directory
eb1f0e66 376 *
8753fadf 377 * Create new udev device, and fill in information from the sys
214a6c79 378 * device and the udev database entry. The syspath is the absolute
8753fadf 379 * path to the device, including the sys mount point.
eb1f0e66
KS
380 *
381 * The initial refcount is 1, and needs to be decremented to
be7de409 382 * release the resources of the udev device.
eb1f0e66
KS
383 *
384 * Returns: a new udev device, or #NULL, if it does not exist
385 **/
8753fadf 386struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath)
eb1f0e66 387{
b95f8a76
KS
388 size_t len;
389 const char *subdir;
3eb46ec6 390 char path[UTIL_PATH_SIZE];
62b9dfb6 391 char *pos;
eb1f0e66
KS
392 struct stat statbuf;
393 struct udev_device *udev_device;
eb1f0e66 394
ba6929f6
KS
395 if (udev == NULL)
396 return NULL;
8753fadf 397 if (syspath == NULL)
ba6929f6
KS
398 return NULL;
399
b95f8a76
KS
400 /* path starts in sys */
401 len = strlen(udev_get_sys_path(udev));
402 if (strncmp(syspath, udev_get_sys_path(udev), len) != 0) {
403 info(udev, "not in sys :%s\n", syspath);
eb1f0e66 404 return NULL;
4ad3a37f 405 }
eb1f0e66 406
b95f8a76
KS
407 /* path is not a root directory */
408 subdir = &syspath[len+1];
409 pos = strrchr(subdir, '/');
f454f670 410 if (pos == NULL || pos[1] == '\0' || pos < &subdir[2]) {
86b57788 411 dbg(udev, "not a subdir :%s\n", syspath);
eb1f0e66 412 return NULL;
b95f8a76 413 }
eb1f0e66 414
ba6929f6 415 /* resolve possible symlink to real path */
065db052 416 util_strscpy(path, sizeof(path), syspath);
b21b95d7 417 util_resolve_sys_link(udev, path, sizeof(path));
b95f8a76 418
28460195 419 if (strncmp(&path[len], "/devices/", 9) == 0) {
b95f8a76
KS
420 char file[UTIL_PATH_SIZE];
421
422 /* all "devices" require a "uevent" file */
065db052 423 util_strscpyl(file, sizeof(file), path, "/uevent", NULL);
b95f8a76 424 if (stat(file, &statbuf) != 0) {
86b57788 425 dbg(udev, "not a device: %s\n", syspath);
b95f8a76
KS
426 return NULL;
427 }
428 } else {
429 /* everything else just needs to be a directory */
430 if (stat(path, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) {
86b57788 431 dbg(udev, "directory not found: %s\n", syspath);
b95f8a76
KS
432 return NULL;
433 }
434 }
435
a5710160 436 udev_device = udev_device_new(udev);
b95f8a76
KS
437 if (udev_device == NULL)
438 return NULL;
439
8cd2e972 440 udev_device_set_syspath(udev_device, path);
7d563a17 441 info(udev, "device %p has devpath '%s'\n", udev_device, udev_device_get_devpath(udev_device));
eb1f0e66 442
eb1f0e66
KS
443 return udev_device;
444}
445
1e511322
KS
446/**
447 * udev_device_new_from_devnum:
448 * @udev: udev library context
449 * @type: char or block device
450 * @devnum: device major/minor number
451 *
452 * Create new udev device, and fill in information from the sys
dbba7e40
KS
453 * device and the udev database entry. The device is looked-up
454 * by its major/minor number and type. Character and block device
455 * numbers are not unique across the two types.
1e511322
KS
456 *
457 * The initial refcount is 1, and needs to be decremented to
458 * release the resources of the udev device.
459 *
460 * Returns: a new udev device, or #NULL, if it does not exist
461 **/
4c9dff47
KS
462struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum)
463{
464 char path[UTIL_PATH_SIZE];
03198b93
KS
465 const char *type_str;
466
467 if (type == 'b')
468 type_str = "block";
469 else if (type == 'c')
470 type_str = "char";
471 else
472 return NULL;
4c9dff47 473
58b533f4
KS
474 /* use /sys/dev/{block,char}/<maj>:<min> link */
475 snprintf(path, sizeof(path), "%s/dev/%s/%u:%u",
476 udev_get_sys_path(udev), type_str, major(devnum), minor(devnum));
477 return udev_device_new_from_syspath(udev, path);
4c9dff47
KS
478}
479
cad40a5f
KS
480struct udev_device *udev_device_new_from_id_filename(struct udev *udev, char *id)
481{
482 char type;
483 int maj, min;
484 char subsys[UTIL_PATH_SIZE];
485 char *sysname;
486
487 switch(id[0]) {
488 case 'b':
489 case 'c':
490 if (sscanf(id, "%c%i:%i", &type, &maj, &min) != 3)
491 return NULL;
492 return udev_device_new_from_devnum(udev, type, makedev(maj, min));
493 case '+':
494 util_strscpy(subsys, sizeof(subsys), &id[1]);
495 sysname = strchr(subsys, ':');
496 if (sysname == NULL)
497 return NULL;
498 sysname[0] = '\0';
499 sysname = &sysname[1];
500 return udev_device_new_from_subsystem_sysname(udev, subsys, sysname);
501 default:
502 return NULL;
503 }
504}
505
1e511322
KS
506/**
507 * udev_device_new_from_subsystem_sysname:
508 * @udev: udev library context
214a6c79 509 * @subsystem: the subsystem of the device
1e511322
KS
510 * @sysname: the name of the device
511 *
dbba7e40
KS
512 * Create new udev device, and fill in information from the sys device
513 * and the udev database entry. The device is looked up by the subsystem
514 * and name string of the device, like "mem" / "zero", or "block" / "sda".
1e511322
KS
515 *
516 * The initial refcount is 1, and needs to be decremented to
517 * release the resources of the udev device.
518 *
519 * Returns: a new udev device, or #NULL, if it does not exist
520 **/
90d80c2e
KS
521struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname)
522{
90d80c2e
KS
523 char path_full[UTIL_PATH_SIZE];
524 char *path;
065db052 525 size_t l;
90d80c2e
KS
526 struct stat statbuf;
527
065db052
KS
528 path = path_full;
529 l = util_strpcpyl(&path, sizeof(path_full), udev_get_sys_path(udev), NULL);
90d80c2e
KS
530
531 if (strcmp(subsystem, "subsystem") == 0) {
065db052 532 util_strscpyl(path, l, "/subsystem/", sysname, NULL);
90d80c2e
KS
533 if (stat(path_full, &statbuf) == 0)
534 goto found;
535
065db052 536 util_strscpyl(path, l, "/bus/", sysname, NULL);
90d80c2e
KS
537 if (stat(path_full, &statbuf) == 0)
538 goto found;
539
065db052 540 util_strscpyl(path, l, "/class/", sysname, NULL);
90d80c2e
KS
541 if (stat(path_full, &statbuf) == 0)
542 goto found;
543 goto out;
544 }
545
546 if (strcmp(subsystem, "module") == 0) {
065db052 547 util_strscpyl(path, l, "/module/", sysname, NULL);
90d80c2e
KS
548 if (stat(path_full, &statbuf) == 0)
549 goto found;
550 goto out;
551 }
552
553 if (strcmp(subsystem, "drivers") == 0) {
554 char subsys[UTIL_NAME_SIZE];
555 char *driver;
556
065db052 557 util_strscpy(subsys, sizeof(subsys), sysname);
90d80c2e
KS
558 driver = strchr(subsys, ':');
559 if (driver != NULL) {
560 driver[0] = '\0';
561 driver = &driver[1];
065db052
KS
562
563 util_strscpyl(path, l, "/subsystem/", subsys, "/drivers/", driver, NULL);
90d80c2e
KS
564 if (stat(path_full, &statbuf) == 0)
565 goto found;
566
065db052 567 util_strscpyl(path, l, "/bus/", subsys, "/drivers/", driver, NULL);
90d80c2e
KS
568 if (stat(path_full, &statbuf) == 0)
569 goto found;
570 }
571 goto out;
572 }
573
065db052 574 util_strscpyl(path, l, "/subsystem/", subsystem, "/devices/", sysname, NULL);
90d80c2e
KS
575 if (stat(path_full, &statbuf) == 0)
576 goto found;
577
065db052 578 util_strscpyl(path, l, "/bus/", subsystem, "/devices/", sysname, NULL);
90d80c2e
KS
579 if (stat(path_full, &statbuf) == 0)
580 goto found;
581
065db052 582 util_strscpyl(path, l, "/class/", subsystem, "/", sysname, NULL);
90d80c2e
KS
583 if (stat(path_full, &statbuf) == 0)
584 goto found;
585out:
586 return NULL;
587found:
588 return udev_device_new_from_syspath(udev, path_full);
589}
590
fc8d61c5
KS
591/**
592 * udev_device_new_from_environment
593 * @udev: udev library context
594 *
595 * Create new udev device, and fill in information from the
596 * current process environment. This only works reliable if
597 * the process is called from a udev rule. It is usually used
598 * for tools executed from IMPORT= rules.
599 *
600 * The initial refcount is 1, and needs to be decremented to
601 * release the resources of the udev device.
602 *
603 * Returns: a new udev device, or #NULL, if it does not exist
604 **/
605struct udev_device *udev_device_new_from_environment(struct udev *udev)
606{
607 int i;
608 struct udev_device *udev_device;
609
610 udev_device = udev_device_new(udev);
611 if (udev_device == NULL)
612 return NULL;
613 udev_device_set_info_loaded(udev_device);
614
615 for (i = 0; environ[i] != NULL; i++)
616 udev_device_add_property_from_string_parse(udev_device, environ[i]);
617
618 if (udev_device_add_property_from_string_parse_finish(udev_device) < 0) {
619 info(udev, "missing values, invalid device\n");
620 udev_device_unref(udev_device);
621 udev_device = NULL;
622 }
623
624 return udev_device;
625}
626
b2d9e4f2 627static struct udev_device *device_new_from_parent(struct udev_device *udev_device)
4ad3a37f
KS
628{
629 struct udev_device *udev_device_parent = NULL;
630 char path[UTIL_PATH_SIZE];
b95f8a76 631 const char *subdir;
4ad3a37f 632
065db052 633 util_strscpy(path, sizeof(path), udev_device->syspath);
b95f8a76 634 subdir = &path[strlen(udev_get_sys_path(udev_device->udev))+1];
3c189886 635 for (;;) {
b95f8a76
KS
636 char *pos;
637
638 pos = strrchr(subdir, '/');
639 if (pos == NULL || pos < &subdir[2])
4ad3a37f
KS
640 break;
641 pos[0] = '\0';
8753fadf 642 udev_device_parent = udev_device_new_from_syspath(udev_device->udev, path);
4ad3a37f 643 if (udev_device_parent != NULL)
0518da3b
KS
644 return udev_device_parent;
645 }
0518da3b 646 return NULL;
4ad3a37f
KS
647}
648
1e511322
KS
649/**
650 * udev_device_get_parent:
651 * @udev_device: the device to start searching from
652 *
653 * Find the next parent device, and fill in information from the sys
654 * device and the udev database entry.
655 *
656 * The returned the device is not referenced. It is attached to the
657 * child device, and will be cleaned up when the child device
658 * is cleaned up.
659 *
214a6c79 660 * It is not necessarily just the upper level directory, empty or not
1e511322
KS
661 * recognized sys directories are ignored.
662 *
663 * It can be called as many times as needed, without caring about
664 * references.
665 *
666 * Returns: a new udev device, or #NULL, if it no parent exist.
667 **/
b2d9e4f2
KS
668struct udev_device *udev_device_get_parent(struct udev_device *udev_device)
669{
b95f8a76
KS
670 if (udev_device == NULL)
671 return NULL;
31f4b036 672 if (!udev_device->parent_set) {
28460195 673 udev_device->parent_set = true;
31f4b036 674 udev_device->parent_device = device_new_from_parent(udev_device);
0518da3b 675 }
31f4b036 676 if (udev_device->parent_device != NULL)
86b57788 677 dbg(udev_device->udev, "returning existing parent %p\n", udev_device->parent_device);
b2d9e4f2
KS
678 return udev_device->parent_device;
679}
680
1e511322
KS
681/**
682 * udev_device_get_parent_with_subsystem_devtype:
683 * @udev_device: udev device to start searching from
214a6c79 684 * @subsystem: the subsystem of the device
1e511322
KS
685 * @devtype: the type (DEVTYPE) of the device
686 *
687 * Find the next parent device, with a matching subsystem and devtype
688 * value, and fill in information from the sys device and the udev
689 * database entry.
690 *
79ef2e97 691 * If devtype is #NULL, only subsystem is checked, and any devtype will
54d4f54e
MP
692 * match.
693 *
1e511322
KS
694 * The returned the device is not referenced. It is attached to the
695 * child device, and will be cleaned up when the child device
696 * is cleaned up.
697 *
698 * It can be called as many times as needed, without caring about
699 * references.
700 *
8d6bc73a 701 * Returns: a new udev device, or #NULL if no matching parent exists.
1e511322 702 **/
883012d4 703struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype)
bf8b2ae1
MH
704{
705 struct udev_device *parent;
706
883012d4
MH
707 if (subsystem == NULL)
708 return NULL;
709
bf8b2ae1
MH
710 parent = udev_device_get_parent(udev_device);
711 while (parent != NULL) {
883012d4 712 const char *parent_subsystem;
bf8b2ae1
MH
713 const char *parent_devtype;
714
883012d4
MH
715 parent_subsystem = udev_device_get_subsystem(parent);
716 if (parent_subsystem != NULL && strcmp(parent_subsystem, subsystem) == 0) {
717 if (devtype == NULL)
718 break;
719 parent_devtype = udev_device_get_devtype(parent);
720 if (parent_devtype != NULL && strcmp(parent_devtype, devtype) == 0)
721 break;
722 }
bf8b2ae1
MH
723 parent = udev_device_get_parent(parent);
724 }
725 return parent;
726}
727
eb1f0e66
KS
728/**
729 * udev_device_get_udev:
7d8787b3 730 * @udev_device: udev device
eb1f0e66
KS
731 *
732 * Retrieve the udev library context the device was created with.
733 *
734 * Returns: the udev library context
735 **/
736struct udev *udev_device_get_udev(struct udev_device *udev_device)
737{
ba6929f6
KS
738 if (udev_device == NULL)
739 return NULL;
eb1f0e66
KS
740 return udev_device->udev;
741}
742
743/**
744 * udev_device_ref:
745 * @udev_device: udev device
746 *
747 * Take a reference of a udev device.
748 *
749 * Returns: the passed udev device
750 **/
751struct udev_device *udev_device_ref(struct udev_device *udev_device)
752{
ba6929f6
KS
753 if (udev_device == NULL)
754 return NULL;
eb1f0e66
KS
755 udev_device->refcount++;
756 return udev_device;
757}
758
759/**
760 * udev_device_unref:
761 * @udev_device: udev device
762 *
763 * Drop a reference of a udev device. If the refcount reaches zero,
be7de409 764 * the resources of the device will be released.
eb1f0e66
KS
765 *
766 **/
767void udev_device_unref(struct udev_device *udev_device)
768{
ba6929f6
KS
769 if (udev_device == NULL)
770 return;
eb1f0e66
KS
771 udev_device->refcount--;
772 if (udev_device->refcount > 0)
773 return;
b2d9e4f2
KS
774 if (udev_device->parent_device != NULL)
775 udev_device_unref(udev_device->parent_device);
11d543c1 776 free(udev_device->syspath);
517814e7 777 free(udev_device->sysname);
99214844 778 free(udev_device->devnode);
ba6929f6 779 free(udev_device->subsystem);
bf8b2ae1 780 free(udev_device->devtype);
eb8837e1
KS
781 udev_list_cleanup_entries(udev_device->udev, &udev_device->devlinks_list);
782 udev_list_cleanup_entries(udev_device->udev, &udev_device->properties_list);
28460195
KS
783 udev_list_cleanup_entries(udev_device->udev, &udev_device->sysattr_list);
784 udev_list_cleanup_entries(udev_device->udev, &udev_device->tags_list);
1c7047ea
KS
785 free(udev_device->action);
786 free(udev_device->driver);
787 free(udev_device->devpath_old);
2ffc9cc1 788 free(udev_device->sysname_old);
cb14f454 789 free(udev_device->knodename);
4281da1f 790 free(udev_device->id_filename);
6493e655 791 free(udev_device->envp);
c2654402 792 free(udev_device->monitor_buf);
86b57788 793 dbg(udev_device->udev, "udev_device: %p released\n", udev_device);
eb1f0e66
KS
794 free(udev_device);
795}
796
797/**
798 * udev_device_get_devpath:
799 * @udev_device: udev device
800 *
11d543c1
KS
801 * Retrieve the kernel devpath value of the udev device. The path
802 * does not contain the sys mount point, and starts with a '/'.
eb1f0e66 803 *
11d543c1 804 * Returns: the devpath of the udev device
eb1f0e66
KS
805 **/
806const char *udev_device_get_devpath(struct udev_device *udev_device)
807{
ba6929f6
KS
808 if (udev_device == NULL)
809 return NULL;
810 return udev_device->devpath;
eb1f0e66
KS
811}
812
11d543c1
KS
813/**
814 * udev_device_get_syspath:
815 * @udev_device: udev device
816 *
817 * Retrieve the sys path of the udev device. The path is an
818 * absolute path and starts with the sys mount point.
819 *
820 * Returns: the sys path of the udev device
821 **/
822const char *udev_device_get_syspath(struct udev_device *udev_device)
823{
824 if (udev_device == NULL)
825 return NULL;
826 return udev_device->syspath;
827}
828
1e511322
KS
829/**
830 * udev_device_get_sysname:
831 * @udev_device: udev device
832 *
833 * Returns: the sys name of the device device
834 **/
4ad3a37f
KS
835const char *udev_device_get_sysname(struct udev_device *udev_device)
836{
837 if (udev_device == NULL)
838 return NULL;
839 return udev_device->sysname;
840}
841
1e511322
KS
842/**
843 * udev_device_get_sysnum:
844 * @udev_device: udev device
845 *
846 * Returns: the trailing number of of the device name
847 **/
517814e7
KS
848const char *udev_device_get_sysnum(struct udev_device *udev_device)
849{
850 if (udev_device == NULL)
851 return NULL;
852 return udev_device->sysnum;
853}
854
eb1f0e66 855/**
fb762bb9 856 * udev_device_get_devnode:
eb1f0e66
KS
857 * @udev_device: udev device
858 *
859 * Retrieve the device node file name belonging to the udev device.
ba6929f6 860 * The path is an absolute path, and starts with the device directory.
eb1f0e66
KS
861 *
862 * Returns: the device node file name of the udev device, or #NULL if no device node exists
863 **/
fb762bb9 864const char *udev_device_get_devnode(struct udev_device *udev_device)
eb1f0e66 865{
ba6929f6 866 if (udev_device == NULL)
eb1f0e66 867 return NULL;
cdb1d760
KS
868 if (!udev_device->info_loaded) {
869 udev_device_read_uevent_file(udev_device);
28460195 870 udev_device_read_db(udev_device);
cdb1d760
KS
871 }
872
873 /* we might get called before we handled an event and have a db, use the kernel-provided name */
874 if (udev_device->devnode == NULL && udev_device_get_knodename(udev_device) != NULL) {
24d10766
KS
875 char filename[UTIL_NAME_SIZE];
876
877 util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/",
878 udev_device_get_knodename(udev_device), NULL);
879 udev_device_set_devnode(udev_device, filename);
cdb1d760
KS
880 return udev_device->devnode;
881 }
882
99214844 883 return udev_device->devnode;
eb1f0e66
KS
884}
885
886/**
887 * udev_device_get_subsystem:
888 * @udev_device: udev device
889 *
890 * Retrieve the subsystem string of the udev device. The string does not
891 * contain any "/".
892 *
893 * Returns: the subsystem name of the udev device, or #NULL if it can not be determined
894 **/
895const char *udev_device_get_subsystem(struct udev_device *udev_device)
896{
17fcfb59 897 char subsystem[UTIL_NAME_SIZE];
ba6929f6
KS
898
899 if (udev_device == NULL)
900 return NULL;
5c5cad79 901 if (!udev_device->subsystem_set) {
28460195 902 udev_device->subsystem_set = true;
214a6c79 903 /* read "subsystem" link */
5c5cad79
KS
904 if (util_get_sys_subsystem(udev_device->udev, udev_device->syspath, subsystem, sizeof(subsystem)) > 0) {
905 udev_device_set_subsystem(udev_device, subsystem);
906 return udev_device->subsystem;
907 }
908 /* implicit names */
909 if (strncmp(udev_device->devpath, "/module/", 8) == 0) {
910 udev_device_set_subsystem(udev_device, "module");
911 return udev_device->subsystem;
912 }
913 if (strstr(udev_device->devpath, "/drivers/") != NULL) {
914 udev_device_set_subsystem(udev_device, "drivers");
915 return udev_device->subsystem;
916 }
917 if (strncmp(udev_device->devpath, "/subsystem/", 11) == 0 ||
918 strncmp(udev_device->devpath, "/class/", 7) == 0 ||
919 strncmp(udev_device->devpath, "/bus/", 5) == 0) {
920 udev_device_set_subsystem(udev_device, "subsystem");
921 return udev_device->subsystem;
922 }
0518da3b 923 }
5c5cad79 924 return udev_device->subsystem;
eb1f0e66
KS
925}
926
bf8b2ae1
MH
927/**
928 * udev_device_get_devtype:
929 * @udev_device: udev device
930 *
931 * Retrieve the devtype string of the udev device.
932 *
933 * Returns: the devtype name of the udev device, or #NULL if it can not be determined
934 **/
935const char *udev_device_get_devtype(struct udev_device *udev_device)
936{
937 if (udev_device == NULL)
938 return NULL;
939 if (!udev_device->devtype_set) {
28460195
KS
940 udev_device->devtype_set = true;
941 udev_device_read_uevent_file(udev_device);
bf8b2ae1
MH
942 }
943 return udev_device->devtype;
944}
945
eb1f0e66 946/**
0de33a61 947 * udev_device_get_devlinks_list_entry:
eb1f0e66 948 * @udev_device: udev device
eb1f0e66 949 *
bf7ad0ea
KS
950 * Retrieve the list of device links pointing to the device file of
951 * the udev device. The next list entry can be retrieved with
e345e267 952 * udev_list_entry_next(), which returns #NULL if no more entries exist.
bf7ad0ea 953 * The devlink path can be retrieved from the list entry by
e345e267 954 * udev_list_entry_get_name(). The path is an absolute path, and starts with
bf7ad0ea 955 * the device directory.
eb1f0e66 956 *
bf7ad0ea 957 * Returns: the first entry of the device node link list
eb1f0e66 958 **/
0de33a61 959struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device)
eb1f0e66 960{
99214844
KS
961 if (udev_device == NULL)
962 return NULL;
963 if (!udev_device->info_loaded)
28460195 964 udev_device_read_db(udev_device);
517814e7 965 return udev_list_get_entry(&udev_device->devlinks_list);
eb1f0e66
KS
966}
967
979ff016
KS
968void udev_device_cleanup_devlinks_list(struct udev_device *udev_device)
969{
28460195 970 udev_device->devlinks_uptodate = false;
eb8837e1 971 udev_list_cleanup_entries(udev_device->udev, &udev_device->devlinks_list);
979ff016
KS
972}
973
eb1f0e66 974/**
0de33a61 975 * udev_device_get_properties_list_entry:
eb1f0e66 976 * @udev_device: udev device
eb1f0e66 977 *
bf7ad0ea 978 * Retrieve the list of key/value device properties of the udev
e345e267 979 * device. The next list entry can be retrieved with udev_list_entry_next(),
bf7ad0ea
KS
980 * which returns #NULL if no more entries exist. The property name
981 * can be retrieved from the list entry by udev_list_get_name(),
982 * the property value by udev_list_get_value().
eb1f0e66 983 *
bf7ad0ea 984 * Returns: the first entry of the property list
eb1f0e66 985 **/
0de33a61 986struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device)
eb1f0e66 987{
99214844
KS
988 if (udev_device == NULL)
989 return NULL;
28460195
KS
990 if (!udev_device->info_loaded) {
991 udev_device_read_uevent_file(udev_device);
992 udev_device_read_db(udev_device);
993 }
bd85566c
KS
994 if (!udev_device->devlinks_uptodate) {
995 char symlinks[UTIL_PATH_SIZE];
996 struct udev_list_entry *list_entry;
997
28460195 998 udev_device->devlinks_uptodate = true;
bd85566c
KS
999 list_entry = udev_device_get_devlinks_list_entry(udev_device);
1000 if (list_entry != NULL) {
065db052
KS
1001 char *s;
1002 size_t l;
1003
1004 s = symlinks;
1005 l = util_strpcpyl(&s, sizeof(symlinks), udev_list_entry_get_name(list_entry), NULL);
1006 udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry))
1007 l = util_strpcpyl(&s, l, " ", udev_list_entry_get_name(list_entry), NULL);
bd85566c
KS
1008 udev_device_add_property(udev_device, "DEVLINKS", symlinks);
1009 }
1010 }
28460195
KS
1011 if (!udev_device->tags_uptodate) {
1012 udev_device->tags_uptodate = true;
1013 if (udev_device_get_tags_list_entry(udev_device) != NULL) {
1014 char tags[UTIL_PATH_SIZE];
1015 struct udev_list_entry *list_entry;
1016 char *s;
1017 size_t l;
1018
1019 s = tags;
1020 l = util_strpcpyl(&s, sizeof(tags), ":", NULL);
1021 udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(udev_device))
1022 l = util_strpcpyl(&s, l, udev_list_entry_get_name(list_entry), ":", NULL);
1023 udev_device_add_property(udev_device, "TAGS", tags);
1024 }
1025 }
8cd2e972 1026 return udev_list_get_entry(&udev_device->properties_list);
eb1f0e66 1027}
11d543c1 1028
1e511322
KS
1029/**
1030 * udev_device_get_driver:
1031 * @udev_device: udev device
1032 *
ce1d6d7f 1033 * Returns: the driver string, or #NULL if there is no driver attached.
1e511322 1034 **/
c4f5f942
KS
1035const char *udev_device_get_driver(struct udev_device *udev_device)
1036{
17fcfb59 1037 char driver[UTIL_NAME_SIZE];
95d90c4f 1038
c4f5f942
KS
1039 if (udev_device == NULL)
1040 return NULL;
5c5cad79 1041 if (!udev_device->driver_set) {
28460195 1042 udev_device->driver_set = true;
5c5cad79
KS
1043 if (util_get_sys_driver(udev_device->udev, udev_device->syspath, driver, sizeof(driver)) > 0)
1044 udev_device->driver = strdup(driver);
1045 }
c4f5f942
KS
1046 return udev_device->driver;
1047}
1048
1e511322
KS
1049/**
1050 * udev_device_get_devnum:
1051 * @udev_device: udev device
1052 *
1053 * Returns: the device major/minor number.
1054 **/
c4f5f942
KS
1055dev_t udev_device_get_devnum(struct udev_device *udev_device)
1056{
1057 if (udev_device == NULL)
1058 return makedev(0, 0);
99214844 1059 if (!udev_device->info_loaded)
28460195 1060 udev_device_read_uevent_file(udev_device);
c4f5f942
KS
1061 return udev_device->devnum;
1062}
1063
1e511322
KS
1064/**
1065 * udev_device_get_action:
1066 * @udev_device: udev device
1067 *
1068 * This is only valid if the device was received through a monitor. Devices read from
1069 * sys do not have an action string. Usual actions are: add, remove, change, online,
1070 * offline.
1071 *
1072 * Returns: the kernel action value, or #NULL if there is no action value available.
1073 **/
c4f5f942
KS
1074const char *udev_device_get_action(struct udev_device *udev_device)
1075{
1076 if (udev_device == NULL)
1077 return NULL;
1078 return udev_device->action;
1079}
1080
1e511322
KS
1081/**
1082 * udev_device_get_devnum:
1083 * @udev_device: udev device
1084 *
1085 * This is only valid if the device was received through a monitor. Devices read from
1086 * sys do not have a sequence number.
1087 *
1088 * Returns: the kernel event sequence number, or 0 if there is no sequence number available.
1089 **/
37372bbc
KS
1090unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device)
1091{
1092 if (udev_device == NULL)
1093 return 0;
1094 return udev_device->seqnum;
1095}
1096
1e511322
KS
1097/**
1098 * udev_device_get_sysattr_value:
1099 * @udev_device: udev device
1100 * @sysattr: attribute name
1101 *
456719b6 1102 * The retrieved value is cached in the device. Repeated calls will return the same
1e511322
KS
1103 * value and not open the attribute again.
1104 *
1105 * Returns: the content of a sys attribute file, or #NULL if there is no sys attribute value.
1106 **/
69239210 1107const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr)
93b0f384 1108{
0de33a61 1109 struct udev_list_entry *list_entry;
93b0f384 1110 char path[UTIL_PATH_SIZE];
affed87a 1111 char value[4096];
93b0f384
KS
1112 struct stat statbuf;
1113 int fd;
1114 ssize_t size;
1115 const char *val = NULL;
1116
517814e7
KS
1117 if (udev_device == NULL)
1118 return NULL;
69239210 1119 if (sysattr == NULL)
517814e7
KS
1120 return NULL;
1121
0518da3b 1122 /* look for possibly already cached result */
69239210
KS
1123 udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_device->sysattr_list)) {
1124 if (strcmp(udev_list_entry_get_name(list_entry), sysattr) == 0) {
86b57788
KS
1125 dbg(udev_device->udev, "got '%s' (%s) from cache\n",
1126 sysattr, udev_list_entry_get_value(list_entry));
0de33a61 1127 return udev_list_entry_get_value(list_entry);
0518da3b
KS
1128 }
1129 }
1130
065db052 1131 util_strscpyl(path, sizeof(path), udev_device_get_syspath(udev_device), "/", sysattr, NULL);
93b0f384 1132 if (lstat(path, &statbuf) != 0) {
86b57788 1133 dbg(udev_device->udev, "no attribute '%s', keep negative entry\n", path);
69239210 1134 udev_list_entry_add(udev_device->udev, &udev_device->sysattr_list, sysattr, NULL, 0, 0);
93b0f384
KS
1135 goto out;
1136 }
1137
1138 if (S_ISLNK(statbuf.st_mode)) {
93b0f384
KS
1139 char target[UTIL_NAME_SIZE];
1140 int len;
1141 char *pos;
1142
096e59ed
KS
1143 /* some core links return the last element of the target path */
1144 if (strcmp(sysattr, "driver") != 0 &&
1145 strcmp(sysattr, "subsystem") != 0 &&
1146 strcmp(sysattr, "module") != 0)
1147 goto out;
1148
93b0f384 1149 len = readlink(path, target, sizeof(target));
60067cc7
KS
1150 if (len <= 0 || len == sizeof(target))
1151 goto out;
1152 target[len] = '\0';
1153
1154 pos = strrchr(target, '/');
1155 if (pos != NULL) {
1156 pos = &pos[1];
1157 dbg(udev_device->udev, "cache '%s' with link value '%s'\n", sysattr, pos);
1158 list_entry = udev_list_entry_add(udev_device->udev, &udev_device->sysattr_list, sysattr, pos, 0, 0);
1159 val = udev_list_entry_get_value(list_entry);
93b0f384 1160 }
60067cc7 1161
93b0f384
KS
1162 goto out;
1163 }
1164
1165 /* skip directories */
1166 if (S_ISDIR(statbuf.st_mode))
1167 goto out;
1168
1169 /* skip non-readable files */
1170 if ((statbuf.st_mode & S_IRUSR) == 0)
1171 goto out;
1172
1173 /* read attribute value */
0c5c4804 1174 fd = open(path, O_RDONLY|O_CLOEXEC);
93b0f384 1175 if (fd < 0) {
86b57788 1176 dbg(udev_device->udev, "attribute '%s' can not be opened\n", path);
93b0f384
KS
1177 goto out;
1178 }
1179 size = read(fd, value, sizeof(value));
1180 close(fd);
1181 if (size < 0)
1182 goto out;
1183 if (size == sizeof(value))
1184 goto out;
1185
0518da3b 1186 /* got a valid value, store it in cache and return it */
93b0f384
KS
1187 value[size] = '\0';
1188 util_remove_trailing_chars(value, '\n');
86b57788 1189 dbg(udev_device->udev, "'%s' has attribute value '%s'\n", path, value);
69239210 1190 list_entry = udev_list_entry_add(udev_device->udev, &udev_device->sysattr_list, sysattr, value, 0, 0);
0de33a61 1191 val = udev_list_entry_get_value(list_entry);
93b0f384
KS
1192out:
1193 return val;
1194}
517814e7 1195
8cd2e972 1196int udev_device_set_syspath(struct udev_device *udev_device, const char *syspath)
11d543c1 1197{
8753fadf 1198 const char *pos;
517814e7 1199 size_t len;
8753fadf 1200
8cd2e972 1201 free(udev_device->syspath);
8753fadf
KS
1202 udev_device->syspath = strdup(syspath);
1203 if (udev_device->syspath == NULL)
11d543c1
KS
1204 return -ENOMEM;
1205 udev_device->devpath = &udev_device->syspath[strlen(udev_get_sys_path(udev_device->udev))];
9a997ecf 1206 udev_device_add_property(udev_device, "DEVPATH", udev_device->devpath);
517814e7 1207
8753fadf
KS
1208 pos = strrchr(udev_device->syspath, '/');
1209 if (pos == NULL)
1210 return -EINVAL;
517814e7
KS
1211 udev_device->sysname = strdup(&pos[1]);
1212 if (udev_device->sysname == NULL)
1213 return -ENOMEM;
1214
1215 /* some devices have '!' in their name, change that to '/' */
1216 len = 0;
1217 while (udev_device->sysname[len] != '\0') {
1218 if (udev_device->sysname[len] == '!')
1219 udev_device->sysname[len] = '/';
1220 len++;
1221 }
1222
1223 /* trailing number */
babcf3cb 1224 while (len > 0 && isdigit(udev_device->sysname[--len]))
517814e7 1225 udev_device->sysnum = &udev_device->sysname[len];
babcf3cb
AJ
1226
1227 /* sysname is completely numeric */
1228 if (len == 0)
1229 udev_device->sysnum = NULL;
1230
11d543c1
KS
1231 return 0;
1232}
1233
8cd2e972 1234int udev_device_set_subsystem(struct udev_device *udev_device, const char *subsystem)
11d543c1 1235{
979ff016 1236 free(udev_device->subsystem);
11d543c1
KS
1237 udev_device->subsystem = strdup(subsystem);
1238 if (udev_device->subsystem == NULL)
9a997ecf 1239 return -ENOMEM;
28460195 1240 udev_device->subsystem_set = true;
9a997ecf 1241 udev_device_add_property(udev_device, "SUBSYSTEM", udev_device->subsystem);
11d543c1
KS
1242 return 0;
1243}
1244
bf8b2ae1
MH
1245int udev_device_set_devtype(struct udev_device *udev_device, const char *devtype)
1246{
1247 free(udev_device->devtype);
1248 udev_device->devtype = strdup(devtype);
1249 if (udev_device->devtype == NULL)
1250 return -ENOMEM;
28460195 1251 udev_device->devtype_set = true;
bf8b2ae1
MH
1252 udev_device_add_property(udev_device, "DEVTYPE", udev_device->devtype);
1253 return 0;
1254}
1255
8cd2e972 1256int udev_device_set_devnode(struct udev_device *udev_device, const char *devnode)
11d543c1 1257{
517814e7 1258 free(udev_device->devnode);
99214844
KS
1259 udev_device->devnode = strdup(devnode);
1260 if (udev_device->devnode == NULL)
11d543c1 1261 return -ENOMEM;
979ff016 1262 udev_device_add_property(udev_device, "DEVNAME", udev_device->devnode);
11d543c1
KS
1263 return 0;
1264}
1265
6c29f2b9 1266int udev_device_add_devlink(struct udev_device *udev_device, const char *devlink, int unique)
11d543c1 1267{
6c29f2b9
KS
1268 struct udev_list_entry *list_entry;
1269
28460195 1270 udev_device->devlinks_uptodate = false;
6c29f2b9
KS
1271 list_entry = udev_list_entry_add(udev_device->udev, &udev_device->devlinks_list, devlink, NULL, 1, 0);
1272 if (list_entry == NULL)
11d543c1 1273 return -ENOMEM;
6c29f2b9 1274 if (unique)
fbb31cd6 1275 udev_list_entry_set_flags(list_entry, 1);
11d543c1
KS
1276 return 0;
1277}
1278
4281da1f
KS
1279const char *udev_device_get_id_filename(struct udev_device *udev_device)
1280{
1281 if (udev_device->id_filename == NULL) {
1282 if (udev_device_get_subsystem(udev_device) == NULL)
1283 return NULL;
1284
1285 if (major(udev_device_get_devnum(udev_device)) > 0) {
1286 /* use dev_t -- b259:131072, c254:0 */
1287 if (asprintf(&udev_device->id_filename, "%c%u:%u",
1288 strcmp(udev_device_get_subsystem(udev_device), "block") == 0 ? 'b' : 'c',
1289 major(udev_device_get_devnum(udev_device)),
1290 minor(udev_device_get_devnum(udev_device))) < 0)
1291 udev_device->id_filename = NULL;
ff0e1f4e 1292 } else if (udev_device_get_ifindex(udev_device) > 0) {
4281da1f
KS
1293 /* use netdev ifindex -- n3 */
1294 if (asprintf(&udev_device->id_filename, "n%u", udev_device_get_ifindex(udev_device)) < 0)
1295 udev_device->id_filename = NULL;
1296 } else {
1297 /*
1298 * use $subsys:$syname -- pci:0000:00:1f.2
1299 * sysname() has '!' translated, get it from devpath
1300 */
1301 const char *sysname;
1302 sysname = strrchr(udev_device->devpath, '/');
1303 if (sysname == NULL)
1304 return NULL;
1305 sysname = &sysname[1];
1306 if (asprintf(&udev_device->id_filename, "+%s:%s", udev_device_get_subsystem(udev_device), sysname) < 0)
1307 udev_device->id_filename = NULL;
1308 }
1309 }
1310 return udev_device->id_filename;
1311}
1312
48a0170b
KS
1313/**
1314 * udev_device_get_is_initialized:
1315 * @udev_device: udev device
1316 *
1317 * Check if udev has already handled the device and has set up
1318 * device node permissions and context, or has renamed a network
1319 * device.
1320 *
1321 * For now, this is only implemented for devices with a device node
1322 * or network interfaces. All other devices return 1 here.
1323 *
1324 * Returns: 1 if the device is set up. 0 otherwise.
1325 **/
1326int udev_device_get_is_initialized(struct udev_device *udev_device)
1327{
1328 if (!udev_device->info_loaded)
1329 udev_device_read_db(udev_device);
1330 return udev_device->is_initialized;
1331}
1332
1333void udev_device_set_is_initialized(struct udev_device *udev_device)
1334{
1335 udev_device->is_initialized = true;
1336}
1337
28460195
KS
1338int udev_device_add_tag(struct udev_device *udev_device, const char *tag)
1339{
1340 if (strchr(tag, ':') != NULL || strchr(tag, ' ') != NULL)
1341 return -EINVAL;
1342 udev_device->tags_uptodate = false;
1343 if (udev_list_entry_add(udev_device->udev, &udev_device->tags_list, tag, NULL, 1, 0) != NULL)
1344 return 0;
1345 return -ENOMEM;
1346}
1347
1348void udev_device_cleanup_tags_list(struct udev_device *udev_device)
1349{
1350 udev_device->tags_uptodate = false;
1351 udev_list_cleanup_entries(udev_device->udev, &udev_device->tags_list);
1352}
1353
f712894d
KS
1354/**
1355 * udev_device_get_tags_list_entry:
1356 * @udev_device: udev device
1357 *
1358 * Retrieve the list of tags attached to the udev device. The next
1359 * list entry can be retrieved with udev_list_entry_next(),
1360 * which returns #NULL if no more entries exist. The tag string
1361 * can be retrieved from the list entry by udev_list_get_name().
1362 *
1363 * Returns: the first entry of the tag list
1364 **/
28460195
KS
1365struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device)
1366{
65f099c7
KS
1367 if (udev_device == NULL)
1368 return NULL;
28460195
KS
1369 return udev_list_get_entry(&udev_device->tags_list);
1370}
1371
1372int udev_device_has_tag(struct udev_device *udev_device, const char *tag)
1373{
1374 struct udev_list_entry *list_entry;
1375
1376 if (!udev_device->info_loaded)
1377 udev_device_read_db(udev_device);
1378 list_entry = udev_device_get_tags_list_entry(udev_device);
1379 list_entry = udev_list_entry_get_by_name(list_entry, tag);
1380 if (list_entry != NULL)
1381 return 1;
1382 return 0;
1383}
1384
6493e655
KS
1385#define ENVP_SIZE 128
1386#define MONITOR_BUF_SIZE 4096
1387static int update_envp_monitor_buf(struct udev_device *udev_device)
979ff016 1388{
6493e655 1389 struct udev_list_entry *list_entry;
065db052
KS
1390 char *s;
1391 size_t l;
6493e655 1392 unsigned int i;
979ff016 1393
6493e655
KS
1394 /* monitor buffer of property strings */
1395 free(udev_device->monitor_buf);
1396 udev_device->monitor_buf_len = 0;
1397 udev_device->monitor_buf = malloc(MONITOR_BUF_SIZE);
1398 if (udev_device->monitor_buf == NULL)
1399 return -ENOMEM;
be18918f 1400
6493e655 1401 /* envp array, strings will point into monitor buffer */
427e20b2
KS
1402 if (udev_device->envp == NULL)
1403 udev_device->envp = malloc(sizeof(char *) * ENVP_SIZE);
6493e655
KS
1404 if (udev_device->envp == NULL)
1405 return -ENOMEM;
979ff016 1406
6493e655 1407 i = 0;
065db052
KS
1408 s = udev_device->monitor_buf;
1409 l = MONITOR_BUF_SIZE;
6493e655 1410 udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(udev_device)) {
b25a9454
KS
1411 const char *key;
1412
1413 key = udev_list_entry_get_name(list_entry);
1414 /* skip private variables */
1415 if (key[0] == '.')
1416 continue;
1417
6493e655 1418 /* add string to envp array */
065db052 1419 udev_device->envp[i++] = s;
6493e655
KS
1420 if (i+1 >= ENVP_SIZE)
1421 return -EINVAL;
c2654402 1422
6493e655 1423 /* add property string to monitor buffer */
b25a9454 1424 l = util_strpcpyl(&s, l, key, "=", udev_list_entry_get_value(list_entry), NULL);
065db052 1425 if (l == 0)
c2654402 1426 return -EINVAL;
ecd42de2 1427 /* advance past the trailing '\0' that util_strpcpyl() guarantees */
065db052 1428 s++;
ecd42de2 1429 l--;
c2654402 1430 }
6493e655 1431 udev_device->envp[i] = NULL;
065db052 1432 udev_device->monitor_buf_len = s - udev_device->monitor_buf;
28460195 1433 udev_device->envp_uptodate = true;
065db052
KS
1434 dbg(udev_device->udev, "filled envp/monitor buffer, %u properties, %zu bytes\n",
1435 i, udev_device->monitor_buf_len);
6493e655
KS
1436 return 0;
1437}
1438
1439char **udev_device_get_properties_envp(struct udev_device *udev_device)
1440{
1441 if (!udev_device->envp_uptodate)
c6243a41 1442 if (update_envp_monitor_buf(udev_device) != 0)
6493e655
KS
1443 return NULL;
1444 return udev_device->envp;
1445}
1446
1447ssize_t udev_device_get_properties_monitor_buf(struct udev_device *udev_device, const char **buf)
1448{
1449 if (!udev_device->envp_uptodate)
c6243a41 1450 if (update_envp_monitor_buf(udev_device) != 0)
6493e655 1451 return -EINVAL;
c2654402 1452 *buf = udev_device->monitor_buf;
c2654402
KS
1453 return udev_device->monitor_buf_len;
1454}
1455
8cd2e972 1456int udev_device_set_action(struct udev_device *udev_device, const char *action)
c4f5f942 1457{
517814e7 1458 free(udev_device->action);
c4f5f942
KS
1459 udev_device->action = strdup(action);
1460 if (udev_device->action == NULL)
1461 return -ENOMEM;
31f4b036 1462 udev_device_add_property(udev_device, "ACTION", udev_device->action);
c4f5f942
KS
1463 return 0;
1464}
1465
8cd2e972 1466int udev_device_set_driver(struct udev_device *udev_device, const char *driver)
c4f5f942 1467{
979ff016 1468 free(udev_device->driver);
c4f5f942
KS
1469 udev_device->driver = strdup(driver);
1470 if (udev_device->driver == NULL)
1471 return -ENOMEM;
28460195 1472 udev_device->driver_set = true;
31f4b036 1473 udev_device_add_property(udev_device, "DRIVER", udev_device->driver);
c4f5f942
KS
1474 return 0;
1475}
1476
8cd2e972 1477const char *udev_device_get_devpath_old(struct udev_device *udev_device)
c4f5f942 1478{
c4f5f942
KS
1479 return udev_device->devpath_old;
1480}
1481
8cd2e972 1482int udev_device_set_devpath_old(struct udev_device *udev_device, const char *devpath_old)
c4f5f942 1483{
2ffc9cc1
KS
1484 const char *pos;
1485 size_t len;
1486
a71369b0 1487 free(udev_device->devpath_old);
c4f5f942
KS
1488 udev_device->devpath_old = strdup(devpath_old);
1489 if (udev_device->devpath_old == NULL)
1490 return -ENOMEM;
31f4b036 1491 udev_device_add_property(udev_device, "DEVPATH_OLD", udev_device->devpath_old);
2ffc9cc1
KS
1492
1493 pos = strrchr(udev_device->devpath_old, '/');
1494 if (pos == NULL)
1495 return -EINVAL;
1496 udev_device->sysname_old = strdup(&pos[1]);
1497 if (udev_device->sysname_old == NULL)
1498 return -ENOMEM;
1499
1500 /* some devices have '!' in their name, change that to '/' */
1501 len = 0;
1502 while (udev_device->sysname_old[len] != '\0') {
1503 if (udev_device->sysname_old[len] == '!')
1504 udev_device->sysname_old[len] = '/';
1505 len++;
1506 }
c4f5f942
KS
1507 return 0;
1508}
1509
2ffc9cc1
KS
1510const char *udev_device_get_sysname_old(struct udev_device *udev_device)
1511{
1512 if (udev_device == NULL)
1513 return NULL;
1514 return udev_device->sysname_old;
1515}
1516
cb14f454
KS
1517const char *udev_device_get_knodename(struct udev_device *udev_device)
1518{
1519 return udev_device->knodename;
1520}
1521
1522int udev_device_set_knodename(struct udev_device *udev_device, const char *knodename)
1523{
a71369b0 1524 free(udev_device->knodename);
cb14f454
KS
1525 udev_device->knodename = strdup(knodename);
1526 if (udev_device->knodename == NULL)
1527 return -ENOMEM;
24d10766
KS
1528 /* do not overwrite the udev property with the kernel property */
1529 if (udev_device->devnode == NULL)
1530 udev_device_add_property(udev_device, "DEVNAME", udev_device->knodename);
cb14f454
KS
1531 return 0;
1532}
1533
8cd2e972 1534int udev_device_get_timeout(struct udev_device *udev_device)
c4f5f942 1535{
c4f5f942
KS
1536 return udev_device->timeout;
1537}
1538
8cd2e972 1539int udev_device_set_timeout(struct udev_device *udev_device, int timeout)
c4f5f942
KS
1540{
1541 udev_device->timeout = timeout;
1542 return 0;
1543}
8cd2e972 1544int udev_device_get_event_timeout(struct udev_device *udev_device)
99214844
KS
1545{
1546 if (!udev_device->info_loaded)
28460195 1547 udev_device_read_db(udev_device);
99214844
KS
1548 return udev_device->event_timeout;
1549}
1550
8cd2e972 1551int udev_device_set_event_timeout(struct udev_device *udev_device, int event_timeout)
99214844 1552{
4281da1f
KS
1553 char num[32];
1554
99214844 1555 udev_device->event_timeout = event_timeout;
4281da1f
KS
1556 snprintf(num, sizeof(num), "%u", event_timeout);
1557 udev_device_add_property(udev_device, "TIMEOUT", num);
99214844
KS
1558 return 0;
1559}
c4f5f942 1560
8cd2e972 1561int udev_device_set_seqnum(struct udev_device *udev_device, unsigned long long int seqnum)
37372bbc 1562{
31f4b036
KS
1563 char num[32];
1564
37372bbc 1565 udev_device->seqnum = seqnum;
31f4b036
KS
1566 snprintf(num, sizeof(num), "%llu", seqnum);
1567 udev_device_add_property(udev_device, "SEQNUM", num);
37372bbc
KS
1568 return 0;
1569}
1570
8cd2e972 1571int udev_device_set_devnum(struct udev_device *udev_device, dev_t devnum)
c4f5f942 1572{
31f4b036
KS
1573 char num[32];
1574
c4f5f942 1575 udev_device->devnum = devnum;
31f4b036
KS
1576
1577 snprintf(num, sizeof(num), "%u", major(devnum));
1578 udev_device_add_property(udev_device, "MAJOR", num);
1579 snprintf(num, sizeof(num), "%u", minor(devnum));
1580 udev_device_add_property(udev_device, "MINOR", num);
c4f5f942
KS
1581 return 0;
1582}
6bd1c78a 1583
8cd2e972 1584int udev_device_get_devlink_priority(struct udev_device *udev_device)
6bd1c78a 1585{
99214844 1586 if (!udev_device->info_loaded)
28460195 1587 udev_device_read_db(udev_device);
e88a82b5 1588 return udev_device->devlink_priority;
6bd1c78a
KS
1589}
1590
8cd2e972 1591int udev_device_set_devlink_priority(struct udev_device *udev_device, int prio)
6bd1c78a 1592{
e88a82b5
KS
1593 udev_device->devlink_priority = prio;
1594 return 0;
6bd1c78a
KS
1595}
1596
d7ce7539
SJR
1597int udev_device_get_watch_handle(struct udev_device *udev_device)
1598{
1599 if (!udev_device->info_loaded)
28460195 1600 udev_device_read_db(udev_device);
d7ce7539
SJR
1601 return udev_device->watch_handle;
1602}
1603
1604int udev_device_set_watch_handle(struct udev_device *udev_device, int handle)
1605{
1606 udev_device->watch_handle = handle;
1607 return 0;
1608}
fc416258
KS
1609
1610int udev_device_get_ifindex(struct udev_device *udev_device)
1611{
ff0e1f4e
KS
1612 if (!udev_device->info_loaded)
1613 udev_device_read_uevent_file(udev_device);
fc416258
KS
1614 return udev_device->ifindex;
1615}
1616
1617int udev_device_set_ifindex(struct udev_device *udev_device, int ifindex)
1618{
4281da1f
KS
1619 char num[32];
1620
fc416258 1621 udev_device->ifindex = ifindex;
4281da1f
KS
1622 snprintf(num, sizeof(num), "%u", ifindex);
1623 udev_device_add_property(udev_device, "IFINDEX", num);
fc416258
KS
1624 return 0;
1625}