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