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