]> git.ipfire.org Git - thirdparty/systemd.git/blame - udev/lib/libudev-device.c
libudev: more list rework
[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>
eb1f0e66
KS
28#include <sys/stat.h>
29
30#include "libudev.h"
31#include "libudev-private.h"
eb1f0e66 32
11d543c1
KS
33struct udev_device {
34 int refcount;
35 struct udev *udev;
b2d9e4f2 36 struct udev_device *parent_device;
11d543c1 37 char *syspath;
4ad3a37f
KS
38 const char *devpath;
39 const char *sysname;
99214844 40 char *devnode;
11d543c1 41 char *subsystem;
e345e267
KS
42 struct list_node devlink_list;
43 struct list_node properties_list;
c4f5f942 44 char *action;
99214844 45 int event_timeout;
c4f5f942
KS
46 char *driver;
47 char *devpath_old;
48 char *physdevpath;
49 int timeout;
50 dev_t devnum;
6bd1c78a
KS
51 unsigned long long int seqnum;
52 int num_fake_partitions;
e88a82b5 53 int devlink_priority;
6bd1c78a 54 int ignore_remove;
e345e267 55 struct list_node attr_list;
99214844 56 int info_loaded;
11d543c1
KS
57};
58
8753fadf 59static size_t syspath_to_db_path(struct udev_device *udev_device, char *filename, size_t len)
e88a82b5
KS
60{
61 size_t start;
62
63 /* translate to location of db file */
8753fadf 64 util_strlcpy(filename, udev_get_dev_path(udev_device->udev), len);
3eb46ec6 65 start = util_strlcat(filename, "/.udev/db/", len);
8753fadf 66 util_strlcat(filename, udev_device->devpath, len);
7a01f11a 67 return util_path_encode(&filename[start], len - start);
e88a82b5
KS
68}
69
70static int device_read_db(struct udev_device *udev_device)
71{
72 struct stat stats;
3eb46ec6
KS
73 char filename[UTIL_PATH_SIZE];
74 char line[UTIL_LINE_SIZE];
e88a82b5 75 FILE *f;
e88a82b5 76
8753fadf 77 syspath_to_db_path(udev_device, filename, sizeof(filename));
e88a82b5
KS
78
79 if (lstat(filename, &stats) != 0) {
80 info(udev_device->udev, "no db file to read %s: %s\n", filename, strerror(errno));
81 return -1;
82 }
83 if ((stats.st_mode & S_IFMT) == S_IFLNK) {
3eb46ec6 84 char target[UTIL_PATH_SIZE];
e88a82b5
KS
85 int target_len;
86
e88a82b5
KS
87 target_len = readlink(filename, target, sizeof(target));
88 if (target_len > 0)
89 target[target_len] = '\0';
90 else {
91 info(udev_device->udev, "error reading db link %s: %s\n", filename, strerror(errno));
92 return -1;
93 }
99214844 94 if (asprintf(&udev_device->devnode, "%s/%s", udev_get_dev_path(udev_device->udev), target) < 0)
e88a82b5 95 return -ENOMEM;
99214844 96 info(udev_device->udev, "device %p filled with db symlink data '%s'\n", udev_device, udev_device->devnode);
e88a82b5
KS
97 return 0;
98 }
99
100 f = fopen(filename, "r");
101 if (f == NULL) {
102 info(udev_device->udev, "error reading db file %s: %s\n", filename, strerror(errno));
103 return -1;
104 }
105 while (fgets(line, sizeof(line), f)) {
106 ssize_t len;
107 const char *val;
e88a82b5
KS
108
109 len = strlen(line);
110 if (len < 4)
111 break;
112 line[len-1] = '\0';
113 val = &line[2];
114
115 switch(line[0]) {
116 case 'N':
99214844 117 asprintf(&udev_device->devnode, "%s/%s", udev_get_dev_path(udev_device->udev), val);
e88a82b5 118 break;
e88a82b5 119 case 'S':
3eb46ec6
KS
120 util_strlcpy(filename, udev_get_dev_path(udev_device->udev), sizeof(filename));
121 util_strlcat(filename, "/", sizeof(filename));
122 util_strlcat(filename, val, sizeof(filename));
e88a82b5
KS
123 device_add_devlink(udev_device, filename);
124 break;
125 case 'L':
126 device_set_devlink_priority(udev_device, atoi(val));
127 break;
128 case 'T':
99214844 129 device_set_event_timeout(udev_device, atoi(val));
e88a82b5
KS
130 break;
131 case 'A':
132 device_set_num_fake_partitions(udev_device, atoi(val));
133 break;
134 case 'R':
135 device_set_ignore_remove(udev_device, atoi(val));
136 break;
137 case 'E':
0518da3b 138 device_add_property_from_string(udev_device, val);
e88a82b5
KS
139 break;
140 }
141 }
142 fclose(f);
143
cd42b50d 144 info(udev_device->udev, "device %p filled with db file data\n", udev_device);
04f5d75f 145 return 0;
e88a82b5
KS
146}
147
99214844
KS
148static int device_read_uevent_file(struct udev_device *udev_device)
149{
150 char filename[UTIL_PATH_SIZE];
151 FILE *f;
152 char line[UTIL_LINE_SIZE];
153 int maj = 0;
154 int min = 0;
155
156 util_strlcpy(filename, udev_device->syspath, sizeof(filename));
157 util_strlcat(filename, "/uevent", sizeof(filename));
158 f = fopen(filename, "r");
159 if (f == NULL)
160 return -1;
161
162 while (fgets(line, sizeof(line), f)) {
163 char *pos;
164
165 pos = strchr(line, '\n');
166 if (pos == NULL)
167 continue;
168 pos[0] = '\0';
169
170 if (strncmp(line, "MAJOR=", 6) == 0)
171 maj = strtoull(&line[6], NULL, 10);
172 else if (strncmp(line, "MINOR=", 6) == 0)
173 min = strtoull(&line[6], NULL, 10);
174
175 device_add_property_from_string(udev_device, line);
176 }
177
178 udev_device->devnum = makedev(maj, min);
179
180 fclose(f);
181 return 0;
182}
183
184static void device_load_info(struct udev_device *device)
185{
186 device_read_uevent_file(device);
187 device_read_db(device);
188 device->info_loaded = 1;
189}
190
191void device_set_info_loaded(struct udev_device *device)
192{
193 device->info_loaded = 1;
194}
195
ba6929f6 196struct udev_device *device_init(struct udev *udev)
eb1f0e66
KS
197{
198 struct udev_device *udev_device;
199
ba6929f6
KS
200 if (udev == NULL)
201 return NULL;
202
eb1f0e66
KS
203 udev_device = malloc(sizeof(struct udev_device));
204 if (udev_device == NULL)
205 return NULL;
206 memset(udev_device, 0x00, sizeof(struct udev_device));
207 udev_device->refcount = 1;
208 udev_device->udev = udev;
e345e267
KS
209 list_init(&udev_device->devlink_list);
210 list_init(&udev_device->properties_list);
211 list_init(&udev_device->attr_list);
7d563a17 212 info(udev_device->udev, "udev_device: %p created\n", udev_device);
eb1f0e66
KS
213 return udev_device;
214}
215
216/**
8753fadf 217 * udev_device_new_from_syspath:
eb1f0e66 218 * @udev: udev library context
8753fadf 219 * @syspath: sys device path including sys directory
eb1f0e66 220 *
8753fadf
KS
221 * Create new udev device, and fill in information from the sys
222 * device and the udev database entry. The sypath is the absolute
223 * path to the device, including the sys mount point.
eb1f0e66
KS
224 *
225 * The initial refcount is 1, and needs to be decremented to
226 * release the ressources of the udev device.
227 *
228 * Returns: a new udev device, or #NULL, if it does not exist
229 **/
8753fadf 230struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath)
eb1f0e66 231{
3eb46ec6 232 char path[UTIL_PATH_SIZE];
eb1f0e66
KS
233 struct stat statbuf;
234 struct udev_device *udev_device;
eb1f0e66 235
ba6929f6
KS
236 if (udev == NULL)
237 return NULL;
8753fadf 238 if (syspath == NULL)
ba6929f6
KS
239 return NULL;
240
8753fadf 241 util_strlcpy(path, syspath, sizeof(path));
4ad3a37f
KS
242 util_strlcat(path, "/uevent", sizeof(path));
243 if (stat(path, &statbuf) != 0) {
8753fadf 244 info(udev, "not a device :%s\n", syspath);
eb1f0e66 245 return NULL;
4ad3a37f 246 }
eb1f0e66
KS
247
248 udev_device = device_init(udev);
249 if (udev_device == NULL)
250 return NULL;
251
ba6929f6 252 /* resolve possible symlink to real path */
8753fadf 253 util_strlcpy(path, syspath, sizeof(path));
b21b95d7 254 util_resolve_sys_link(udev, path, sizeof(path));
8753fadf 255 device_set_syspath(udev_device, path);
7d563a17 256 info(udev, "device %p has devpath '%s'\n", udev_device, udev_device_get_devpath(udev_device));
eb1f0e66 257
eb1f0e66
KS
258 return udev_device;
259}
260
4c9dff47
KS
261struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum)
262{
263 char path[UTIL_PATH_SIZE];
03198b93 264 const char *type_str;
bf7ad0ea 265 struct udev_enumerate *enumerate;
0de33a61 266 struct udev_list_entry *list_entry;
bf7ad0ea 267 struct udev_device *device = NULL;
03198b93
KS
268
269 if (type == 'b')
270 type_str = "block";
271 else if (type == 'c')
272 type_str = "char";
273 else
274 return NULL;
4c9dff47 275
bf7ad0ea 276 /* /sys/dev/{block,char}/<maj>:<min> links */
03198b93
KS
277 snprintf(path, sizeof(path), "%s/dev/%s/%u:%u", udev_get_sys_path(udev),
278 type_str, major(devnum), minor(devnum));
bf7ad0ea
KS
279 if (util_resolve_sys_link(udev, path, sizeof(path)) == 0)
280 return udev_device_new_from_syspath(udev, path);
4c9dff47 281
04f5d75f 282 /* fallback to search all sys devices for the major/minor */
bf7ad0ea
KS
283 enumerate = udev_enumerate_new_from_subsystems(udev, NULL);
284 if (enumerate == NULL)
285 return NULL;
0de33a61 286 udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) {
bf7ad0ea
KS
287 struct udev_device *device_loop;
288
0de33a61 289 device_loop = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list_entry));
bf7ad0ea
KS
290 if (device_loop != NULL) {
291 if (udev_device_get_devnum(device_loop) == devnum) {
292 device = device_loop;
293 break;
294 }
295 udev_device_unref(device_loop);
296 }
bf7ad0ea
KS
297 }
298 udev_enumerate_unref(enumerate);
299 return device;
4c9dff47
KS
300}
301
b2d9e4f2 302static struct udev_device *device_new_from_parent(struct udev_device *udev_device)
4ad3a37f
KS
303{
304 struct udev_device *udev_device_parent = NULL;
305 char path[UTIL_PATH_SIZE];
306 char *pos;
307
308 if (udev_device == NULL)
309 return NULL;
310
8753fadf 311 util_strlcpy(path, udev_device->syspath, sizeof(path));
4ad3a37f
KS
312 while (1) {
313 pos = strrchr(path, '/');
b2d9e4f2 314 if (pos == path || pos == NULL)
4ad3a37f
KS
315 break;
316 pos[0] = '\0';
8753fadf 317 udev_device_parent = udev_device_new_from_syspath(udev_device->udev, path);
4ad3a37f 318 if (udev_device_parent != NULL)
0518da3b
KS
319 return udev_device_parent;
320 }
321
8753fadf 322 /* follow "device" link in deprecated sys /sys/class/ layout */
0518da3b 323 if (strncmp(udev_device->devpath, "/class/", 7) == 0) {
8753fadf 324 util_strlcpy(path, udev_device->syspath, sizeof(path));
0518da3b
KS
325 util_strlcat(path, "/device", sizeof(path));
326 if (util_resolve_sys_link(udev_device->udev, path, sizeof(path)) == 0) {
8753fadf 327 udev_device_parent = udev_device_new_from_syspath(udev_device->udev, path);
0518da3b
KS
328 if (udev_device_parent != NULL)
329 return udev_device_parent;
330 }
4ad3a37f 331 }
0518da3b 332 return NULL;
4ad3a37f
KS
333}
334
b2d9e4f2
KS
335struct udev_device *udev_device_get_parent(struct udev_device *udev_device)
336{
0518da3b
KS
337 if (udev_device->parent_device != NULL) {
338 info(udev_device->udev, "returning existing parent %p\n", udev_device->parent_device);
339 return udev_device->parent_device;
340 }
341 udev_device->parent_device = device_new_from_parent(udev_device);
b2d9e4f2
KS
342 return udev_device->parent_device;
343}
344
eb1f0e66
KS
345/**
346 * udev_device_get_udev:
7d8787b3 347 * @udev_device: udev device
eb1f0e66
KS
348 *
349 * Retrieve the udev library context the device was created with.
350 *
351 * Returns: the udev library context
352 **/
353struct udev *udev_device_get_udev(struct udev_device *udev_device)
354{
ba6929f6
KS
355 if (udev_device == NULL)
356 return NULL;
eb1f0e66
KS
357 return udev_device->udev;
358}
359
360/**
361 * udev_device_ref:
362 * @udev_device: udev device
363 *
364 * Take a reference of a udev device.
365 *
366 * Returns: the passed udev device
367 **/
368struct udev_device *udev_device_ref(struct udev_device *udev_device)
369{
ba6929f6
KS
370 if (udev_device == NULL)
371 return NULL;
eb1f0e66
KS
372 udev_device->refcount++;
373 return udev_device;
374}
375
376/**
377 * udev_device_unref:
378 * @udev_device: udev device
379 *
380 * Drop a reference of a udev device. If the refcount reaches zero,
381 * the ressources of the device will be released.
382 *
383 **/
384void udev_device_unref(struct udev_device *udev_device)
385{
ba6929f6
KS
386 if (udev_device == NULL)
387 return;
eb1f0e66
KS
388 udev_device->refcount--;
389 if (udev_device->refcount > 0)
390 return;
b2d9e4f2
KS
391 if (udev_device->parent_device != NULL)
392 udev_device_unref(udev_device->parent_device);
11d543c1 393 free(udev_device->syspath);
99214844 394 free(udev_device->devnode);
ba6929f6 395 free(udev_device->subsystem);
99214844 396 list_cleanup(udev_device->udev, &udev_device->devlink_list);
bf7ad0ea 397 list_cleanup(udev_device->udev, &udev_device->properties_list);
1c7047ea
KS
398 free(udev_device->action);
399 free(udev_device->driver);
400 free(udev_device->devpath_old);
401 free(udev_device->physdevpath);
bf7ad0ea 402 list_cleanup(udev_device->udev, &udev_device->attr_list);
7d563a17 403 info(udev_device->udev, "udev_device: %p released\n", udev_device);
eb1f0e66
KS
404 free(udev_device);
405}
406
407/**
408 * udev_device_get_devpath:
409 * @udev_device: udev device
410 *
11d543c1
KS
411 * Retrieve the kernel devpath value of the udev device. The path
412 * does not contain the sys mount point, and starts with a '/'.
eb1f0e66 413 *
11d543c1 414 * Returns: the devpath of the udev device
eb1f0e66
KS
415 **/
416const char *udev_device_get_devpath(struct udev_device *udev_device)
417{
ba6929f6
KS
418 if (udev_device == NULL)
419 return NULL;
420 return udev_device->devpath;
eb1f0e66
KS
421}
422
11d543c1
KS
423/**
424 * udev_device_get_syspath:
425 * @udev_device: udev device
426 *
427 * Retrieve the sys path of the udev device. The path is an
428 * absolute path and starts with the sys mount point.
429 *
430 * Returns: the sys path of the udev device
431 **/
432const char *udev_device_get_syspath(struct udev_device *udev_device)
433{
434 if (udev_device == NULL)
435 return NULL;
436 return udev_device->syspath;
437}
438
4ad3a37f
KS
439const char *udev_device_get_sysname(struct udev_device *udev_device)
440{
441 if (udev_device == NULL)
442 return NULL;
443 return udev_device->sysname;
444}
445
eb1f0e66 446/**
fb762bb9 447 * udev_device_get_devnode:
eb1f0e66
KS
448 * @udev_device: udev device
449 *
450 * Retrieve the device node file name belonging to the udev device.
ba6929f6 451 * The path is an absolute path, and starts with the device directory.
eb1f0e66
KS
452 *
453 * Returns: the device node file name of the udev device, or #NULL if no device node exists
454 **/
fb762bb9 455const char *udev_device_get_devnode(struct udev_device *udev_device)
eb1f0e66 456{
ba6929f6 457 if (udev_device == NULL)
eb1f0e66 458 return NULL;
99214844
KS
459 if (!udev_device->info_loaded)
460 device_load_info(udev_device);
461 return udev_device->devnode;
eb1f0e66
KS
462}
463
464/**
465 * udev_device_get_subsystem:
466 * @udev_device: udev device
467 *
468 * Retrieve the subsystem string of the udev device. The string does not
469 * contain any "/".
470 *
471 * Returns: the subsystem name of the udev device, or #NULL if it can not be determined
472 **/
473const char *udev_device_get_subsystem(struct udev_device *udev_device)
474{
17fcfb59 475 char subsystem[UTIL_NAME_SIZE];
ba6929f6
KS
476
477 if (udev_device == NULL)
478 return NULL;
479 if (udev_device->subsystem != NULL)
480 return udev_device->subsystem;
0518da3b
KS
481
482 /* read "subsytem" link */
279595bd 483 if (util_get_sys_subsystem(udev_device->udev, udev_device->syspath, subsystem, sizeof(subsystem)) > 0) {
0518da3b
KS
484 udev_device->subsystem = strdup(subsystem);
485 return udev_device->subsystem;
486 }
487
488 /* implicit names */
489 if (strncmp(udev_device->devpath, "/module/", 8) == 0) {
490 udev_device->subsystem = strdup("module");
491 return udev_device->subsystem;
492 }
493 if (strstr(udev_device->devpath, "/drivers/") != NULL) {
494 udev_device->subsystem = strdup("drivers");
495 return udev_device->subsystem;
496 }
497 if (strncmp(udev_device->devpath, "/subsystem/", 11) == 0 ||
498 strncmp(udev_device->devpath, "/class/", 7) == 0 ||
499 strncmp(udev_device->devpath, "/bus/", 5) == 0) {
500 udev_device->subsystem = strdup("subsystem");
501 return udev_device->subsystem;
502 }
503 return NULL;
eb1f0e66
KS
504}
505
506/**
0de33a61 507 * udev_device_get_devlinks_list_entry:
eb1f0e66 508 * @udev_device: udev device
eb1f0e66 509 *
bf7ad0ea
KS
510 * Retrieve the list of device links pointing to the device file of
511 * the udev device. The next list entry can be retrieved with
e345e267 512 * udev_list_entry_next(), which returns #NULL if no more entries exist.
bf7ad0ea 513 * The devlink path can be retrieved from the list entry by
e345e267 514 * udev_list_entry_get_name(). The path is an absolute path, and starts with
bf7ad0ea 515 * the device directory.
eb1f0e66 516 *
bf7ad0ea 517 * Returns: the first entry of the device node link list
eb1f0e66 518 **/
0de33a61 519struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device)
eb1f0e66 520{
99214844
KS
521 if (udev_device == NULL)
522 return NULL;
523 if (!udev_device->info_loaded)
524 device_load_info(udev_device);
525 return list_get_entry(&udev_device->devlink_list);
eb1f0e66
KS
526}
527
528/**
0de33a61 529 * udev_device_get_properties_list_entry:
eb1f0e66 530 * @udev_device: udev device
eb1f0e66 531 *
bf7ad0ea 532 * Retrieve the list of key/value device properties of the udev
e345e267 533 * device. The next list entry can be retrieved with udev_list_entry_next(),
bf7ad0ea
KS
534 * which returns #NULL if no more entries exist. The property name
535 * can be retrieved from the list entry by udev_list_get_name(),
536 * the property value by udev_list_get_value().
eb1f0e66 537 *
bf7ad0ea 538 * Returns: the first entry of the property list
eb1f0e66 539 **/
0de33a61 540struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device)
eb1f0e66 541{
99214844
KS
542 if (udev_device == NULL)
543 return NULL;
544 if (!udev_device->info_loaded)
545 device_load_info(udev_device);
bf7ad0ea 546 return list_get_entry(&udev_device->properties_list);
eb1f0e66 547}
11d543c1 548
c4f5f942
KS
549const char *udev_device_get_driver(struct udev_device *udev_device)
550{
17fcfb59 551 char driver[UTIL_NAME_SIZE];
95d90c4f 552
c4f5f942
KS
553 if (udev_device == NULL)
554 return NULL;
95d90c4f
KS
555 if (udev_device->driver != NULL)
556 return udev_device->driver;
8753fadf 557 if (util_get_sys_driver(udev_device->udev, udev_device->syspath, driver, sizeof(driver)) < 2)
95d90c4f
KS
558 return NULL;
559 udev_device->driver = strdup(driver);
c4f5f942
KS
560 return udev_device->driver;
561}
562
563dev_t udev_device_get_devnum(struct udev_device *udev_device)
564{
565 if (udev_device == NULL)
566 return makedev(0, 0);
99214844
KS
567 if (!udev_device->info_loaded)
568 device_load_info(udev_device);
c4f5f942
KS
569 return udev_device->devnum;
570}
571
572const char *udev_device_get_action(struct udev_device *udev_device)
573{
574 if (udev_device == NULL)
575 return NULL;
576 return udev_device->action;
577}
578
37372bbc
KS
579unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device)
580{
581 if (udev_device == NULL)
582 return 0;
583 return udev_device->seqnum;
584}
585
93b0f384
KS
586const char *udev_device_get_attr_value(struct udev_device *udev_device, const char *attr)
587{
0de33a61 588 struct udev_list_entry *list_entry;
93b0f384
KS
589 char path[UTIL_PATH_SIZE];
590 char value[UTIL_NAME_SIZE];
591 struct stat statbuf;
592 int fd;
593 ssize_t size;
594 const char *val = NULL;
595
0518da3b 596 /* look for possibly already cached result */
0de33a61
KS
597 udev_list_entry_foreach(list_entry, list_get_entry(&udev_device->attr_list)) {
598 if (strcmp(udev_list_entry_get_name(list_entry), attr) == 0) {
599 info(udev_device->udev, "got '%s' (%s) from cache\n", attr, udev_list_entry_get_value(list_entry));
600 return udev_list_entry_get_value(list_entry);
0518da3b
KS
601 }
602 }
603
93b0f384
KS
604 util_strlcpy(path, udev_device_get_syspath(udev_device), sizeof(path));
605 util_strlcat(path, "/", sizeof(path));
606 util_strlcat(path, attr, sizeof(path));
607
608 if (lstat(path, &statbuf) != 0) {
609 info(udev_device->udev, "stat '%s' failed: %s\n", path, strerror(errno));
610 goto out;
611 }
612
613 if (S_ISLNK(statbuf.st_mode)) {
614 /* links return the last element of the target path */
615 char target[UTIL_NAME_SIZE];
616 int len;
617 char *pos;
618
619 len = readlink(path, target, sizeof(target));
620 if (len > 0) {
621 target[len] = '\0';
622 pos = strrchr(target, '/');
623 if (pos != NULL) {
624 pos = &pos[1];
625 info(udev_device->udev, "cache '%s' with link value '%s'\n", attr, pos);
0de33a61
KS
626 list_entry = list_entry_add(udev_device->udev, &udev_device->attr_list, attr, pos, 0, 0);
627 val = udev_list_entry_get_value(list_entry);
93b0f384
KS
628 }
629 }
630 goto out;
631 }
632
633 /* skip directories */
634 if (S_ISDIR(statbuf.st_mode))
635 goto out;
636
637 /* skip non-readable files */
638 if ((statbuf.st_mode & S_IRUSR) == 0)
639 goto out;
640
641 /* read attribute value */
642 fd = open(path, O_RDONLY);
643 if (fd < 0) {
644 info(udev_device->udev, "attribute '%s' can not be opened\n", path);
645 goto out;
646 }
647 size = read(fd, value, sizeof(value));
648 close(fd);
649 if (size < 0)
650 goto out;
651 if (size == sizeof(value))
652 goto out;
653
0518da3b 654 /* got a valid value, store it in cache and return it */
93b0f384
KS
655 value[size] = '\0';
656 util_remove_trailing_chars(value, '\n');
657 info(udev_device->udev, "'%s' has attribute value '%s'\n", path, value);
0de33a61
KS
658 list_entry = list_entry_add(udev_device->udev, &udev_device->attr_list, attr, value, 0, 0);
659 val = udev_list_entry_get_value(list_entry);
93b0f384
KS
660out:
661 return val;
662}
8753fadf 663int device_set_syspath(struct udev_device *udev_device, const char *syspath)
11d543c1 664{
8753fadf
KS
665 const char *pos;
666
667 udev_device->syspath = strdup(syspath);
668 if (udev_device->syspath == NULL)
11d543c1
KS
669 return -ENOMEM;
670 udev_device->devpath = &udev_device->syspath[strlen(udev_get_sys_path(udev_device->udev))];
8753fadf
KS
671 pos = strrchr(udev_device->syspath, '/');
672 if (pos == NULL)
673 return -EINVAL;
674 udev_device->sysname = &pos[1];
11d543c1
KS
675 return 0;
676}
677
678int device_set_subsystem(struct udev_device *udev_device, const char *subsystem)
679{
680 udev_device->subsystem = strdup(subsystem);
681 if (udev_device->subsystem == NULL)
682 return -1;
683 return 0;
684}
685
99214844 686int device_set_devnode(struct udev_device *udev_device, const char *devnode)
11d543c1 687{
99214844
KS
688 udev_device->devnode = strdup(devnode);
689 if (udev_device->devnode == NULL)
11d543c1
KS
690 return -ENOMEM;
691 return 0;
692}
693
694int device_add_devlink(struct udev_device *udev_device, const char *devlink)
695{
0de33a61 696 if (list_entry_add(udev_device->udev, &udev_device->devlink_list, devlink, NULL, 1, 0) == NULL)
11d543c1
KS
697 return -ENOMEM;
698 return 0;
699}
700
0518da3b 701int device_add_property(struct udev_device *udev_device, const char *key, const char *value)
11d543c1 702{
0de33a61 703 if (list_entry_add(udev_device->udev, &udev_device->properties_list, key, value, 1, 0) == NULL)
11d543c1
KS
704 return -ENOMEM;
705 return 0;
706}
c4f5f942 707
0518da3b
KS
708int device_add_property_from_string(struct udev_device *udev_device, const char *property)
709{
710 char name[UTIL_PATH_SIZE];
711 char *val;
712
713 strncpy(name, property, sizeof(name));
714 val = strchr(name, '=');
715 if (val == NULL)
716 return -1;
717 val[0] = '\0';
718 val = &val[1];
719 if (val[0] == '\0')
720 val = NULL;
721 device_add_property(udev_device, name, val);
722 return 0;
723}
724
c4f5f942
KS
725int device_set_action(struct udev_device *udev_device, const char *action)
726{
727 udev_device->action = strdup(action);
728 if (udev_device->action == NULL)
729 return -ENOMEM;
730 return 0;
731}
732
733int device_set_driver(struct udev_device *udev_device, const char *driver)
734{
735 udev_device->driver = strdup(driver);
736 if (udev_device->driver == NULL)
737 return -ENOMEM;
738 return 0;
739}
740
741const char *device_get_devpath_old(struct udev_device *udev_device)
742{
c4f5f942
KS
743 return udev_device->devpath_old;
744}
745
746int device_set_devpath_old(struct udev_device *udev_device, const char *devpath_old)
747{
748 udev_device->devpath_old = strdup(devpath_old);
749 if (udev_device->devpath_old == NULL)
750 return -ENOMEM;
751 return 0;
752}
753
754const char *device_get_physdevpath(struct udev_device *udev_device)
755{
c4f5f942
KS
756 return udev_device->physdevpath;
757}
758
759int device_set_physdevpath(struct udev_device *udev_device, const char *physdevpath)
760{
761 udev_device->physdevpath = strdup(physdevpath);
762 if (udev_device->physdevpath == NULL)
763 return -ENOMEM;
764 return 0;
765}
766
767int device_get_timeout(struct udev_device *udev_device)
768{
c4f5f942
KS
769 return udev_device->timeout;
770}
771
772int device_set_timeout(struct udev_device *udev_device, int timeout)
773{
774 udev_device->timeout = timeout;
775 return 0;
776}
99214844
KS
777int device_get_event_timeout(struct udev_device *udev_device)
778{
779 if (!udev_device->info_loaded)
780 device_load_info(udev_device);
781 return udev_device->event_timeout;
782}
783
784int device_set_event_timeout(struct udev_device *udev_device, int event_timeout)
785{
786 udev_device->event_timeout = event_timeout;
787 return 0;
788}
c4f5f942 789
37372bbc
KS
790int device_set_seqnum(struct udev_device *udev_device, unsigned long long int seqnum)
791{
792 udev_device->seqnum = seqnum;
793 return 0;
794}
795
c4f5f942
KS
796int device_set_devnum(struct udev_device *udev_device, dev_t devnum)
797{
798 udev_device->devnum = devnum;
799 return 0;
800}
6bd1c78a
KS
801
802int device_get_num_fake_partitions(struct udev_device *udev_device)
803{
99214844
KS
804 if (!udev_device->info_loaded)
805 device_load_info(udev_device);
6bd1c78a
KS
806 return udev_device->num_fake_partitions;
807}
808
809int device_set_num_fake_partitions(struct udev_device *udev_device, int num)
810{
811 udev_device->num_fake_partitions = num;
e88a82b5 812 return 0;
6bd1c78a
KS
813}
814
e88a82b5 815int device_get_devlink_priority(struct udev_device *udev_device)
6bd1c78a 816{
99214844
KS
817 if (!udev_device->info_loaded)
818 device_load_info(udev_device);
e88a82b5 819 return udev_device->devlink_priority;
6bd1c78a
KS
820}
821
e88a82b5 822int device_set_devlink_priority(struct udev_device *udev_device, int prio)
6bd1c78a 823{
e88a82b5
KS
824 udev_device->devlink_priority = prio;
825 return 0;
6bd1c78a
KS
826}
827
828int device_get_ignore_remove(struct udev_device *udev_device)
829{
99214844
KS
830 if (!udev_device->info_loaded)
831 device_load_info(udev_device);
6bd1c78a
KS
832 return udev_device->ignore_remove;
833}
834
835int device_set_ignore_remove(struct udev_device *udev_device, int ignore)
836{
e88a82b5
KS
837 udev_device->ignore_remove = ignore;
838 return 0;
6bd1c78a 839}
e88a82b5 840