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