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