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