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