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