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