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