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