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