]> git.ipfire.org Git - thirdparty/systemd.git/blame - libudev/libudev-device.c
check ifindex > 0 instead of subsystem == "net"
[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
cad40a5f
KS
478struct udev_device *udev_device_new_from_id_filename(struct udev *udev, char *id)
479{
480 char type;
481 int maj, min;
482 char subsys[UTIL_PATH_SIZE];
483 char *sysname;
484
485 switch(id[0]) {
486 case 'b':
487 case 'c':
488 if (sscanf(id, "%c%i:%i", &type, &maj, &min) != 3)
489 return NULL;
490 return udev_device_new_from_devnum(udev, type, makedev(maj, min));
491 case '+':
492 util_strscpy(subsys, sizeof(subsys), &id[1]);
493 sysname = strchr(subsys, ':');
494 if (sysname == NULL)
495 return NULL;
496 sysname[0] = '\0';
497 sysname = &sysname[1];
498 return udev_device_new_from_subsystem_sysname(udev, subsys, sysname);
499 default:
500 return NULL;
501 }
502}
503
1e511322
KS
504/**
505 * udev_device_new_from_subsystem_sysname:
506 * @udev: udev library context
214a6c79 507 * @subsystem: the subsystem of the device
1e511322
KS
508 * @sysname: the name of the device
509 *
dbba7e40
KS
510 * Create new udev device, and fill in information from the sys device
511 * and the udev database entry. The device is looked up by the subsystem
512 * and name string of the device, like "mem" / "zero", or "block" / "sda".
1e511322
KS
513 *
514 * The initial refcount is 1, and needs to be decremented to
515 * release the resources of the udev device.
516 *
517 * Returns: a new udev device, or #NULL, if it does not exist
518 **/
90d80c2e
KS
519struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname)
520{
90d80c2e
KS
521 char path_full[UTIL_PATH_SIZE];
522 char *path;
065db052 523 size_t l;
90d80c2e
KS
524 struct stat statbuf;
525
065db052
KS
526 path = path_full;
527 l = util_strpcpyl(&path, sizeof(path_full), udev_get_sys_path(udev), NULL);
90d80c2e
KS
528
529 if (strcmp(subsystem, "subsystem") == 0) {
065db052 530 util_strscpyl(path, l, "/subsystem/", sysname, NULL);
90d80c2e
KS
531 if (stat(path_full, &statbuf) == 0)
532 goto found;
533
065db052 534 util_strscpyl(path, l, "/bus/", sysname, NULL);
90d80c2e
KS
535 if (stat(path_full, &statbuf) == 0)
536 goto found;
537
065db052 538 util_strscpyl(path, l, "/class/", sysname, NULL);
90d80c2e
KS
539 if (stat(path_full, &statbuf) == 0)
540 goto found;
541 goto out;
542 }
543
544 if (strcmp(subsystem, "module") == 0) {
065db052 545 util_strscpyl(path, l, "/module/", sysname, NULL);
90d80c2e
KS
546 if (stat(path_full, &statbuf) == 0)
547 goto found;
548 goto out;
549 }
550
551 if (strcmp(subsystem, "drivers") == 0) {
552 char subsys[UTIL_NAME_SIZE];
553 char *driver;
554
065db052 555 util_strscpy(subsys, sizeof(subsys), sysname);
90d80c2e
KS
556 driver = strchr(subsys, ':');
557 if (driver != NULL) {
558 driver[0] = '\0';
559 driver = &driver[1];
065db052
KS
560
561 util_strscpyl(path, l, "/subsystem/", subsys, "/drivers/", driver, NULL);
90d80c2e
KS
562 if (stat(path_full, &statbuf) == 0)
563 goto found;
564
065db052 565 util_strscpyl(path, l, "/bus/", subsys, "/drivers/", driver, NULL);
90d80c2e
KS
566 if (stat(path_full, &statbuf) == 0)
567 goto found;
568 }
569 goto out;
570 }
571
065db052 572 util_strscpyl(path, l, "/subsystem/", subsystem, "/devices/", sysname, NULL);
90d80c2e
KS
573 if (stat(path_full, &statbuf) == 0)
574 goto found;
575
065db052 576 util_strscpyl(path, l, "/bus/", subsystem, "/devices/", sysname, NULL);
90d80c2e
KS
577 if (stat(path_full, &statbuf) == 0)
578 goto found;
579
065db052 580 util_strscpyl(path, l, "/class/", subsystem, "/", sysname, NULL);
90d80c2e
KS
581 if (stat(path_full, &statbuf) == 0)
582 goto found;
583out:
584 return NULL;
585found:
586 return udev_device_new_from_syspath(udev, path_full);
587}
588
fc8d61c5
KS
589/**
590 * udev_device_new_from_environment
591 * @udev: udev library context
592 *
593 * Create new udev device, and fill in information from the
594 * current process environment. This only works reliable if
595 * the process is called from a udev rule. It is usually used
596 * for tools executed from IMPORT= rules.
597 *
598 * The initial refcount is 1, and needs to be decremented to
599 * release the resources of the udev device.
600 *
601 * Returns: a new udev device, or #NULL, if it does not exist
602 **/
603struct udev_device *udev_device_new_from_environment(struct udev *udev)
604{
605 int i;
606 struct udev_device *udev_device;
607
608 udev_device = udev_device_new(udev);
609 if (udev_device == NULL)
610 return NULL;
611 udev_device_set_info_loaded(udev_device);
612
613 for (i = 0; environ[i] != NULL; i++)
614 udev_device_add_property_from_string_parse(udev_device, environ[i]);
615
616 if (udev_device_add_property_from_string_parse_finish(udev_device) < 0) {
617 info(udev, "missing values, invalid device\n");
618 udev_device_unref(udev_device);
619 udev_device = NULL;
620 }
621
622 return udev_device;
623}
624
b2d9e4f2 625static struct udev_device *device_new_from_parent(struct udev_device *udev_device)
4ad3a37f
KS
626{
627 struct udev_device *udev_device_parent = NULL;
628 char path[UTIL_PATH_SIZE];
b95f8a76 629 const char *subdir;
4ad3a37f 630
065db052 631 util_strscpy(path, sizeof(path), udev_device->syspath);
b95f8a76 632 subdir = &path[strlen(udev_get_sys_path(udev_device->udev))+1];
3c189886 633 for (;;) {
b95f8a76
KS
634 char *pos;
635
636 pos = strrchr(subdir, '/');
637 if (pos == NULL || pos < &subdir[2])
4ad3a37f
KS
638 break;
639 pos[0] = '\0';
8753fadf 640 udev_device_parent = udev_device_new_from_syspath(udev_device->udev, path);
4ad3a37f 641 if (udev_device_parent != NULL)
0518da3b
KS
642 return udev_device_parent;
643 }
0518da3b 644 return NULL;
4ad3a37f
KS
645}
646
1e511322
KS
647/**
648 * udev_device_get_parent:
649 * @udev_device: the device to start searching from
650 *
651 * Find the next parent device, and fill in information from the sys
652 * device and the udev database entry.
653 *
654 * The returned the device is not referenced. It is attached to the
655 * child device, and will be cleaned up when the child device
656 * is cleaned up.
657 *
214a6c79 658 * It is not necessarily just the upper level directory, empty or not
1e511322
KS
659 * recognized sys directories are ignored.
660 *
661 * It can be called as many times as needed, without caring about
662 * references.
663 *
664 * Returns: a new udev device, or #NULL, if it no parent exist.
665 **/
b2d9e4f2
KS
666struct udev_device *udev_device_get_parent(struct udev_device *udev_device)
667{
b95f8a76
KS
668 if (udev_device == NULL)
669 return NULL;
31f4b036 670 if (!udev_device->parent_set) {
28460195 671 udev_device->parent_set = true;
31f4b036 672 udev_device->parent_device = device_new_from_parent(udev_device);
0518da3b 673 }
31f4b036 674 if (udev_device->parent_device != NULL)
86b57788 675 dbg(udev_device->udev, "returning existing parent %p\n", udev_device->parent_device);
b2d9e4f2
KS
676 return udev_device->parent_device;
677}
678
1e511322
KS
679/**
680 * udev_device_get_parent_with_subsystem_devtype:
681 * @udev_device: udev device to start searching from
214a6c79 682 * @subsystem: the subsystem of the device
1e511322
KS
683 * @devtype: the type (DEVTYPE) of the device
684 *
685 * Find the next parent device, with a matching subsystem and devtype
686 * value, and fill in information from the sys device and the udev
687 * database entry.
688 *
79ef2e97 689 * If devtype is #NULL, only subsystem is checked, and any devtype will
54d4f54e
MP
690 * match.
691 *
1e511322
KS
692 * The returned the device is not referenced. It is attached to the
693 * child device, and will be cleaned up when the child device
694 * is cleaned up.
695 *
696 * It can be called as many times as needed, without caring about
697 * references.
698 *
8d6bc73a 699 * Returns: a new udev device, or #NULL if no matching parent exists.
1e511322 700 **/
883012d4 701struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype)
bf8b2ae1
MH
702{
703 struct udev_device *parent;
704
883012d4
MH
705 if (subsystem == NULL)
706 return NULL;
707
bf8b2ae1
MH
708 parent = udev_device_get_parent(udev_device);
709 while (parent != NULL) {
883012d4 710 const char *parent_subsystem;
bf8b2ae1
MH
711 const char *parent_devtype;
712
883012d4
MH
713 parent_subsystem = udev_device_get_subsystem(parent);
714 if (parent_subsystem != NULL && strcmp(parent_subsystem, subsystem) == 0) {
715 if (devtype == NULL)
716 break;
717 parent_devtype = udev_device_get_devtype(parent);
718 if (parent_devtype != NULL && strcmp(parent_devtype, devtype) == 0)
719 break;
720 }
bf8b2ae1
MH
721 parent = udev_device_get_parent(parent);
722 }
723 return parent;
724}
725
eb1f0e66
KS
726/**
727 * udev_device_get_udev:
7d8787b3 728 * @udev_device: udev device
eb1f0e66
KS
729 *
730 * Retrieve the udev library context the device was created with.
731 *
732 * Returns: the udev library context
733 **/
734struct udev *udev_device_get_udev(struct udev_device *udev_device)
735{
ba6929f6
KS
736 if (udev_device == NULL)
737 return NULL;
eb1f0e66
KS
738 return udev_device->udev;
739}
740
741/**
742 * udev_device_ref:
743 * @udev_device: udev device
744 *
745 * Take a reference of a udev device.
746 *
747 * Returns: the passed udev device
748 **/
749struct udev_device *udev_device_ref(struct udev_device *udev_device)
750{
ba6929f6
KS
751 if (udev_device == NULL)
752 return NULL;
eb1f0e66
KS
753 udev_device->refcount++;
754 return udev_device;
755}
756
757/**
758 * udev_device_unref:
759 * @udev_device: udev device
760 *
761 * Drop a reference of a udev device. If the refcount reaches zero,
be7de409 762 * the resources of the device will be released.
eb1f0e66
KS
763 *
764 **/
765void udev_device_unref(struct udev_device *udev_device)
766{
ba6929f6
KS
767 if (udev_device == NULL)
768 return;
eb1f0e66
KS
769 udev_device->refcount--;
770 if (udev_device->refcount > 0)
771 return;
b2d9e4f2
KS
772 if (udev_device->parent_device != NULL)
773 udev_device_unref(udev_device->parent_device);
11d543c1 774 free(udev_device->syspath);
517814e7 775 free(udev_device->sysname);
99214844 776 free(udev_device->devnode);
ba6929f6 777 free(udev_device->subsystem);
bf8b2ae1 778 free(udev_device->devtype);
eb8837e1
KS
779 udev_list_cleanup_entries(udev_device->udev, &udev_device->devlinks_list);
780 udev_list_cleanup_entries(udev_device->udev, &udev_device->properties_list);
28460195
KS
781 udev_list_cleanup_entries(udev_device->udev, &udev_device->sysattr_list);
782 udev_list_cleanup_entries(udev_device->udev, &udev_device->tags_list);
1c7047ea
KS
783 free(udev_device->action);
784 free(udev_device->driver);
785 free(udev_device->devpath_old);
2ffc9cc1 786 free(udev_device->sysname_old);
cb14f454 787 free(udev_device->knodename);
4281da1f 788 free(udev_device->id_filename);
6493e655 789 free(udev_device->envp);
c2654402 790 free(udev_device->monitor_buf);
86b57788 791 dbg(udev_device->udev, "udev_device: %p released\n", udev_device);
eb1f0e66
KS
792 free(udev_device);
793}
794
795/**
796 * udev_device_get_devpath:
797 * @udev_device: udev device
798 *
11d543c1
KS
799 * Retrieve the kernel devpath value of the udev device. The path
800 * does not contain the sys mount point, and starts with a '/'.
eb1f0e66 801 *
11d543c1 802 * Returns: the devpath of the udev device
eb1f0e66
KS
803 **/
804const char *udev_device_get_devpath(struct udev_device *udev_device)
805{
ba6929f6
KS
806 if (udev_device == NULL)
807 return NULL;
808 return udev_device->devpath;
eb1f0e66
KS
809}
810
11d543c1
KS
811/**
812 * udev_device_get_syspath:
813 * @udev_device: udev device
814 *
815 * Retrieve the sys path of the udev device. The path is an
816 * absolute path and starts with the sys mount point.
817 *
818 * Returns: the sys path of the udev device
819 **/
820const char *udev_device_get_syspath(struct udev_device *udev_device)
821{
822 if (udev_device == NULL)
823 return NULL;
824 return udev_device->syspath;
825}
826
1e511322
KS
827/**
828 * udev_device_get_sysname:
829 * @udev_device: udev device
830 *
831 * Returns: the sys name of the device device
832 **/
4ad3a37f
KS
833const char *udev_device_get_sysname(struct udev_device *udev_device)
834{
835 if (udev_device == NULL)
836 return NULL;
837 return udev_device->sysname;
838}
839
1e511322
KS
840/**
841 * udev_device_get_sysnum:
842 * @udev_device: udev device
843 *
844 * Returns: the trailing number of of the device name
845 **/
517814e7
KS
846const char *udev_device_get_sysnum(struct udev_device *udev_device)
847{
848 if (udev_device == NULL)
849 return NULL;
850 return udev_device->sysnum;
851}
852
eb1f0e66 853/**
fb762bb9 854 * udev_device_get_devnode:
eb1f0e66
KS
855 * @udev_device: udev device
856 *
857 * Retrieve the device node file name belonging to the udev device.
ba6929f6 858 * The path is an absolute path, and starts with the device directory.
eb1f0e66
KS
859 *
860 * Returns: the device node file name of the udev device, or #NULL if no device node exists
861 **/
fb762bb9 862const char *udev_device_get_devnode(struct udev_device *udev_device)
eb1f0e66 863{
ba6929f6 864 if (udev_device == NULL)
eb1f0e66 865 return NULL;
cdb1d760
KS
866 if (!udev_device->info_loaded) {
867 udev_device_read_uevent_file(udev_device);
28460195 868 udev_device_read_db(udev_device);
cdb1d760
KS
869 }
870
871 /* we might get called before we handled an event and have a db, use the kernel-provided name */
872 if (udev_device->devnode == NULL && udev_device_get_knodename(udev_device) != NULL) {
24d10766
KS
873 char filename[UTIL_NAME_SIZE];
874
875 util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/",
876 udev_device_get_knodename(udev_device), NULL);
877 udev_device_set_devnode(udev_device, filename);
cdb1d760
KS
878 return udev_device->devnode;
879 }
880
99214844 881 return udev_device->devnode;
eb1f0e66
KS
882}
883
884/**
885 * udev_device_get_subsystem:
886 * @udev_device: udev device
887 *
888 * Retrieve the subsystem string of the udev device. The string does not
889 * contain any "/".
890 *
891 * Returns: the subsystem name of the udev device, or #NULL if it can not be determined
892 **/
893const char *udev_device_get_subsystem(struct udev_device *udev_device)
894{
17fcfb59 895 char subsystem[UTIL_NAME_SIZE];
ba6929f6
KS
896
897 if (udev_device == NULL)
898 return NULL;
5c5cad79 899 if (!udev_device->subsystem_set) {
28460195 900 udev_device->subsystem_set = true;
214a6c79 901 /* read "subsystem" link */
5c5cad79
KS
902 if (util_get_sys_subsystem(udev_device->udev, udev_device->syspath, subsystem, sizeof(subsystem)) > 0) {
903 udev_device_set_subsystem(udev_device, subsystem);
904 return udev_device->subsystem;
905 }
906 /* implicit names */
907 if (strncmp(udev_device->devpath, "/module/", 8) == 0) {
908 udev_device_set_subsystem(udev_device, "module");
909 return udev_device->subsystem;
910 }
911 if (strstr(udev_device->devpath, "/drivers/") != NULL) {
912 udev_device_set_subsystem(udev_device, "drivers");
913 return udev_device->subsystem;
914 }
915 if (strncmp(udev_device->devpath, "/subsystem/", 11) == 0 ||
916 strncmp(udev_device->devpath, "/class/", 7) == 0 ||
917 strncmp(udev_device->devpath, "/bus/", 5) == 0) {
918 udev_device_set_subsystem(udev_device, "subsystem");
919 return udev_device->subsystem;
920 }
0518da3b 921 }
5c5cad79 922 return udev_device->subsystem;
eb1f0e66
KS
923}
924
bf8b2ae1
MH
925/**
926 * udev_device_get_devtype:
927 * @udev_device: udev device
928 *
929 * Retrieve the devtype string of the udev device.
930 *
931 * Returns: the devtype name of the udev device, or #NULL if it can not be determined
932 **/
933const char *udev_device_get_devtype(struct udev_device *udev_device)
934{
935 if (udev_device == NULL)
936 return NULL;
937 if (!udev_device->devtype_set) {
28460195
KS
938 udev_device->devtype_set = true;
939 udev_device_read_uevent_file(udev_device);
bf8b2ae1
MH
940 }
941 return udev_device->devtype;
942}
943
eb1f0e66 944/**
0de33a61 945 * udev_device_get_devlinks_list_entry:
eb1f0e66 946 * @udev_device: udev device
eb1f0e66 947 *
bf7ad0ea
KS
948 * Retrieve the list of device links pointing to the device file of
949 * the udev device. The next list entry can be retrieved with
e345e267 950 * udev_list_entry_next(), which returns #NULL if no more entries exist.
bf7ad0ea 951 * The devlink path can be retrieved from the list entry by
e345e267 952 * udev_list_entry_get_name(). The path is an absolute path, and starts with
bf7ad0ea 953 * the device directory.
eb1f0e66 954 *
bf7ad0ea 955 * Returns: the first entry of the device node link list
eb1f0e66 956 **/
0de33a61 957struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device)
eb1f0e66 958{
99214844
KS
959 if (udev_device == NULL)
960 return NULL;
961 if (!udev_device->info_loaded)
28460195 962 udev_device_read_db(udev_device);
517814e7 963 return udev_list_get_entry(&udev_device->devlinks_list);
eb1f0e66
KS
964}
965
979ff016
KS
966void udev_device_cleanup_devlinks_list(struct udev_device *udev_device)
967{
28460195 968 udev_device->devlinks_uptodate = false;
eb8837e1 969 udev_list_cleanup_entries(udev_device->udev, &udev_device->devlinks_list);
979ff016
KS
970}
971
eb1f0e66 972/**
0de33a61 973 * udev_device_get_properties_list_entry:
eb1f0e66 974 * @udev_device: udev device
eb1f0e66 975 *
bf7ad0ea 976 * Retrieve the list of key/value device properties of the udev
e345e267 977 * device. The next list entry can be retrieved with udev_list_entry_next(),
bf7ad0ea
KS
978 * which returns #NULL if no more entries exist. The property name
979 * can be retrieved from the list entry by udev_list_get_name(),
980 * the property value by udev_list_get_value().
eb1f0e66 981 *
bf7ad0ea 982 * Returns: the first entry of the property list
eb1f0e66 983 **/
0de33a61 984struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device)
eb1f0e66 985{
99214844
KS
986 if (udev_device == NULL)
987 return NULL;
28460195
KS
988 if (!udev_device->info_loaded) {
989 udev_device_read_uevent_file(udev_device);
990 udev_device_read_db(udev_device);
991 }
bd85566c
KS
992 if (!udev_device->devlinks_uptodate) {
993 char symlinks[UTIL_PATH_SIZE];
994 struct udev_list_entry *list_entry;
995
28460195 996 udev_device->devlinks_uptodate = true;
bd85566c
KS
997 list_entry = udev_device_get_devlinks_list_entry(udev_device);
998 if (list_entry != NULL) {
065db052
KS
999 char *s;
1000 size_t l;
1001
1002 s = symlinks;
1003 l = util_strpcpyl(&s, sizeof(symlinks), udev_list_entry_get_name(list_entry), NULL);
1004 udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry))
1005 l = util_strpcpyl(&s, l, " ", udev_list_entry_get_name(list_entry), NULL);
bd85566c
KS
1006 udev_device_add_property(udev_device, "DEVLINKS", symlinks);
1007 }
1008 }
28460195
KS
1009 if (!udev_device->tags_uptodate) {
1010 udev_device->tags_uptodate = true;
1011 if (udev_device_get_tags_list_entry(udev_device) != NULL) {
1012 char tags[UTIL_PATH_SIZE];
1013 struct udev_list_entry *list_entry;
1014 char *s;
1015 size_t l;
1016
1017 s = tags;
1018 l = util_strpcpyl(&s, sizeof(tags), ":", NULL);
1019 udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(udev_device))
1020 l = util_strpcpyl(&s, l, udev_list_entry_get_name(list_entry), ":", NULL);
1021 udev_device_add_property(udev_device, "TAGS", tags);
1022 }
1023 }
8cd2e972 1024 return udev_list_get_entry(&udev_device->properties_list);
eb1f0e66 1025}
11d543c1 1026
1e511322
KS
1027/**
1028 * udev_device_get_driver:
1029 * @udev_device: udev device
1030 *
ce1d6d7f 1031 * Returns: the driver string, or #NULL if there is no driver attached.
1e511322 1032 **/
c4f5f942
KS
1033const char *udev_device_get_driver(struct udev_device *udev_device)
1034{
17fcfb59 1035 char driver[UTIL_NAME_SIZE];
95d90c4f 1036
c4f5f942
KS
1037 if (udev_device == NULL)
1038 return NULL;
5c5cad79 1039 if (!udev_device->driver_set) {
28460195 1040 udev_device->driver_set = true;
5c5cad79
KS
1041 if (util_get_sys_driver(udev_device->udev, udev_device->syspath, driver, sizeof(driver)) > 0)
1042 udev_device->driver = strdup(driver);
1043 }
c4f5f942
KS
1044 return udev_device->driver;
1045}
1046
1e511322
KS
1047/**
1048 * udev_device_get_devnum:
1049 * @udev_device: udev device
1050 *
1051 * Returns: the device major/minor number.
1052 **/
c4f5f942
KS
1053dev_t udev_device_get_devnum(struct udev_device *udev_device)
1054{
1055 if (udev_device == NULL)
1056 return makedev(0, 0);
99214844 1057 if (!udev_device->info_loaded)
28460195 1058 udev_device_read_uevent_file(udev_device);
c4f5f942
KS
1059 return udev_device->devnum;
1060}
1061
1e511322
KS
1062/**
1063 * udev_device_get_action:
1064 * @udev_device: udev device
1065 *
1066 * This is only valid if the device was received through a monitor. Devices read from
1067 * sys do not have an action string. Usual actions are: add, remove, change, online,
1068 * offline.
1069 *
1070 * Returns: the kernel action value, or #NULL if there is no action value available.
1071 **/
c4f5f942
KS
1072const char *udev_device_get_action(struct udev_device *udev_device)
1073{
1074 if (udev_device == NULL)
1075 return NULL;
1076 return udev_device->action;
1077}
1078
1e511322
KS
1079/**
1080 * udev_device_get_devnum:
1081 * @udev_device: udev device
1082 *
1083 * This is only valid if the device was received through a monitor. Devices read from
1084 * sys do not have a sequence number.
1085 *
1086 * Returns: the kernel event sequence number, or 0 if there is no sequence number available.
1087 **/
37372bbc
KS
1088unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device)
1089{
1090 if (udev_device == NULL)
1091 return 0;
1092 return udev_device->seqnum;
1093}
1094
1e511322
KS
1095/**
1096 * udev_device_get_sysattr_value:
1097 * @udev_device: udev device
1098 * @sysattr: attribute name
1099 *
456719b6 1100 * The retrieved value is cached in the device. Repeated calls will return the same
1e511322
KS
1101 * value and not open the attribute again.
1102 *
1103 * Returns: the content of a sys attribute file, or #NULL if there is no sys attribute value.
1104 **/
69239210 1105const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr)
93b0f384 1106{
0de33a61 1107 struct udev_list_entry *list_entry;
93b0f384 1108 char path[UTIL_PATH_SIZE];
affed87a 1109 char value[4096];
93b0f384
KS
1110 struct stat statbuf;
1111 int fd;
1112 ssize_t size;
1113 const char *val = NULL;
1114
517814e7
KS
1115 if (udev_device == NULL)
1116 return NULL;
69239210 1117 if (sysattr == NULL)
517814e7
KS
1118 return NULL;
1119
0518da3b 1120 /* look for possibly already cached result */
69239210
KS
1121 udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_device->sysattr_list)) {
1122 if (strcmp(udev_list_entry_get_name(list_entry), sysattr) == 0) {
86b57788
KS
1123 dbg(udev_device->udev, "got '%s' (%s) from cache\n",
1124 sysattr, udev_list_entry_get_value(list_entry));
0de33a61 1125 return udev_list_entry_get_value(list_entry);
0518da3b
KS
1126 }
1127 }
1128
065db052 1129 util_strscpyl(path, sizeof(path), udev_device_get_syspath(udev_device), "/", sysattr, NULL);
93b0f384 1130 if (lstat(path, &statbuf) != 0) {
86b57788 1131 dbg(udev_device->udev, "no attribute '%s', keep negative entry\n", path);
69239210 1132 udev_list_entry_add(udev_device->udev, &udev_device->sysattr_list, sysattr, NULL, 0, 0);
93b0f384
KS
1133 goto out;
1134 }
1135
1136 if (S_ISLNK(statbuf.st_mode)) {
93b0f384
KS
1137 char target[UTIL_NAME_SIZE];
1138 int len;
1139 char *pos;
1140
096e59ed
KS
1141 /* some core links return the last element of the target path */
1142 if (strcmp(sysattr, "driver") != 0 &&
1143 strcmp(sysattr, "subsystem") != 0 &&
1144 strcmp(sysattr, "module") != 0)
1145 goto out;
1146
93b0f384 1147 len = readlink(path, target, sizeof(target));
60067cc7
KS
1148 if (len <= 0 || len == sizeof(target))
1149 goto out;
1150 target[len] = '\0';
1151
1152 pos = strrchr(target, '/');
1153 if (pos != NULL) {
1154 pos = &pos[1];
1155 dbg(udev_device->udev, "cache '%s' with link value '%s'\n", sysattr, pos);
1156 list_entry = udev_list_entry_add(udev_device->udev, &udev_device->sysattr_list, sysattr, pos, 0, 0);
1157 val = udev_list_entry_get_value(list_entry);
93b0f384 1158 }
60067cc7 1159
93b0f384
KS
1160 goto out;
1161 }
1162
1163 /* skip directories */
1164 if (S_ISDIR(statbuf.st_mode))
1165 goto out;
1166
1167 /* skip non-readable files */
1168 if ((statbuf.st_mode & S_IRUSR) == 0)
1169 goto out;
1170
1171 /* read attribute value */
0c5c4804 1172 fd = open(path, O_RDONLY|O_CLOEXEC);
93b0f384 1173 if (fd < 0) {
86b57788 1174 dbg(udev_device->udev, "attribute '%s' can not be opened\n", path);
93b0f384
KS
1175 goto out;
1176 }
1177 size = read(fd, value, sizeof(value));
1178 close(fd);
1179 if (size < 0)
1180 goto out;
1181 if (size == sizeof(value))
1182 goto out;
1183
0518da3b 1184 /* got a valid value, store it in cache and return it */
93b0f384
KS
1185 value[size] = '\0';
1186 util_remove_trailing_chars(value, '\n');
86b57788 1187 dbg(udev_device->udev, "'%s' has attribute value '%s'\n", path, value);
69239210 1188 list_entry = udev_list_entry_add(udev_device->udev, &udev_device->sysattr_list, sysattr, value, 0, 0);
0de33a61 1189 val = udev_list_entry_get_value(list_entry);
93b0f384
KS
1190out:
1191 return val;
1192}
517814e7 1193
8cd2e972 1194int udev_device_set_syspath(struct udev_device *udev_device, const char *syspath)
11d543c1 1195{
8753fadf 1196 const char *pos;
517814e7 1197 size_t len;
8753fadf 1198
8cd2e972 1199 free(udev_device->syspath);
8753fadf
KS
1200 udev_device->syspath = strdup(syspath);
1201 if (udev_device->syspath == NULL)
11d543c1
KS
1202 return -ENOMEM;
1203 udev_device->devpath = &udev_device->syspath[strlen(udev_get_sys_path(udev_device->udev))];
9a997ecf 1204 udev_device_add_property(udev_device, "DEVPATH", udev_device->devpath);
517814e7 1205
8753fadf
KS
1206 pos = strrchr(udev_device->syspath, '/');
1207 if (pos == NULL)
1208 return -EINVAL;
517814e7
KS
1209 udev_device->sysname = strdup(&pos[1]);
1210 if (udev_device->sysname == NULL)
1211 return -ENOMEM;
1212
1213 /* some devices have '!' in their name, change that to '/' */
1214 len = 0;
1215 while (udev_device->sysname[len] != '\0') {
1216 if (udev_device->sysname[len] == '!')
1217 udev_device->sysname[len] = '/';
1218 len++;
1219 }
1220
1221 /* trailing number */
babcf3cb 1222 while (len > 0 && isdigit(udev_device->sysname[--len]))
517814e7 1223 udev_device->sysnum = &udev_device->sysname[len];
babcf3cb
AJ
1224
1225 /* sysname is completely numeric */
1226 if (len == 0)
1227 udev_device->sysnum = NULL;
1228
11d543c1
KS
1229 return 0;
1230}
1231
8cd2e972 1232int udev_device_set_subsystem(struct udev_device *udev_device, const char *subsystem)
11d543c1 1233{
979ff016 1234 free(udev_device->subsystem);
11d543c1
KS
1235 udev_device->subsystem = strdup(subsystem);
1236 if (udev_device->subsystem == NULL)
9a997ecf 1237 return -ENOMEM;
28460195 1238 udev_device->subsystem_set = true;
9a997ecf 1239 udev_device_add_property(udev_device, "SUBSYSTEM", udev_device->subsystem);
11d543c1
KS
1240 return 0;
1241}
1242
bf8b2ae1
MH
1243int udev_device_set_devtype(struct udev_device *udev_device, const char *devtype)
1244{
1245 free(udev_device->devtype);
1246 udev_device->devtype = strdup(devtype);
1247 if (udev_device->devtype == NULL)
1248 return -ENOMEM;
28460195 1249 udev_device->devtype_set = true;
bf8b2ae1
MH
1250 udev_device_add_property(udev_device, "DEVTYPE", udev_device->devtype);
1251 return 0;
1252}
1253
8cd2e972 1254int udev_device_set_devnode(struct udev_device *udev_device, const char *devnode)
11d543c1 1255{
517814e7 1256 free(udev_device->devnode);
99214844
KS
1257 udev_device->devnode = strdup(devnode);
1258 if (udev_device->devnode == NULL)
11d543c1 1259 return -ENOMEM;
979ff016 1260 udev_device_add_property(udev_device, "DEVNAME", udev_device->devnode);
11d543c1
KS
1261 return 0;
1262}
1263
6c29f2b9 1264int udev_device_add_devlink(struct udev_device *udev_device, const char *devlink, int unique)
11d543c1 1265{
6c29f2b9
KS
1266 struct udev_list_entry *list_entry;
1267
28460195 1268 udev_device->devlinks_uptodate = false;
6c29f2b9
KS
1269 list_entry = udev_list_entry_add(udev_device->udev, &udev_device->devlinks_list, devlink, NULL, 1, 0);
1270 if (list_entry == NULL)
11d543c1 1271 return -ENOMEM;
6c29f2b9 1272 if (unique)
fbb31cd6 1273 udev_list_entry_set_flags(list_entry, 1);
11d543c1
KS
1274 return 0;
1275}
1276
4281da1f
KS
1277const char *udev_device_get_id_filename(struct udev_device *udev_device)
1278{
1279 if (udev_device->id_filename == NULL) {
1280 if (udev_device_get_subsystem(udev_device) == NULL)
1281 return NULL;
1282
1283 if (major(udev_device_get_devnum(udev_device)) > 0) {
1284 /* use dev_t -- b259:131072, c254:0 */
1285 if (asprintf(&udev_device->id_filename, "%c%u:%u",
1286 strcmp(udev_device_get_subsystem(udev_device), "block") == 0 ? 'b' : 'c',
1287 major(udev_device_get_devnum(udev_device)),
1288 minor(udev_device_get_devnum(udev_device))) < 0)
1289 udev_device->id_filename = NULL;
ff0e1f4e 1290 } else if (udev_device_get_ifindex(udev_device) > 0) {
4281da1f
KS
1291 /* use netdev ifindex -- n3 */
1292 if (asprintf(&udev_device->id_filename, "n%u", udev_device_get_ifindex(udev_device)) < 0)
1293 udev_device->id_filename = NULL;
1294 } else {
1295 /*
1296 * use $subsys:$syname -- pci:0000:00:1f.2
1297 * sysname() has '!' translated, get it from devpath
1298 */
1299 const char *sysname;
1300 sysname = strrchr(udev_device->devpath, '/');
1301 if (sysname == NULL)
1302 return NULL;
1303 sysname = &sysname[1];
1304 if (asprintf(&udev_device->id_filename, "+%s:%s", udev_device_get_subsystem(udev_device), sysname) < 0)
1305 udev_device->id_filename = NULL;
1306 }
1307 }
1308 return udev_device->id_filename;
1309}
1310
28460195
KS
1311int udev_device_add_tag(struct udev_device *udev_device, const char *tag)
1312{
1313 if (strchr(tag, ':') != NULL || strchr(tag, ' ') != NULL)
1314 return -EINVAL;
1315 udev_device->tags_uptodate = false;
1316 if (udev_list_entry_add(udev_device->udev, &udev_device->tags_list, tag, NULL, 1, 0) != NULL)
1317 return 0;
1318 return -ENOMEM;
1319}
1320
1321void udev_device_cleanup_tags_list(struct udev_device *udev_device)
1322{
1323 udev_device->tags_uptodate = false;
1324 udev_list_cleanup_entries(udev_device->udev, &udev_device->tags_list);
1325}
1326
f712894d
KS
1327/**
1328 * udev_device_get_tags_list_entry:
1329 * @udev_device: udev device
1330 *
1331 * Retrieve the list of tags attached to the udev device. The next
1332 * list entry can be retrieved with udev_list_entry_next(),
1333 * which returns #NULL if no more entries exist. The tag string
1334 * can be retrieved from the list entry by udev_list_get_name().
1335 *
1336 * Returns: the first entry of the tag list
1337 **/
28460195
KS
1338struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device)
1339{
65f099c7
KS
1340 if (udev_device == NULL)
1341 return NULL;
28460195
KS
1342 return udev_list_get_entry(&udev_device->tags_list);
1343}
1344
1345int udev_device_has_tag(struct udev_device *udev_device, const char *tag)
1346{
1347 struct udev_list_entry *list_entry;
1348
1349 if (!udev_device->info_loaded)
1350 udev_device_read_db(udev_device);
1351 list_entry = udev_device_get_tags_list_entry(udev_device);
1352 list_entry = udev_list_entry_get_by_name(list_entry, tag);
1353 if (list_entry != NULL)
1354 return 1;
1355 return 0;
1356}
1357
6493e655
KS
1358#define ENVP_SIZE 128
1359#define MONITOR_BUF_SIZE 4096
1360static int update_envp_monitor_buf(struct udev_device *udev_device)
979ff016 1361{
6493e655 1362 struct udev_list_entry *list_entry;
065db052
KS
1363 char *s;
1364 size_t l;
6493e655 1365 unsigned int i;
979ff016 1366
6493e655
KS
1367 /* monitor buffer of property strings */
1368 free(udev_device->monitor_buf);
1369 udev_device->monitor_buf_len = 0;
1370 udev_device->monitor_buf = malloc(MONITOR_BUF_SIZE);
1371 if (udev_device->monitor_buf == NULL)
1372 return -ENOMEM;
be18918f 1373
6493e655 1374 /* envp array, strings will point into monitor buffer */
427e20b2
KS
1375 if (udev_device->envp == NULL)
1376 udev_device->envp = malloc(sizeof(char *) * ENVP_SIZE);
6493e655
KS
1377 if (udev_device->envp == NULL)
1378 return -ENOMEM;
979ff016 1379
6493e655 1380 i = 0;
065db052
KS
1381 s = udev_device->monitor_buf;
1382 l = MONITOR_BUF_SIZE;
6493e655 1383 udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(udev_device)) {
b25a9454
KS
1384 const char *key;
1385
1386 key = udev_list_entry_get_name(list_entry);
1387 /* skip private variables */
1388 if (key[0] == '.')
1389 continue;
1390
6493e655 1391 /* add string to envp array */
065db052 1392 udev_device->envp[i++] = s;
6493e655
KS
1393 if (i+1 >= ENVP_SIZE)
1394 return -EINVAL;
c2654402 1395
6493e655 1396 /* add property string to monitor buffer */
b25a9454 1397 l = util_strpcpyl(&s, l, key, "=", udev_list_entry_get_value(list_entry), NULL);
065db052 1398 if (l == 0)
c2654402 1399 return -EINVAL;
ecd42de2 1400 /* advance past the trailing '\0' that util_strpcpyl() guarantees */
065db052 1401 s++;
ecd42de2 1402 l--;
c2654402 1403 }
6493e655 1404 udev_device->envp[i] = NULL;
065db052 1405 udev_device->monitor_buf_len = s - udev_device->monitor_buf;
28460195 1406 udev_device->envp_uptodate = true;
065db052
KS
1407 dbg(udev_device->udev, "filled envp/monitor buffer, %u properties, %zu bytes\n",
1408 i, udev_device->monitor_buf_len);
6493e655
KS
1409 return 0;
1410}
1411
1412char **udev_device_get_properties_envp(struct udev_device *udev_device)
1413{
1414 if (!udev_device->envp_uptodate)
c6243a41 1415 if (update_envp_monitor_buf(udev_device) != 0)
6493e655
KS
1416 return NULL;
1417 return udev_device->envp;
1418}
1419
1420ssize_t udev_device_get_properties_monitor_buf(struct udev_device *udev_device, const char **buf)
1421{
1422 if (!udev_device->envp_uptodate)
c6243a41 1423 if (update_envp_monitor_buf(udev_device) != 0)
6493e655 1424 return -EINVAL;
c2654402 1425 *buf = udev_device->monitor_buf;
c2654402
KS
1426 return udev_device->monitor_buf_len;
1427}
1428
8cd2e972 1429int udev_device_set_action(struct udev_device *udev_device, const char *action)
c4f5f942 1430{
517814e7 1431 free(udev_device->action);
c4f5f942
KS
1432 udev_device->action = strdup(action);
1433 if (udev_device->action == NULL)
1434 return -ENOMEM;
31f4b036 1435 udev_device_add_property(udev_device, "ACTION", udev_device->action);
c4f5f942
KS
1436 return 0;
1437}
1438
8cd2e972 1439int udev_device_set_driver(struct udev_device *udev_device, const char *driver)
c4f5f942 1440{
979ff016 1441 free(udev_device->driver);
c4f5f942
KS
1442 udev_device->driver = strdup(driver);
1443 if (udev_device->driver == NULL)
1444 return -ENOMEM;
28460195 1445 udev_device->driver_set = true;
31f4b036 1446 udev_device_add_property(udev_device, "DRIVER", udev_device->driver);
c4f5f942
KS
1447 return 0;
1448}
1449
8cd2e972 1450const char *udev_device_get_devpath_old(struct udev_device *udev_device)
c4f5f942 1451{
c4f5f942
KS
1452 return udev_device->devpath_old;
1453}
1454
8cd2e972 1455int udev_device_set_devpath_old(struct udev_device *udev_device, const char *devpath_old)
c4f5f942 1456{
2ffc9cc1
KS
1457 const char *pos;
1458 size_t len;
1459
a71369b0 1460 free(udev_device->devpath_old);
c4f5f942
KS
1461 udev_device->devpath_old = strdup(devpath_old);
1462 if (udev_device->devpath_old == NULL)
1463 return -ENOMEM;
31f4b036 1464 udev_device_add_property(udev_device, "DEVPATH_OLD", udev_device->devpath_old);
2ffc9cc1
KS
1465
1466 pos = strrchr(udev_device->devpath_old, '/');
1467 if (pos == NULL)
1468 return -EINVAL;
1469 udev_device->sysname_old = strdup(&pos[1]);
1470 if (udev_device->sysname_old == NULL)
1471 return -ENOMEM;
1472
1473 /* some devices have '!' in their name, change that to '/' */
1474 len = 0;
1475 while (udev_device->sysname_old[len] != '\0') {
1476 if (udev_device->sysname_old[len] == '!')
1477 udev_device->sysname_old[len] = '/';
1478 len++;
1479 }
c4f5f942
KS
1480 return 0;
1481}
1482
2ffc9cc1
KS
1483const char *udev_device_get_sysname_old(struct udev_device *udev_device)
1484{
1485 if (udev_device == NULL)
1486 return NULL;
1487 return udev_device->sysname_old;
1488}
1489
cb14f454
KS
1490const char *udev_device_get_knodename(struct udev_device *udev_device)
1491{
1492 return udev_device->knodename;
1493}
1494
1495int udev_device_set_knodename(struct udev_device *udev_device, const char *knodename)
1496{
a71369b0 1497 free(udev_device->knodename);
cb14f454
KS
1498 udev_device->knodename = strdup(knodename);
1499 if (udev_device->knodename == NULL)
1500 return -ENOMEM;
24d10766
KS
1501 /* do not overwrite the udev property with the kernel property */
1502 if (udev_device->devnode == NULL)
1503 udev_device_add_property(udev_device, "DEVNAME", udev_device->knodename);
cb14f454
KS
1504 return 0;
1505}
1506
8cd2e972 1507int udev_device_get_timeout(struct udev_device *udev_device)
c4f5f942 1508{
c4f5f942
KS
1509 return udev_device->timeout;
1510}
1511
8cd2e972 1512int udev_device_set_timeout(struct udev_device *udev_device, int timeout)
c4f5f942
KS
1513{
1514 udev_device->timeout = timeout;
1515 return 0;
1516}
8cd2e972 1517int udev_device_get_event_timeout(struct udev_device *udev_device)
99214844
KS
1518{
1519 if (!udev_device->info_loaded)
28460195 1520 udev_device_read_db(udev_device);
99214844
KS
1521 return udev_device->event_timeout;
1522}
1523
8cd2e972 1524int udev_device_set_event_timeout(struct udev_device *udev_device, int event_timeout)
99214844 1525{
4281da1f
KS
1526 char num[32];
1527
99214844 1528 udev_device->event_timeout = event_timeout;
4281da1f
KS
1529 snprintf(num, sizeof(num), "%u", event_timeout);
1530 udev_device_add_property(udev_device, "TIMEOUT", num);
99214844
KS
1531 return 0;
1532}
c4f5f942 1533
8cd2e972 1534int udev_device_set_seqnum(struct udev_device *udev_device, unsigned long long int seqnum)
37372bbc 1535{
31f4b036
KS
1536 char num[32];
1537
37372bbc 1538 udev_device->seqnum = seqnum;
31f4b036
KS
1539 snprintf(num, sizeof(num), "%llu", seqnum);
1540 udev_device_add_property(udev_device, "SEQNUM", num);
37372bbc
KS
1541 return 0;
1542}
1543
8cd2e972 1544int udev_device_set_devnum(struct udev_device *udev_device, dev_t devnum)
c4f5f942 1545{
31f4b036
KS
1546 char num[32];
1547
c4f5f942 1548 udev_device->devnum = devnum;
31f4b036
KS
1549
1550 snprintf(num, sizeof(num), "%u", major(devnum));
1551 udev_device_add_property(udev_device, "MAJOR", num);
1552 snprintf(num, sizeof(num), "%u", minor(devnum));
1553 udev_device_add_property(udev_device, "MINOR", num);
c4f5f942
KS
1554 return 0;
1555}
6bd1c78a 1556
8cd2e972 1557int udev_device_get_devlink_priority(struct udev_device *udev_device)
6bd1c78a 1558{
99214844 1559 if (!udev_device->info_loaded)
28460195 1560 udev_device_read_db(udev_device);
e88a82b5 1561 return udev_device->devlink_priority;
6bd1c78a
KS
1562}
1563
8cd2e972 1564int udev_device_set_devlink_priority(struct udev_device *udev_device, int prio)
6bd1c78a 1565{
e88a82b5
KS
1566 udev_device->devlink_priority = prio;
1567 return 0;
6bd1c78a
KS
1568}
1569
d7ce7539
SJR
1570int udev_device_get_watch_handle(struct udev_device *udev_device)
1571{
1572 if (!udev_device->info_loaded)
28460195 1573 udev_device_read_db(udev_device);
d7ce7539
SJR
1574 return udev_device->watch_handle;
1575}
1576
1577int udev_device_set_watch_handle(struct udev_device *udev_device, int handle)
1578{
1579 udev_device->watch_handle = handle;
1580 return 0;
1581}
fc416258
KS
1582
1583int udev_device_get_ifindex(struct udev_device *udev_device)
1584{
ff0e1f4e
KS
1585 if (!udev_device->info_loaded)
1586 udev_device_read_uevent_file(udev_device);
fc416258
KS
1587 return udev_device->ifindex;
1588}
1589
1590int udev_device_set_ifindex(struct udev_device *udev_device, int ifindex)
1591{
4281da1f
KS
1592 char num[32];
1593
fc416258 1594 udev_device->ifindex = ifindex;
4281da1f
KS
1595 snprintf(num, sizeof(num), "%u", ifindex);
1596 udev_device_add_property(udev_device, "IFINDEX", num);
fc416258
KS
1597 return 0;
1598}