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