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