• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***
2   This file is part of systemd.
3 
4   Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
5 
6   systemd is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as published by
8   the Free Software Foundation; either version 2.1 of the License, or
9   (at your option) any later version.
10 
11   systemd is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   Lesser General Public License for more details.
15 
16   You should have received a copy of the GNU Lesser General Public License
17   along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <stddef.h>
23 #include <unistd.h>
24 #include <stdbool.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <dirent.h>
28 #include <fcntl.h>
29 #include <ctype.h>
30 #include <net/if.h>
31 #include <sys/stat.h>
32 #include <sys/ioctl.h>
33 #include <sys/socket.h>
34 #include <linux/sockios.h>
35 #include <sys/sysmacros.h>
36 
37 #include "libudev.h"
38 #include "libudev-private.h"
39 
40 static int udev_device_read_uevent_file(struct udev_device *udev_device);
41 static int udev_device_set_devnode(struct udev_device *udev_device, const char *devnode);
42 static struct udev_list_entry *udev_device_add_property_internal(struct udev_device *udev_device, const char *key, const char *value);
43 
44 /**
45  * SECTION:libudev-device
46  * @short_description: kernel sys devices
47  *
48  * Representation of kernel sys devices. Devices are uniquely identified
49  * by their syspath, every device has exactly one path in the kernel sys
50  * filesystem. Devices usually belong to a kernel subsystem, and have
51  * a unique name inside that subsystem.
52  */
53 
54 /**
55  * udev_device:
56  *
57  * Opaque object representing one kernel sys device.
58  */
59 struct udev_device {
60         struct udev *udev;
61         struct udev_device *parent_device;
62         char *syspath;
63         const char *devpath;
64         char *sysname;
65         const char *sysnum;
66         char *devnode;
67         mode_t devnode_mode;
68         uid_t devnode_uid;
69         gid_t devnode_gid;
70         char *subsystem;
71         char *devtype;
72         char *driver;
73         char *action;
74         char *devpath_old;
75         char *id_filename;
76         char **envp;
77         char *monitor_buf;
78         size_t monitor_buf_len;
79         struct udev_list devlinks_list;
80         struct udev_list properties_list;
81         struct udev_list sysattr_value_list;
82         struct udev_list sysattr_list;
83         struct udev_list tags_list;
84         unsigned long long int seqnum;
85         usec_t usec_initialized;
86         int devlink_priority;
87         int refcount;
88         dev_t devnum;
89         int ifindex;
90         int watch_handle;
91         int maj, min;
92         bool parent_set;
93         bool subsystem_set;
94         bool devtype_set;
95         bool devlinks_uptodate;
96         bool envp_uptodate;
97         bool tags_uptodate;
98         bool driver_set;
99         bool info_loaded;
100         bool db_loaded;
101         bool uevent_loaded;
102         bool is_initialized;
103         bool sysattr_list_read;
104         bool db_persist;
105 };
106 
107 /**
108  * udev_device_get_seqnum:
109  * @udev_device: udev device
110  *
111  * This is only valid if the device was received through a monitor. Devices read from
112  * sys do not have a sequence number.
113  *
114  * Returns: the kernel event sequence number, or 0 if there is no sequence number available.
115  **/
udev_device_get_seqnum(struct udev_device * udev_device)116 _public_ unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device)
117 {
118         if (udev_device == NULL)
119                 return 0;
120         return udev_device->seqnum;
121 }
122 
udev_device_set_seqnum(struct udev_device * udev_device,unsigned long long int seqnum)123 static int udev_device_set_seqnum(struct udev_device *udev_device, unsigned long long int seqnum)
124 {
125         char num[32];
126 
127         udev_device->seqnum = seqnum;
128         snprintf(num, sizeof(num), "%llu", seqnum);
129         udev_device_add_property_internal(udev_device, "SEQNUM", num);
130         return 0;
131 }
132 
udev_device_get_ifindex(struct udev_device * udev_device)133 int udev_device_get_ifindex(struct udev_device *udev_device)
134 {
135         if (!udev_device->info_loaded)
136                 udev_device_read_uevent_file(udev_device);
137         return udev_device->ifindex;
138 }
139 
udev_device_set_ifindex(struct udev_device * udev_device,int ifindex)140 static int udev_device_set_ifindex(struct udev_device *udev_device, int ifindex)
141 {
142         char num[32];
143 
144         udev_device->ifindex = ifindex;
145         snprintf(num, sizeof(num), "%d", ifindex);
146         udev_device_add_property_internal(udev_device, "IFINDEX", num);
147         return 0;
148 }
149 
150 /**
151  * udev_device_get_devnum:
152  * @udev_device: udev device
153  *
154  * Get the device major/minor number.
155  *
156  * Returns: the dev_t number.
157  **/
udev_device_get_devnum(struct udev_device * udev_device)158 _public_ dev_t udev_device_get_devnum(struct udev_device *udev_device)
159 {
160         if (udev_device == NULL)
161                 return makedev(0, 0);
162         if (!udev_device->info_loaded)
163                 udev_device_read_uevent_file(udev_device);
164         return udev_device->devnum;
165 }
166 
udev_device_set_devnum(struct udev_device * udev_device,dev_t devnum)167 static int udev_device_set_devnum(struct udev_device *udev_device, dev_t devnum)
168 {
169         char num[32];
170 
171         udev_device->devnum = devnum;
172 
173         snprintf(num, sizeof(num), "%u", major(devnum));
174         udev_device_add_property_internal(udev_device, "MAJOR", num);
175         snprintf(num, sizeof(num), "%u", minor(devnum));
176         udev_device_add_property_internal(udev_device, "MINOR", num);
177         return 0;
178 }
179 
udev_device_get_devpath_old(struct udev_device * udev_device)180 const char *udev_device_get_devpath_old(struct udev_device *udev_device)
181 {
182         return udev_device->devpath_old;
183 }
184 
udev_device_set_devpath_old(struct udev_device * udev_device,const char * devpath_old)185 static int udev_device_set_devpath_old(struct udev_device *udev_device, const char *devpath_old)
186 {
187         const char *pos;
188 
189         free(udev_device->devpath_old);
190         udev_device->devpath_old = strdup(devpath_old);
191         if (udev_device->devpath_old == NULL)
192                 return -ENOMEM;
193         udev_device_add_property_internal(udev_device, "DEVPATH_OLD", udev_device->devpath_old);
194 
195         pos = strrchr(udev_device->devpath_old, '/');
196         if (pos == NULL)
197                 return -EINVAL;
198         return 0;
199 }
200 
201 /**
202  * udev_device_get_driver:
203  * @udev_device: udev device
204  *
205  * Get the kernel driver name.
206  *
207  * Returns: the driver name string, or #NULL if there is no driver attached.
208  **/
udev_device_get_driver(struct udev_device * udev_device)209 _public_ const char *udev_device_get_driver(struct udev_device *udev_device)
210 {
211         char driver[UTIL_NAME_SIZE];
212 
213         if (udev_device == NULL)
214                 return NULL;
215         if (!udev_device->driver_set) {
216                 udev_device->driver_set = true;
217                 if (util_get_sys_core_link_value(udev_device->udev, "driver", udev_device->syspath, driver, sizeof(driver)) > 0)
218                         udev_device->driver = strdup(driver);
219         }
220         return udev_device->driver;
221 }
222 
udev_device_set_driver(struct udev_device * udev_device,const char * driver)223 static int udev_device_set_driver(struct udev_device *udev_device, const char *driver)
224 {
225         free(udev_device->driver);
226         udev_device->driver = strdup(driver);
227         if (udev_device->driver == NULL)
228                 return -ENOMEM;
229         udev_device->driver_set = true;
230         udev_device_add_property_internal(udev_device, "DRIVER", udev_device->driver);
231         return 0;
232 }
233 
234 /**
235  * udev_device_get_devtype:
236  * @udev_device: udev device
237  *
238  * Retrieve the devtype string of the udev device.
239  *
240  * Returns: the devtype name of the udev device, or #NULL if it can not be determined
241  **/
udev_device_get_devtype(struct udev_device * udev_device)242 _public_ const char *udev_device_get_devtype(struct udev_device *udev_device)
243 {
244         if (udev_device == NULL)
245                 return NULL;
246         if (!udev_device->devtype_set) {
247                 udev_device->devtype_set = true;
248                 udev_device_read_uevent_file(udev_device);
249         }
250         return udev_device->devtype;
251 }
252 
udev_device_set_devtype(struct udev_device * udev_device,const char * devtype)253 static int udev_device_set_devtype(struct udev_device *udev_device, const char *devtype)
254 {
255         free(udev_device->devtype);
256         udev_device->devtype = strdup(devtype);
257         if (udev_device->devtype == NULL)
258                 return -ENOMEM;
259         udev_device->devtype_set = true;
260         udev_device_add_property_internal(udev_device, "DEVTYPE", udev_device->devtype);
261         return 0;
262 }
263 
udev_device_set_subsystem(struct udev_device * udev_device,const char * subsystem)264 static int udev_device_set_subsystem(struct udev_device *udev_device, const char *subsystem)
265 {
266         free(udev_device->subsystem);
267         udev_device->subsystem = strdup(subsystem);
268         if (udev_device->subsystem == NULL)
269                 return -ENOMEM;
270         udev_device->subsystem_set = true;
271         udev_device_add_property_internal(udev_device, "SUBSYSTEM", udev_device->subsystem);
272         return 0;
273 }
274 
275 /**
276  * udev_device_get_subsystem:
277  * @udev_device: udev device
278  *
279  * Retrieve the subsystem string of the udev device. The string does not
280  * contain any "/".
281  *
282  * Returns: the subsystem name of the udev device, or #NULL if it can not be determined
283  **/
udev_device_get_subsystem(struct udev_device * udev_device)284 _public_ const char *udev_device_get_subsystem(struct udev_device *udev_device)
285 {
286         char subsystem[UTIL_NAME_SIZE];
287 
288         if (udev_device == NULL)
289                 return NULL;
290         if (!udev_device->subsystem_set) {
291                 udev_device->subsystem_set = true;
292                 /* read "subsystem" link */
293                 if (util_get_sys_core_link_value(udev_device->udev, "subsystem", udev_device->syspath, subsystem, sizeof(subsystem)) > 0) {
294                         udev_device_set_subsystem(udev_device, subsystem);
295                         return udev_device->subsystem;
296                 }
297                 /* implicit names */
298                 if (startswith(udev_device->devpath, "/module/")) {
299                         udev_device_set_subsystem(udev_device, "module");
300                         return udev_device->subsystem;
301                 }
302                 if (strstr(udev_device->devpath, "/drivers/") != NULL) {
303                         udev_device_set_subsystem(udev_device, "drivers");
304                         return udev_device->subsystem;
305                 }
306                 if (startswith(udev_device->devpath, "/subsystem/") ||
307                     startswith(udev_device->devpath, "/class/") ||
308                     startswith(udev_device->devpath, "/bus/")) {
309                         udev_device_set_subsystem(udev_device, "subsystem");
310                         return udev_device->subsystem;
311                 }
312         }
313         return udev_device->subsystem;
314 }
315 
udev_device_get_devnode_mode(struct udev_device * udev_device)316 mode_t udev_device_get_devnode_mode(struct udev_device *udev_device)
317 {
318         if (!udev_device->info_loaded)
319                 udev_device_read_uevent_file(udev_device);
320         return udev_device->devnode_mode;
321 }
322 
udev_device_set_devnode_mode(struct udev_device * udev_device,mode_t mode)323 static int udev_device_set_devnode_mode(struct udev_device *udev_device, mode_t mode)
324 {
325         char num[32];
326 
327         udev_device->devnode_mode = mode;
328         snprintf(num, sizeof(num), "%#o", mode);
329         udev_device_add_property_internal(udev_device, "DEVMODE", num);
330         return 0;
331 }
332 
udev_device_get_devnode_uid(struct udev_device * udev_device)333 uid_t udev_device_get_devnode_uid(struct udev_device *udev_device)
334 {
335         if (!udev_device->info_loaded)
336                 udev_device_read_uevent_file(udev_device);
337         return udev_device->devnode_uid;
338 }
339 
udev_device_set_devnode_uid(struct udev_device * udev_device,uid_t uid)340 static int udev_device_set_devnode_uid(struct udev_device *udev_device, uid_t uid)
341 {
342         char num[32];
343 
344         udev_device->devnode_uid = uid;
345         snprintf(num, sizeof(num), "%u", uid);
346         udev_device_add_property_internal(udev_device, "DEVUID", num);
347         return 0;
348 }
349 
udev_device_get_devnode_gid(struct udev_device * udev_device)350 gid_t udev_device_get_devnode_gid(struct udev_device *udev_device)
351 {
352         if (!udev_device->info_loaded)
353                 udev_device_read_uevent_file(udev_device);
354         return udev_device->devnode_gid;
355 }
356 
udev_device_set_devnode_gid(struct udev_device * udev_device,gid_t gid)357 static int udev_device_set_devnode_gid(struct udev_device *udev_device, gid_t gid)
358 {
359         char num[32];
360 
361         udev_device->devnode_gid = gid;
362         snprintf(num, sizeof(num), "%u", gid);
363         udev_device_add_property_internal(udev_device, "DEVGID", num);
364         return 0;
365 }
366 
udev_device_add_property_internal(struct udev_device * udev_device,const char * key,const char * value)367 static struct udev_list_entry *udev_device_add_property_internal(struct udev_device *udev_device, const char *key, const char *value)
368 {
369         udev_device->envp_uptodate = false;
370         if (value == NULL) {
371                 struct udev_list_entry *list_entry;
372 
373                 list_entry = udev_device_get_properties_list_entry(udev_device);
374                 list_entry = udev_list_entry_get_by_name(list_entry, key);
375                 if (list_entry != NULL)
376                         udev_list_entry_delete(list_entry);
377                 return NULL;
378         }
379         return udev_list_entry_add(&udev_device->properties_list, key, value);
380 }
381 
382 
udev_device_add_property(struct udev_device * udev_device,const char * key,const char * value)383 int udev_device_add_property(struct udev_device *udev_device, const char *key, const char *value)
384 {
385         struct udev_list_entry *property;
386 
387         property = udev_device_add_property_internal(udev_device, key, value);
388 
389         /* store in db, skip private keys */
390         if (key[0] != '.')
391                 udev_list_entry_set_num(property, true);
392 
393         return 0;
394 }
395 
udev_device_add_property_from_string(struct udev_device * udev_device,const char * property)396 static struct udev_list_entry *udev_device_add_property_from_string(struct udev_device *udev_device, const char *property)
397 {
398         char name[UTIL_LINE_SIZE];
399         char *val;
400 
401         strscpy(name, sizeof(name), property);
402         val = strchr(name, '=');
403         if (val == NULL)
404                 return NULL;
405         val[0] = '\0';
406         val = &val[1];
407         if (val[0] == '\0')
408                 val = NULL;
409         return udev_device_add_property_internal(udev_device, name, val);
410 }
411 
udev_device_set_syspath(struct udev_device * udev_device,const char * syspath)412 static int udev_device_set_syspath(struct udev_device *udev_device, const char *syspath)
413 {
414         const char *pos;
415         size_t len;
416 
417         free(udev_device->syspath);
418         udev_device->syspath = strdup(syspath);
419         if (udev_device->syspath ==  NULL)
420                 return -ENOMEM;
421         udev_device->devpath = udev_device->syspath + strlen("/sys");
422         udev_device_add_property_internal(udev_device, "DEVPATH", udev_device->devpath);
423 
424         pos = strrchr(udev_device->syspath, '/');
425         if (pos == NULL)
426                 return -EINVAL;
427         udev_device->sysname = strdup(&pos[1]);
428         if (udev_device->sysname == NULL)
429                 return -ENOMEM;
430 
431         /* some devices have '!' in their name, change that to '/' */
432         len = 0;
433         while (udev_device->sysname[len] != '\0') {
434                 if (udev_device->sysname[len] == '!')
435                         udev_device->sysname[len] = '/';
436                 len++;
437         }
438 
439         /* trailing number */
440         while (len > 0 && isdigit(udev_device->sysname[--len]))
441                 udev_device->sysnum = &udev_device->sysname[len];
442 
443         /* sysname is completely numeric */
444         if (len == 0)
445                 udev_device->sysnum = NULL;
446 
447         return 0;
448 }
449 
udev_device_set_usec_initialized(struct udev_device * udev_device,usec_t usec_initialized)450 static void udev_device_set_usec_initialized(struct udev_device *udev_device, usec_t usec_initialized)
451 {
452         char num[DECIMAL_STR_MAX(usec_t)];
453 
454         udev_device->usec_initialized = usec_initialized;
455         snprintf(num, sizeof(num), USEC_FMT, usec_initialized);
456         udev_device_add_property_internal(udev_device, "USEC_INITIALIZED", num);
457 }
458 
udev_device_ensure_usec_initialized(struct udev_device * udev_device,struct udev_device * old_device)459 void udev_device_ensure_usec_initialized(struct udev_device *udev_device, struct udev_device *old_device)
460 {
461         if (old_device && old_device->usec_initialized != 0)
462                 udev_device_set_usec_initialized(udev_device, old_device->usec_initialized);
463         else
464                 udev_device_set_usec_initialized(udev_device, now(CLOCK_MONOTONIC));
465 }
466 
udev_device_set_action(struct udev_device * udev_device,const char * action)467 static int udev_device_set_action(struct udev_device *udev_device, const char *action)
468 {
469         free(udev_device->action);
470         udev_device->action = strdup(action);
471         if (udev_device->action == NULL)
472                 return -ENOMEM;
473         udev_device_add_property_internal(udev_device, "ACTION", udev_device->action);
474         return 0;
475 }
476 
477 /*
478  * parse property string, and if needed, update internal values accordingly
479  *
480  * udev_device_add_property_from_string_parse_finish() needs to be
481  * called after adding properties, and its return value checked
482  *
483  * udev_device_set_info_loaded() needs to be set, to avoid trying
484  * to use a device without a DEVPATH set
485  */
udev_device_add_property_from_string_parse(struct udev_device * udev_device,const char * property)486 static void udev_device_add_property_from_string_parse(struct udev_device *udev_device, const char *property)
487 {
488         if (startswith(property, "DEVPATH=")) {
489                 char path[UTIL_PATH_SIZE];
490 
491                 strscpyl(path, sizeof(path), "/sys", &property[8], NULL);
492                 udev_device_set_syspath(udev_device, path);
493         } else if (startswith(property, "SUBSYSTEM=")) {
494                 udev_device_set_subsystem(udev_device, &property[10]);
495         } else if (startswith(property, "DEVTYPE=")) {
496                 udev_device_set_devtype(udev_device, &property[8]);
497         } else if (startswith(property, "DEVNAME=")) {
498                 udev_device_set_devnode(udev_device, &property[8]);
499         } else if (startswith(property, "DEVLINKS=")) {
500                 char devlinks[UTIL_PATH_SIZE];
501                 char *slink;
502                 char *next;
503 
504                 strscpy(devlinks, sizeof(devlinks), &property[9]);
505                 slink = devlinks;
506                 next = strchr(slink, ' ');
507                 while (next != NULL) {
508                         next[0] = '\0';
509                         udev_device_add_devlink(udev_device, slink);
510                         slink = &next[1];
511                         next = strchr(slink, ' ');
512                 }
513                 if (slink[0] != '\0')
514                         udev_device_add_devlink(udev_device, slink);
515         } else if (startswith(property, "TAGS=")) {
516                 char tags[UTIL_PATH_SIZE];
517                 char *next;
518 
519                 strscpy(tags, sizeof(tags), &property[5]);
520                 next = strchr(tags, ':');
521                 if (next != NULL) {
522                         next++;
523                         while (next[0] != '\0') {
524                                 char *tag;
525 
526                                 tag = next;
527                                 next = strchr(tag, ':');
528                                 if (next == NULL)
529                                         break;
530                                 next[0] = '\0';
531                                 next++;
532                                 udev_device_add_tag(udev_device, tag);
533                         }
534                 }
535         } else if (startswith(property, "USEC_INITIALIZED=")) {
536                 udev_device_set_usec_initialized(udev_device, strtoull(&property[19], NULL, 10));
537         } else if (startswith(property, "DRIVER=")) {
538                 udev_device_set_driver(udev_device, &property[7]);
539         } else if (startswith(property, "ACTION=")) {
540                 udev_device_set_action(udev_device, &property[7]);
541         } else if (startswith(property, "MAJOR=")) {
542                 udev_device->maj = strtoull(&property[6], NULL, 10);
543         } else if (startswith(property, "MINOR=")) {
544                 udev_device->min = strtoull(&property[6], NULL, 10);
545         } else if (startswith(property, "DEVPATH_OLD=")) {
546                 udev_device_set_devpath_old(udev_device, &property[12]);
547         } else if (startswith(property, "SEQNUM=")) {
548                 udev_device_set_seqnum(udev_device, strtoull(&property[7], NULL, 10));
549         } else if (startswith(property, "IFINDEX=")) {
550                 udev_device_set_ifindex(udev_device, strtoull(&property[8], NULL, 10));
551         } else if (startswith(property, "DEVMODE=")) {
552                 udev_device_set_devnode_mode(udev_device, strtoul(&property[8], NULL, 8));
553         } else if (startswith(property, "DEVUID=")) {
554                 udev_device_set_devnode_uid(udev_device, strtoul(&property[7], NULL, 10));
555         } else if (startswith(property, "DEVGID=")) {
556                 udev_device_set_devnode_gid(udev_device, strtoul(&property[7], NULL, 10));
557         } else {
558                 udev_device_add_property_from_string(udev_device, property);
559         }
560 }
561 
udev_device_add_property_from_string_parse_finish(struct udev_device * udev_device)562 static int udev_device_add_property_from_string_parse_finish(struct udev_device *udev_device)
563 {
564         if (udev_device->maj > 0)
565                 udev_device_set_devnum(udev_device, makedev(udev_device->maj, udev_device->min));
566         udev_device->maj = 0;
567         udev_device->min = 0;
568 
569         if (udev_device->devpath == NULL || udev_device->subsystem == NULL)
570                 return -EINVAL;
571         return 0;
572 }
573 
574 /**
575  * udev_device_get_property_value:
576  * @udev_device: udev device
577  * @key: property name
578  *
579  * Get the value of a given property.
580  *
581  * Returns: the property string, or #NULL if there is no such property.
582  **/
udev_device_get_property_value(struct udev_device * udev_device,const char * key)583 _public_ const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key)
584 {
585         struct udev_list_entry *list_entry;
586 
587         if (udev_device == NULL)
588                 return NULL;
589         if (key == NULL)
590                 return NULL;
591 
592         list_entry = udev_device_get_properties_list_entry(udev_device);
593         list_entry = udev_list_entry_get_by_name(list_entry, key);
594         return udev_list_entry_get_value(list_entry);
595 }
596 
udev_device_read_db(struct udev_device * udev_device)597 int udev_device_read_db(struct udev_device *udev_device)
598 {
599         char filename[UTIL_PATH_SIZE];
600         char line[UTIL_LINE_SIZE];
601         const char *id;
602         FILE *f;
603 
604         if (udev_device->db_loaded)
605                 return 0;
606 
607         udev_device->db_loaded = true;
608 
609         id = udev_device_get_id_filename(udev_device);
610         if (id == NULL)
611                 return -1;
612 
613         strscpyl(filename, sizeof(filename), UDEV_ROOT_RUN "/udev/data/", id, NULL);
614 
615         f = fopen(filename, "re");
616         if (f == NULL)
617                 return log_debug_errno(errno, "no db file to read %s: %m", filename);
618 
619         /* devices with a database entry are initialized */
620         udev_device->is_initialized = true;
621 
622         while (fgets(line, sizeof(line), f)) {
623                 ssize_t len;
624                 const char *val;
625                 struct udev_list_entry *entry;
626 
627                 len = strlen(line);
628                 if (len < 4)
629                         break;
630                 line[len-1] = '\0';
631                 val = &line[2];
632                 switch(line[0]) {
633                 case 'S':
634                         strscpyl(filename, sizeof(filename), "/dev/", val, NULL);
635                         udev_device_add_devlink(udev_device, filename);
636                         break;
637                 case 'L':
638                         udev_device_set_devlink_priority(udev_device, atoi(val));
639                         break;
640                 case 'E':
641                         entry = udev_device_add_property_from_string(udev_device, val);
642                         udev_list_entry_set_num(entry, true);
643                         break;
644                 case 'G':
645                         udev_device_add_tag(udev_device, val);
646                         break;
647                 case 'W':
648                         udev_device_set_watch_handle(udev_device, atoi(val));
649                         break;
650                 case 'I':
651                         udev_device_set_usec_initialized(udev_device, strtoull(val, NULL, 10));
652                         break;
653                 }
654         }
655         fclose(f);
656 
657         log_trace("device %p filled with db file data", udev_device);
658         return 0;
659 }
660 
udev_device_read_uevent_file(struct udev_device * udev_device)661 static int udev_device_read_uevent_file(struct udev_device *udev_device)
662 {
663         char filename[UTIL_PATH_SIZE];
664         FILE *f;
665         char line[UTIL_LINE_SIZE];
666         int maj = 0;
667         int min = 0;
668 
669         if (udev_device->uevent_loaded)
670                 return 0;
671 
672         strscpyl(filename, sizeof(filename), udev_device->syspath, "/uevent", NULL);
673         f = fopen(filename, "re");
674         if (f == NULL)
675                 return -errno;
676         udev_device->uevent_loaded = true;
677 
678         while (fgets(line, sizeof(line), f)) {
679                 char *pos;
680 
681                 pos = strchr(line, '\n');
682                 if (pos == NULL)
683                         continue;
684                 pos[0] = '\0';
685 
686                 if (startswith(line, "DEVTYPE=")) {
687                         udev_device_set_devtype(udev_device, &line[8]);
688                         continue;
689                 }
690                 if (startswith(line, "IFINDEX=")) {
691                         udev_device_set_ifindex(udev_device, strtoull(&line[8], NULL, 10));
692                         continue;
693                 }
694                 if (startswith(line, "DEVNAME=")) {
695                         udev_device_set_devnode(udev_device, &line[8]);
696                         continue;
697                 }
698 
699                 if (startswith(line, "MAJOR="))
700                         maj = strtoull(&line[6], NULL, 10);
701                 else if (startswith(line, "MINOR="))
702                         min = strtoull(&line[6], NULL, 10);
703                 else if (startswith(line, "DEVMODE="))
704                         udev_device->devnode_mode = strtoul(&line[8], NULL, 8);
705 
706                 udev_device_add_property_from_string(udev_device, line);
707         }
708 
709         udev_device->devnum = makedev(maj, min);
710         fclose(f);
711         return 0;
712 }
713 
udev_device_set_info_loaded(struct udev_device * device)714 void udev_device_set_info_loaded(struct udev_device *device)
715 {
716         device->info_loaded = true;
717 }
718 
udev_device_new(struct udev * udev)719 static struct udev_device *udev_device_new(struct udev *udev)
720 {
721         struct udev_device *udev_device;
722 
723         if (udev == NULL) {
724                 errno = EINVAL;
725                 return NULL;
726         }
727 
728         udev_device = new0(struct udev_device, 1);
729         if (udev_device == NULL) {
730                 errno = ENOMEM;
731                 return NULL;
732         }
733         udev_device->refcount = 1;
734         udev_device->udev = udev;
735         udev_list_init(udev, &udev_device->devlinks_list, true);
736         udev_list_init(udev, &udev_device->properties_list, true);
737         udev_list_init(udev, &udev_device->sysattr_value_list, true);
738         udev_list_init(udev, &udev_device->sysattr_list, false);
739         udev_list_init(udev, &udev_device->tags_list, true);
740         udev_device->watch_handle = -1;
741 
742         return udev_device;
743 }
744 
745 /**
746  * udev_device_new_from_syspath:
747  * @udev: udev library context
748  * @syspath: sys device path including sys directory
749  *
750  * Create new udev device, and fill in information from the sys
751  * device and the udev database entry. The syspath is the absolute
752  * path to the device, including the sys mount point.
753  *
754  * The initial refcount is 1, and needs to be decremented to
755  * release the resources of the udev device.
756  *
757  * Returns: a new udev device, or #NULL, if it does not exist
758  **/
udev_device_new_from_syspath(struct udev * udev,const char * syspath)759 _public_ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath)
760 {
761         const char *subdir;
762         char path[UTIL_PATH_SIZE];
763         char *pos;
764         struct stat statbuf;
765         struct udev_device *udev_device;
766 
767         if (udev == NULL) {
768                 errno = EINVAL;
769                 return NULL;
770         }
771 
772         if (syspath == NULL) {
773                 errno = EINVAL;
774                 return NULL;
775         }
776 
777         /* path starts in sys */
778         if (!startswith(syspath, "/sys")) {
779                 log_debug("not in sys :%s", syspath);
780                 errno = EINVAL;
781                 return NULL;
782         }
783 
784         /* path is not a root directory */
785         subdir = syspath + strlen("/sys");
786         pos = strrchr(subdir, '/');
787         if (pos == NULL || pos[1] == '\0' || pos < &subdir[2]) {
788                 errno = EINVAL;
789                 return NULL;
790         }
791 
792         /* resolve possible symlink to real path */
793         strscpy(path, sizeof(path), syspath);
794         util_resolve_sys_link(udev, path, sizeof(path));
795 
796         if (startswith(path + strlen("/sys"), "/devices/")) {
797                 char file[UTIL_PATH_SIZE];
798 
799                 /* all "devices" require a "uevent" file */
800                 strscpyl(file, sizeof(file), path, "/uevent", NULL);
801                 if (stat(file, &statbuf) != 0)
802                         return NULL;
803         } else {
804                 /* everything else just needs to be a directory */
805                 if (stat(path, &statbuf) != 0)
806                         return NULL;
807 
808                 if (!S_ISDIR(statbuf.st_mode)) {
809                         errno = EISDIR;
810                         return NULL;
811                 }
812         }
813 
814         udev_device = udev_device_new(udev);
815         if (udev_device == NULL)
816                 return NULL;
817 
818         udev_device_set_syspath(udev_device, path);
819         log_trace("device %p has devpath '%s'", udev_device, udev_device_get_devpath(udev_device));
820 
821         return udev_device;
822 }
823 
824 /**
825  * udev_device_new_from_devnum:
826  * @udev: udev library context
827  * @type: char or block device
828  * @devnum: device major/minor number
829  *
830  * Create new udev device, and fill in information from the sys
831  * device and the udev database entry. The device is looked-up
832  * by its major/minor number and type. Character and block device
833  * numbers are not unique across the two types.
834  *
835  * The initial refcount is 1, and needs to be decremented to
836  * release the resources of the udev device.
837  *
838  * Returns: a new udev device, or #NULL, if it does not exist
839  **/
udev_device_new_from_devnum(struct udev * udev,char type,dev_t devnum)840 _public_ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum)
841 {
842         char path[UTIL_PATH_SIZE];
843         const char *type_str;
844 
845         if (type == 'b')
846                 type_str = "block";
847         else if (type == 'c')
848                 type_str = "char";
849         else {
850                 errno = EINVAL;
851                 return NULL;
852         }
853 
854         /* use /sys/dev/{block,char}/<maj>:<min> link */
855         snprintf(path, sizeof(path), "/sys/dev/%s/%u:%u",
856                  type_str, major(devnum), minor(devnum));
857         return udev_device_new_from_syspath(udev, path);
858 }
859 
860 /**
861  * udev_device_new_from_device_id:
862  * @udev: udev library context
863  * @id: text string identifying a kernel device
864  *
865  * Create new udev device, and fill in information from the sys
866  * device and the udev database entry. The device is looked-up
867  * by a special string:
868  *   b8:2          - block device major:minor
869  *   c128:1        - char device major:minor
870  *   n3            - network device ifindex
871  *   +sound:card29 - kernel driver core subsystem:device name
872  *
873  * The initial refcount is 1, and needs to be decremented to
874  * release the resources of the udev device.
875  *
876  * Returns: a new udev device, or #NULL, if it does not exist
877  **/
udev_device_new_from_device_id(struct udev * udev,const char * id)878 _public_ struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id)
879 {
880         char type;
881         int maj, min;
882         char subsys[UTIL_PATH_SIZE];
883         char *sysname;
884 
885         switch(id[0]) {
886         case 'b':
887         case 'c':
888                 if (sscanf(id, "%c%i:%i", &type, &maj, &min) != 3)
889                         return NULL;
890                 return udev_device_new_from_devnum(udev, type, makedev(maj, min));
891         case 'n': {
892                 int sk;
893                 struct ifreq ifr;
894                 struct udev_device *dev;
895                 int ifindex;
896 
897                 ifindex = strtoul(&id[1], NULL, 10);
898                 if (ifindex <= 0) {
899                         errno = EINVAL;
900                         return NULL;
901                 }
902 
903                 sk = socket(PF_INET, SOCK_DGRAM, 0);
904                 if (sk < 0)
905                         return NULL;
906                 memzero(&ifr, sizeof(struct ifreq));
907                 ifr.ifr_ifindex = ifindex;
908                 if (ioctl(sk, SIOCGIFNAME, &ifr) != 0) {
909                         close(sk);
910                         return NULL;
911                 }
912                 close(sk);
913 
914                 dev = udev_device_new_from_subsystem_sysname(udev, "net", ifr.ifr_name);
915                 if (dev == NULL)
916                         return NULL;
917                 if (udev_device_get_ifindex(dev) == ifindex)
918                         return dev;
919 
920                 /* this is racy, so we may end up with the wrong device */
921                 udev_device_unref(dev);
922                 errno = ENODEV;
923                 return NULL;
924         }
925         case '+':
926                 strscpy(subsys, sizeof(subsys), &id[1]);
927                 sysname = strchr(subsys, ':');
928                 if (sysname == NULL) {
929                         errno = EINVAL;
930                         return NULL;
931                 }
932                 sysname[0] = '\0';
933                 sysname = &sysname[1];
934                 return udev_device_new_from_subsystem_sysname(udev, subsys, sysname);
935         default:
936                 errno = EINVAL;
937                 return NULL;
938         }
939 }
940 
941 /**
942  * udev_device_new_from_subsystem_sysname:
943  * @udev: udev library context
944  * @subsystem: the subsystem of the device
945  * @sysname: the name of the device
946  *
947  * Create new udev device, and fill in information from the sys device
948  * and the udev database entry. The device is looked up by the subsystem
949  * and name string of the device, like "mem" / "zero", or "block" / "sda".
950  *
951  * The initial refcount is 1, and needs to be decremented to
952  * release the resources of the udev device.
953  *
954  * Returns: a new udev device, or #NULL, if it does not exist
955  **/
udev_device_new_from_subsystem_sysname(struct udev * udev,const char * subsystem,const char * sysname)956 _public_ struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname)
957 {
958         char path[UTIL_PATH_SIZE];
959         struct stat statbuf;
960 
961         if (streq(subsystem, "subsystem")) {
962                 strscpyl(path, sizeof(path), "/sys/subsystem/", sysname, NULL);
963                 if (stat(path, &statbuf) == 0)
964                         goto found;
965 
966                 strscpyl(path, sizeof(path), "/sys/bus/", sysname, NULL);
967                 if (stat(path, &statbuf) == 0)
968                         goto found;
969 
970                 strscpyl(path, sizeof(path), "/sys/class/", sysname, NULL);
971                 if (stat(path, &statbuf) == 0)
972                         goto found;
973                 goto out;
974         }
975 
976         if (streq(subsystem, "module")) {
977                 strscpyl(path, sizeof(path), "/sys/module/", sysname, NULL);
978                 if (stat(path, &statbuf) == 0)
979                         goto found;
980                 goto out;
981         }
982 
983         if (streq(subsystem, "drivers")) {
984                 char subsys[UTIL_NAME_SIZE];
985                 char *driver;
986 
987                 strscpy(subsys, sizeof(subsys), sysname);
988                 driver = strchr(subsys, ':');
989                 if (driver != NULL) {
990                         driver[0] = '\0';
991                         driver = &driver[1];
992 
993                         strscpyl(path, sizeof(path), "/sys/subsystem/", subsys, "/drivers/", driver, NULL);
994                         if (stat(path, &statbuf) == 0)
995                                 goto found;
996 
997                         strscpyl(path, sizeof(path), "/sys/bus/", subsys, "/drivers/", driver, NULL);
998                         if (stat(path, &statbuf) == 0)
999                                 goto found;
1000                 } else
1001                         errno = EINVAL;
1002 
1003                 goto out;
1004         }
1005 
1006         strscpyl(path, sizeof(path), "/sys/subsystem/", subsystem, "/devices/", sysname, NULL);
1007         if (stat(path, &statbuf) == 0)
1008                 goto found;
1009 
1010         strscpyl(path, sizeof(path), "/sys/bus/", subsystem, "/devices/", sysname, NULL);
1011         if (stat(path, &statbuf) == 0)
1012                 goto found;
1013 
1014         strscpyl(path, sizeof(path), "/sys/class/", subsystem, "/", sysname, NULL);
1015         if (stat(path, &statbuf) == 0)
1016                 goto found;
1017 out:
1018         return NULL;
1019 found:
1020         return udev_device_new_from_syspath(udev, path);
1021 }
1022 
1023 /**
1024  * udev_device_new_from_environment
1025  * @udev: udev library context
1026  *
1027  * Create new udev device, and fill in information from the
1028  * current process environment. This only works reliable if
1029  * the process is called from a udev rule. It is usually used
1030  * for tools executed from IMPORT= rules.
1031  *
1032  * The initial refcount is 1, and needs to be decremented to
1033  * release the resources of the udev device.
1034  *
1035  * Returns: a new udev device, or #NULL, if it does not exist
1036  **/
udev_device_new_from_environment(struct udev * udev)1037 _public_ struct udev_device *udev_device_new_from_environment(struct udev *udev)
1038 {
1039         int i;
1040         struct udev_device *udev_device;
1041 
1042         udev_device = udev_device_new(udev);
1043         if (udev_device == NULL)
1044                 return NULL;
1045         udev_device_set_info_loaded(udev_device);
1046 
1047         for (i = 0; environ[i] != NULL; i++)
1048                 udev_device_add_property_from_string_parse(udev_device, environ[i]);
1049 
1050         if (udev_device_add_property_from_string_parse_finish(udev_device) < 0) {
1051                 log_debug("missing values, invalid device");
1052                 udev_device_unref(udev_device);
1053                 udev_device = NULL;
1054         }
1055 
1056         return udev_device;
1057 }
1058 
device_new_from_parent(struct udev_device * udev_device)1059 static struct udev_device *device_new_from_parent(struct udev_device *udev_device)
1060 {
1061         struct udev_device *udev_device_parent = NULL;
1062         char path[UTIL_PATH_SIZE];
1063         const char *subdir;
1064 
1065         strscpy(path, sizeof(path), udev_device->syspath);
1066         subdir = path + strlen("/sys/");
1067         for (;;) {
1068                 char *pos;
1069 
1070                 pos = strrchr(subdir, '/');
1071                 if (pos == NULL || pos < &subdir[2])
1072                         break;
1073                 pos[0] = '\0';
1074                 udev_device_parent = udev_device_new_from_syspath(udev_device->udev, path);
1075                 if (udev_device_parent != NULL)
1076                         return udev_device_parent;
1077         }
1078 
1079         errno = ENOENT;
1080         return NULL;
1081 }
1082 
1083 /**
1084  * udev_device_get_parent:
1085  * @udev_device: the device to start searching from
1086  *
1087  * Find the next parent device, and fill in information from the sys
1088  * device and the udev database entry.
1089  *
1090  * Returned device is not referenced. It is attached to the child
1091  * device, and will be cleaned up when the child device is cleaned up.
1092  *
1093  * It is not necessarily just the upper level directory, empty or not
1094  * recognized sys directories are ignored.
1095  *
1096  * It can be called as many times as needed, without caring about
1097  * references.
1098  *
1099  * Returns: a new udev device, or #NULL, if it no parent exist.
1100  **/
udev_device_get_parent(struct udev_device * udev_device)1101 _public_ struct udev_device *udev_device_get_parent(struct udev_device *udev_device)
1102 {
1103         if (udev_device == NULL) {
1104                 errno = EINVAL;
1105                 return NULL;
1106         }
1107         if (!udev_device->parent_set) {
1108                 udev_device->parent_set = true;
1109                 udev_device->parent_device = device_new_from_parent(udev_device);
1110         }
1111         return udev_device->parent_device;
1112 }
1113 
1114 /**
1115  * udev_device_get_parent_with_subsystem_devtype:
1116  * @udev_device: udev device to start searching from
1117  * @subsystem: the subsystem of the device
1118  * @devtype: the type (DEVTYPE) of the device
1119  *
1120  * Find the next parent device, with a matching subsystem and devtype
1121  * value, and fill in information from the sys device and the udev
1122  * database entry.
1123  *
1124  * If devtype is #NULL, only subsystem is checked, and any devtype will
1125  * match.
1126  *
1127  * Returned device is not referenced. It is attached to the child
1128  * device, and will be cleaned up when the child device is cleaned up.
1129  *
1130  * It can be called as many times as needed, without caring about
1131  * references.
1132  *
1133  * Returns: a new udev device, or #NULL if no matching parent exists.
1134  **/
udev_device_get_parent_with_subsystem_devtype(struct udev_device * udev_device,const char * subsystem,const char * devtype)1135 _public_ struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype)
1136 {
1137         struct udev_device *parent;
1138 
1139         if (subsystem == NULL) {
1140                 errno = EINVAL;
1141                 return NULL;
1142         }
1143 
1144         parent = udev_device_get_parent(udev_device);
1145         while (parent != NULL) {
1146                 const char *parent_subsystem;
1147                 const char *parent_devtype;
1148 
1149                 parent_subsystem = udev_device_get_subsystem(parent);
1150                 if (parent_subsystem != NULL && streq(parent_subsystem, subsystem)) {
1151                         if (devtype == NULL)
1152                                 break;
1153                         parent_devtype = udev_device_get_devtype(parent);
1154                         if (parent_devtype != NULL && streq(parent_devtype, devtype))
1155                                 break;
1156                 }
1157                 parent = udev_device_get_parent(parent);
1158         }
1159 
1160         if (!parent)
1161                 errno = ENOENT;
1162 
1163         return parent;
1164 }
1165 
1166 /**
1167  * udev_device_get_udev:
1168  * @udev_device: udev device
1169  *
1170  * Retrieve the udev library context the device was created with.
1171  *
1172  * Returns: the udev library context
1173  **/
udev_device_get_udev(struct udev_device * udev_device)1174 _public_ struct udev *udev_device_get_udev(struct udev_device *udev_device)
1175 {
1176         if (udev_device == NULL)
1177                 return NULL;
1178         return udev_device->udev;
1179 }
1180 
1181 /**
1182  * udev_device_ref:
1183  * @udev_device: udev device
1184  *
1185  * Take a reference of a udev device.
1186  *
1187  * Returns: the passed udev device
1188  **/
udev_device_ref(struct udev_device * udev_device)1189 _public_ struct udev_device *udev_device_ref(struct udev_device *udev_device)
1190 {
1191         if (udev_device == NULL)
1192                 return NULL;
1193         udev_device->refcount++;
1194         return udev_device;
1195 }
1196 
1197 /**
1198  * udev_device_unref:
1199  * @udev_device: udev device
1200  *
1201  * Drop a reference of a udev device. If the refcount reaches zero,
1202  * the resources of the device will be released.
1203  *
1204  * Returns: #NULL
1205  **/
udev_device_unref(struct udev_device * udev_device)1206 _public_ struct udev_device *udev_device_unref(struct udev_device *udev_device)
1207 {
1208         if (udev_device == NULL)
1209                 return NULL;
1210         udev_device->refcount--;
1211         if (udev_device->refcount > 0)
1212                 return NULL;
1213         if (udev_device->parent_device != NULL)
1214                 udev_device_unref(udev_device->parent_device);
1215         free(udev_device->syspath);
1216         free(udev_device->sysname);
1217         free(udev_device->devnode);
1218         free(udev_device->subsystem);
1219         free(udev_device->devtype);
1220         udev_list_cleanup(&udev_device->devlinks_list);
1221         udev_list_cleanup(&udev_device->properties_list);
1222         udev_list_cleanup(&udev_device->sysattr_value_list);
1223         udev_list_cleanup(&udev_device->sysattr_list);
1224         udev_list_cleanup(&udev_device->tags_list);
1225         free(udev_device->action);
1226         free(udev_device->driver);
1227         free(udev_device->devpath_old);
1228         free(udev_device->id_filename);
1229         free(udev_device->envp);
1230         free(udev_device->monitor_buf);
1231         free(udev_device);
1232         return NULL;
1233 }
1234 
1235 /**
1236  * udev_device_get_devpath:
1237  * @udev_device: udev device
1238  *
1239  * Retrieve the kernel devpath value of the udev device. The path
1240  * does not contain the sys mount point, and starts with a '/'.
1241  *
1242  * Returns: the devpath of the udev device
1243  **/
udev_device_get_devpath(struct udev_device * udev_device)1244 _public_ const char *udev_device_get_devpath(struct udev_device *udev_device)
1245 {
1246         if (udev_device == NULL)
1247                 return NULL;
1248         return udev_device->devpath;
1249 }
1250 
1251 /**
1252  * udev_device_get_syspath:
1253  * @udev_device: udev device
1254  *
1255  * Retrieve the sys path of the udev device. The path is an
1256  * absolute path and starts with the sys mount point.
1257  *
1258  * Returns: the sys path of the udev device
1259  **/
udev_device_get_syspath(struct udev_device * udev_device)1260 _public_ const char *udev_device_get_syspath(struct udev_device *udev_device)
1261 {
1262         if (udev_device == NULL)
1263                 return NULL;
1264         return udev_device->syspath;
1265 }
1266 
1267 /**
1268  * udev_device_get_sysname:
1269  * @udev_device: udev device
1270  *
1271  * Get the kernel device name in /sys.
1272  *
1273  * Returns: the name string of the device device
1274  **/
udev_device_get_sysname(struct udev_device * udev_device)1275 _public_ const char *udev_device_get_sysname(struct udev_device *udev_device)
1276 {
1277         if (udev_device == NULL)
1278                 return NULL;
1279         return udev_device->sysname;
1280 }
1281 
1282 /**
1283  * udev_device_get_sysnum:
1284  * @udev_device: udev device
1285  *
1286  * Get the instance number of the device.
1287  *
1288  * Returns: the trailing number string of the device name
1289  **/
udev_device_get_sysnum(struct udev_device * udev_device)1290 _public_ const char *udev_device_get_sysnum(struct udev_device *udev_device)
1291 {
1292         if (udev_device == NULL)
1293                 return NULL;
1294         return udev_device->sysnum;
1295 }
1296 
1297 /**
1298  * udev_device_get_devnode:
1299  * @udev_device: udev device
1300  *
1301  * Retrieve the device node file name belonging to the udev device.
1302  * The path is an absolute path, and starts with the device directory.
1303  *
1304  * Returns: the device node file name of the udev device, or #NULL if no device node exists
1305  **/
udev_device_get_devnode(struct udev_device * udev_device)1306 _public_ const char *udev_device_get_devnode(struct udev_device *udev_device)
1307 {
1308         if (udev_device == NULL)
1309                 return NULL;
1310         if (udev_device->devnode != NULL)
1311                 return udev_device->devnode;
1312         if (!udev_device->info_loaded)
1313                 udev_device_read_uevent_file(udev_device);
1314         return udev_device->devnode;
1315 }
1316 
1317 /**
1318  * udev_device_get_devlinks_list_entry:
1319  * @udev_device: udev device
1320  *
1321  * Retrieve the list of device links pointing to the device file of
1322  * the udev device. The next list entry can be retrieved with
1323  * udev_list_entry_get_next(), which returns #NULL if no more entries exist.
1324  * The devlink path can be retrieved from the list entry by
1325  * udev_list_entry_get_name(). The path is an absolute path, and starts with
1326  * the device directory.
1327  *
1328  * Returns: the first entry of the device node link list
1329  **/
udev_device_get_devlinks_list_entry(struct udev_device * udev_device)1330 _public_ struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device)
1331 {
1332         if (udev_device == NULL)
1333                 return NULL;
1334         if (!udev_device->info_loaded)
1335                 udev_device_read_db(udev_device);
1336         return udev_list_get_entry(&udev_device->devlinks_list);
1337 }
1338 
udev_device_cleanup_devlinks_list(struct udev_device * udev_device)1339 void udev_device_cleanup_devlinks_list(struct udev_device *udev_device)
1340 {
1341         udev_device->devlinks_uptodate = false;
1342         udev_list_cleanup(&udev_device->devlinks_list);
1343 }
1344 
1345 /**
1346  * udev_device_get_properties_list_entry:
1347  * @udev_device: udev device
1348  *
1349  * Retrieve the list of key/value device properties of the udev
1350  * device. The next list entry can be retrieved with udev_list_entry_get_next(),
1351  * which returns #NULL if no more entries exist. The property name
1352  * can be retrieved from the list entry by udev_list_entry_get_name(),
1353  * the property value by udev_list_entry_get_value().
1354  *
1355  * Returns: the first entry of the property list
1356  **/
udev_device_get_properties_list_entry(struct udev_device * udev_device)1357 _public_ struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device)
1358 {
1359         if (udev_device == NULL)
1360                 return NULL;
1361         if (!udev_device->info_loaded) {
1362                 udev_device_read_uevent_file(udev_device);
1363                 udev_device_read_db(udev_device);
1364         }
1365         if (!udev_device->devlinks_uptodate) {
1366                 char symlinks[UTIL_PATH_SIZE];
1367                 struct udev_list_entry *list_entry;
1368 
1369                 udev_device->devlinks_uptodate = true;
1370                 list_entry = udev_device_get_devlinks_list_entry(udev_device);
1371                 if (list_entry != NULL) {
1372                         char *s;
1373                         size_t l;
1374 
1375                         s = symlinks;
1376                         l = strpcpyl(&s, sizeof(symlinks), udev_list_entry_get_name(list_entry), NULL);
1377                         udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry))
1378                                 l = strpcpyl(&s, l, " ", udev_list_entry_get_name(list_entry), NULL);
1379                         udev_device_add_property_internal(udev_device, "DEVLINKS", symlinks);
1380                 }
1381         }
1382         if (!udev_device->tags_uptodate) {
1383                 udev_device->tags_uptodate = true;
1384                 if (udev_device_get_tags_list_entry(udev_device) != NULL) {
1385                         char tags[UTIL_PATH_SIZE];
1386                         struct udev_list_entry *list_entry;
1387                         char *s;
1388                         size_t l;
1389 
1390                         s = tags;
1391                         l = strpcpyl(&s, sizeof(tags), ":", NULL);
1392                         udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(udev_device))
1393                                 l = strpcpyl(&s, l, udev_list_entry_get_name(list_entry), ":", NULL);
1394                         udev_device_add_property_internal(udev_device, "TAGS", tags);
1395                 } else {
1396                         udev_device_add_property_internal(udev_device, "TAGS", NULL);
1397                 }
1398         }
1399         return udev_list_get_entry(&udev_device->properties_list);
1400 }
1401 
1402 /**
1403  * udev_device_get_action:
1404  * @udev_device: udev device
1405  *
1406  * This is only valid if the device was received through a monitor. Devices read from
1407  * sys do not have an action string. Usual actions are: add, remove, change, online,
1408  * offline.
1409  *
1410  * Returns: the kernel action value, or #NULL if there is no action value available.
1411  **/
udev_device_get_action(struct udev_device * udev_device)1412 _public_ const char *udev_device_get_action(struct udev_device *udev_device)
1413 {
1414         if (udev_device == NULL)
1415                 return NULL;
1416         return udev_device->action;
1417 }
1418 
1419 /**
1420  * udev_device_get_usec_since_initialized:
1421  * @udev_device: udev device
1422  *
1423  * Return the number of microseconds passed since udev set up the
1424  * device for the first time.
1425  *
1426  * This is only implemented for devices with need to store properties
1427  * in the udev database. All other devices return 0 here.
1428  *
1429  * Returns: the number of microseconds since the device was first seen.
1430  **/
udev_device_get_usec_since_initialized(struct udev_device * udev_device)1431 _public_ unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device)
1432 {
1433         usec_t now_ts;
1434 
1435         if (udev_device == NULL)
1436                 return 0;
1437         if (!udev_device->info_loaded)
1438                 udev_device_read_db(udev_device);
1439         if (udev_device->usec_initialized == 0)
1440                 return 0;
1441         now_ts = now(CLOCK_MONOTONIC);
1442         if (now_ts == 0)
1443                 return 0;
1444         return now_ts - udev_device->usec_initialized;
1445 }
1446 
udev_device_get_usec_initialized(struct udev_device * udev_device)1447 usec_t udev_device_get_usec_initialized(struct udev_device *udev_device)
1448 {
1449         return udev_device->usec_initialized;
1450 }
1451 
1452 /**
1453  * udev_device_get_sysattr_value:
1454  * @udev_device: udev device
1455  * @sysattr: attribute name
1456  *
1457  * The retrieved value is cached in the device. Repeated calls will return the same
1458  * value and not open the attribute again.
1459  *
1460  * Returns: the content of a sys attribute file, or #NULL if there is no sys attribute value.
1461  **/
udev_device_get_sysattr_value(struct udev_device * udev_device,const char * sysattr)1462 _public_ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr)
1463 {
1464         struct udev_list_entry *list_entry;
1465         char path[UTIL_PATH_SIZE];
1466         char value[4096];
1467         struct stat statbuf;
1468         int fd;
1469         ssize_t size;
1470         const char *val = NULL;
1471 
1472         if (udev_device == NULL)
1473                 return NULL;
1474         if (sysattr == NULL)
1475                 return NULL;
1476 
1477         /* look for possibly already cached result */
1478         list_entry = udev_list_get_entry(&udev_device->sysattr_value_list);
1479         list_entry = udev_list_entry_get_by_name(list_entry, sysattr);
1480         if (list_entry != NULL)
1481                 return udev_list_entry_get_value(list_entry);
1482 
1483         strscpyl(path, sizeof(path), udev_device_get_syspath(udev_device), "/", sysattr, NULL);
1484         if (lstat(path, &statbuf) != 0) {
1485                 udev_list_entry_add(&udev_device->sysattr_value_list, sysattr, NULL);
1486                 goto out;
1487         }
1488 
1489         if (S_ISLNK(statbuf.st_mode)) {
1490                 /*
1491                  * Some core links return only the last element of the target path,
1492                  * these are just values, the paths should not be exposed.
1493                  */
1494                 if (streq(sysattr, "driver") ||
1495                     streq(sysattr, "subsystem") ||
1496                     streq(sysattr, "module")) {
1497                         if (util_get_sys_core_link_value(udev_device->udev, sysattr,
1498                                                          udev_device->syspath, value, sizeof(value)) < 0)
1499                                 return NULL;
1500                         list_entry = udev_list_entry_add(&udev_device->sysattr_value_list, sysattr, value);
1501                         val = udev_list_entry_get_value(list_entry);
1502                         goto out;
1503                 }
1504 
1505                 goto out;
1506         }
1507 
1508         /* skip directories */
1509         if (S_ISDIR(statbuf.st_mode))
1510                 goto out;
1511 
1512         /* skip non-readable files */
1513         if ((statbuf.st_mode & S_IRUSR) == 0)
1514                 goto out;
1515 
1516         /* read attribute value */
1517         fd = open(path, O_RDONLY|O_CLOEXEC);
1518         if (fd < 0)
1519                 goto out;
1520         size = read(fd, value, sizeof(value));
1521         close(fd);
1522         if (size < 0)
1523                 goto out;
1524         if (size == sizeof(value))
1525                 goto out;
1526 
1527         /* got a valid value, store it in cache and return it */
1528         value[size] = '\0';
1529         util_remove_trailing_chars(value, '\n');
1530         list_entry = udev_list_entry_add(&udev_device->sysattr_value_list, sysattr, value);
1531         val = udev_list_entry_get_value(list_entry);
1532 out:
1533         return val;
1534 }
1535 
1536 /**
1537  * udev_device_set_sysattr_value:
1538  * @udev_device: udev device
1539  * @sysattr: attribute name
1540  * @value: new value to be set
1541  *
1542  * Update the contents of the sys attribute and the cached value of the device.
1543  *
1544  * Returns: Negative error code on failure or 0 on success.
1545  **/
udev_device_set_sysattr_value(struct udev_device * udev_device,const char * sysattr,char * value)1546 _public_ int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, char *value)
1547 {
1548         struct udev_device *dev;
1549         char path[UTIL_PATH_SIZE];
1550         struct stat statbuf;
1551         int fd;
1552         ssize_t size, value_len;
1553         int ret = 0;
1554 
1555         if (udev_device == NULL)
1556                 return -EINVAL;
1557         dev = udev_device;
1558         if (sysattr == NULL)
1559                 return -EINVAL;
1560         if (value == NULL)
1561                 value_len = 0;
1562         else
1563                 value_len = strlen(value);
1564 
1565         strscpyl(path, sizeof(path), udev_device_get_syspath(dev), "/", sysattr, NULL);
1566         if (lstat(path, &statbuf) != 0) {
1567                 udev_list_entry_add(&dev->sysattr_value_list, sysattr, NULL);
1568                 ret = -ENXIO;
1569                 goto out;
1570         }
1571 
1572         if (S_ISLNK(statbuf.st_mode)) {
1573                 ret = -EINVAL;
1574                 goto out;
1575         }
1576 
1577         /* skip directories */
1578         if (S_ISDIR(statbuf.st_mode)) {
1579                 ret = -EISDIR;
1580                 goto out;
1581         }
1582 
1583         /* skip non-readable files */
1584         if ((statbuf.st_mode & S_IRUSR) == 0) {
1585                 ret = -EACCES;
1586                 goto out;
1587         }
1588 
1589         /* Value is limited to 4k */
1590         if (value_len > 4096) {
1591                 ret = -EINVAL;
1592                 goto out;
1593         }
1594         util_remove_trailing_chars(value, '\n');
1595 
1596         /* write attribute value */
1597         fd = open(path, O_WRONLY|O_CLOEXEC);
1598         if (fd < 0) {
1599                 ret = -errno;
1600                 goto out;
1601         }
1602         size = write(fd, value, value_len);
1603         close(fd);
1604         if (size < 0) {
1605                 ret = -errno;
1606                 goto out;
1607         }
1608         if (size < value_len) {
1609                 ret = -EIO;
1610                 goto out;
1611         }
1612 
1613         /* wrote a valid value, store it in cache and return it */
1614         udev_list_entry_add(&dev->sysattr_value_list, sysattr, value);
1615 out:
1616         if (dev != udev_device)
1617                 udev_device_unref(dev);
1618         return ret;
1619 }
1620 
udev_device_sysattr_list_read(struct udev_device * udev_device)1621 static int udev_device_sysattr_list_read(struct udev_device *udev_device)
1622 {
1623         struct dirent *dent;
1624         DIR *dir;
1625         int num = 0;
1626 
1627         if (udev_device == NULL)
1628                 return -EINVAL;
1629         if (udev_device->sysattr_list_read)
1630                 return 0;
1631 
1632         dir = opendir(udev_device_get_syspath(udev_device));
1633         if (!dir)
1634                 return -errno;
1635 
1636         for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
1637                 char path[UTIL_PATH_SIZE];
1638                 struct stat statbuf;
1639 
1640                 /* only handle symlinks and regular files */
1641                 if (dent->d_type != DT_LNK && dent->d_type != DT_REG)
1642                         continue;
1643 
1644                 strscpyl(path, sizeof(path), udev_device_get_syspath(udev_device), "/", dent->d_name, NULL);
1645                 if (lstat(path, &statbuf) != 0)
1646                         continue;
1647                 if ((statbuf.st_mode & S_IRUSR) == 0)
1648                         continue;
1649 
1650                 udev_list_entry_add(&udev_device->sysattr_list, dent->d_name, NULL);
1651                 num++;
1652         }
1653 
1654         closedir(dir);
1655         udev_device->sysattr_list_read = true;
1656 
1657         return num;
1658 }
1659 
1660 /**
1661  * udev_device_get_sysattr_list_entry:
1662  * @udev_device: udev device
1663  *
1664  * Retrieve the list of available sysattrs, with value being empty;
1665  * This just return all available sysfs attributes for a particular
1666  * device without reading their values.
1667  *
1668  * Returns: the first entry of the property list
1669  **/
udev_device_get_sysattr_list_entry(struct udev_device * udev_device)1670 _public_ struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device)
1671 {
1672         if (!udev_device->sysattr_list_read) {
1673                 int ret;
1674                 ret = udev_device_sysattr_list_read(udev_device);
1675                 if (0 > ret)
1676                         return NULL;
1677         }
1678 
1679         return udev_list_get_entry(&udev_device->sysattr_list);
1680 }
1681 
udev_device_set_devnode(struct udev_device * udev_device,const char * devnode)1682 static int udev_device_set_devnode(struct udev_device *udev_device, const char *devnode)
1683 {
1684         free(udev_device->devnode);
1685         if (devnode[0] != '/') {
1686                 if (asprintf(&udev_device->devnode, "/dev/%s", devnode) < 0)
1687                         udev_device->devnode = NULL;
1688         } else {
1689                 udev_device->devnode = strdup(devnode);
1690         }
1691         if (udev_device->devnode == NULL)
1692                 return -ENOMEM;
1693         udev_device_add_property_internal(udev_device, "DEVNAME", udev_device->devnode);
1694         return 0;
1695 }
1696 
udev_device_add_devlink(struct udev_device * udev_device,const char * devlink)1697 int udev_device_add_devlink(struct udev_device *udev_device, const char *devlink)
1698 {
1699         struct udev_list_entry *list_entry;
1700 
1701         udev_device->devlinks_uptodate = false;
1702         list_entry = udev_list_entry_add(&udev_device->devlinks_list, devlink, NULL);
1703         if (list_entry == NULL)
1704                 return -ENOMEM;
1705         return 0;
1706 }
1707 
udev_device_get_id_filename(struct udev_device * udev_device)1708 const char *udev_device_get_id_filename(struct udev_device *udev_device)
1709 {
1710         if (udev_device->id_filename == NULL) {
1711                 if (udev_device_get_subsystem(udev_device) == NULL)
1712                         return NULL;
1713 
1714                 if (major(udev_device_get_devnum(udev_device)) > 0) {
1715                         /* use dev_t -- b259:131072, c254:0 */
1716                         if (asprintf(&udev_device->id_filename, "%c%u:%u",
1717                                      streq(udev_device_get_subsystem(udev_device), "block") ? 'b' : 'c',
1718                                      major(udev_device_get_devnum(udev_device)),
1719                                      minor(udev_device_get_devnum(udev_device))) < 0)
1720                                 udev_device->id_filename = NULL;
1721                 } else if (udev_device_get_ifindex(udev_device) > 0) {
1722                         /* use netdev ifindex -- n3 */
1723                         if (asprintf(&udev_device->id_filename, "n%i", udev_device_get_ifindex(udev_device)) < 0)
1724                                 udev_device->id_filename = NULL;
1725                 } else {
1726                         /*
1727                          * use $subsys:$syname -- pci:0000:00:1f.2
1728                          * sysname() has '!' translated, get it from devpath
1729                          */
1730                         const char *sysname;
1731                         sysname = strrchr(udev_device->devpath, '/');
1732                         if (sysname == NULL)
1733                                 return NULL;
1734                         sysname = &sysname[1];
1735                         if (asprintf(&udev_device->id_filename, "+%s:%s", udev_device_get_subsystem(udev_device), sysname) < 0)
1736                                 udev_device->id_filename = NULL;
1737                 }
1738         }
1739         return udev_device->id_filename;
1740 }
1741 
1742 /**
1743  * udev_device_get_is_initialized:
1744  * @udev_device: udev device
1745  *
1746  * Check if udev has already handled the device and has set up
1747  * device node permissions and context, or has renamed a network
1748  * device.
1749  *
1750  * This is only implemented for devices with a device node
1751  * or network interfaces. All other devices return 1 here.
1752  *
1753  * Returns: 1 if the device is set up. 0 otherwise.
1754  **/
udev_device_get_is_initialized(struct udev_device * udev_device)1755 _public_ int udev_device_get_is_initialized(struct udev_device *udev_device)
1756 {
1757         if (!udev_device->info_loaded)
1758                 udev_device_read_db(udev_device);
1759         return udev_device->is_initialized;
1760 }
1761 
udev_device_set_is_initialized(struct udev_device * udev_device)1762 void udev_device_set_is_initialized(struct udev_device *udev_device)
1763 {
1764         udev_device->is_initialized = true;
1765 }
1766 
is_valid_tag(const char * tag)1767 static bool is_valid_tag(const char *tag)
1768 {
1769         return !strchr(tag, ':') && !strchr(tag, ' ');
1770 }
1771 
udev_device_add_tag(struct udev_device * udev_device,const char * tag)1772 int udev_device_add_tag(struct udev_device *udev_device, const char *tag)
1773 {
1774         if (!is_valid_tag(tag))
1775                 return -EINVAL;
1776         udev_device->tags_uptodate = false;
1777         if (udev_list_entry_add(&udev_device->tags_list, tag, NULL) != NULL)
1778                 return 0;
1779         return -ENOMEM;
1780 }
1781 
udev_device_remove_tag(struct udev_device * udev_device,const char * tag)1782 void udev_device_remove_tag(struct udev_device *udev_device, const char *tag)
1783 {
1784         struct udev_list_entry *e;
1785 
1786         if (!is_valid_tag(tag))
1787                 return;
1788         e = udev_list_get_entry(&udev_device->tags_list);
1789         e = udev_list_entry_get_by_name(e, tag);
1790         if (e) {
1791                 udev_device->tags_uptodate = false;
1792                 udev_list_entry_delete(e);
1793         }
1794 }
1795 
udev_device_cleanup_tags_list(struct udev_device * udev_device)1796 void udev_device_cleanup_tags_list(struct udev_device *udev_device)
1797 {
1798         udev_device->tags_uptodate = false;
1799         udev_list_cleanup(&udev_device->tags_list);
1800 }
1801 
1802 /**
1803  * udev_device_get_tags_list_entry:
1804  * @udev_device: udev device
1805  *
1806  * Retrieve the list of tags attached to the udev device. The next
1807  * list entry can be retrieved with udev_list_entry_get_next(),
1808  * which returns #NULL if no more entries exist. The tag string
1809  * can be retrieved from the list entry by udev_list_entry_get_name().
1810  *
1811  * Returns: the first entry of the tag list
1812  **/
udev_device_get_tags_list_entry(struct udev_device * udev_device)1813 _public_ struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device)
1814 {
1815         if (udev_device == NULL)
1816                 return NULL;
1817         if (!udev_device->info_loaded)
1818                 udev_device_read_db(udev_device);
1819         return udev_list_get_entry(&udev_device->tags_list);
1820 }
1821 
1822 /**
1823  * udev_device_has_tag:
1824  * @udev_device: udev device
1825  * @tag: tag name
1826  *
1827  * Check if a given device has a certain tag associated.
1828  *
1829  * Returns: 1 if the tag is found. 0 otherwise.
1830  **/
udev_device_has_tag(struct udev_device * udev_device,const char * tag)1831 _public_ int udev_device_has_tag(struct udev_device *udev_device, const char *tag)
1832 {
1833         struct udev_list_entry *list_entry;
1834 
1835         if (udev_device == NULL)
1836                 return false;
1837         if (!udev_device->info_loaded)
1838                 udev_device_read_db(udev_device);
1839         list_entry = udev_device_get_tags_list_entry(udev_device);
1840         if (udev_list_entry_get_by_name(list_entry, tag) != NULL)
1841                 return true;
1842         return false;
1843 }
1844 
1845 #define ENVP_SIZE                        128
1846 #define MONITOR_BUF_SIZE                4096
update_envp_monitor_buf(struct udev_device * udev_device)1847 static int update_envp_monitor_buf(struct udev_device *udev_device)
1848 {
1849         struct udev_list_entry *list_entry;
1850         char *s;
1851         size_t l;
1852         unsigned int i;
1853 
1854         /* monitor buffer of property strings */
1855         free(udev_device->monitor_buf);
1856         udev_device->monitor_buf_len = 0;
1857         udev_device->monitor_buf = malloc(MONITOR_BUF_SIZE);
1858         if (udev_device->monitor_buf == NULL)
1859                 return -ENOMEM;
1860 
1861         /* envp array, strings will point into monitor buffer */
1862         if (udev_device->envp == NULL)
1863                 udev_device->envp = malloc(sizeof(char *) * ENVP_SIZE);
1864         if (udev_device->envp == NULL)
1865                 return -ENOMEM;
1866 
1867         i = 0;
1868         s = udev_device->monitor_buf;
1869         l = MONITOR_BUF_SIZE;
1870         udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(udev_device)) {
1871                 const char *key;
1872 
1873                 key = udev_list_entry_get_name(list_entry);
1874                 /* skip private variables */
1875                 if (key[0] == '.')
1876                         continue;
1877 
1878                 /* add string to envp array */
1879                 udev_device->envp[i++] = s;
1880                 if (i+1 >= ENVP_SIZE)
1881                         return -EINVAL;
1882 
1883                 /* add property string to monitor buffer */
1884                 l = strpcpyl(&s, l, key, "=", udev_list_entry_get_value(list_entry), NULL);
1885                 if (l == 0)
1886                         return -EINVAL;
1887                 /* advance past the trailing '\0' that strpcpyl() guarantees */
1888                 s++;
1889                 l--;
1890         }
1891         udev_device->envp[i] = NULL;
1892         udev_device->monitor_buf_len = s - udev_device->monitor_buf;
1893         udev_device->envp_uptodate = true;
1894         return 0;
1895 }
1896 
udev_device_get_properties_envp(struct udev_device * udev_device)1897 char **udev_device_get_properties_envp(struct udev_device *udev_device)
1898 {
1899         if (!udev_device->envp_uptodate)
1900                 if (update_envp_monitor_buf(udev_device) != 0)
1901                         return NULL;
1902         return udev_device->envp;
1903 }
1904 
udev_device_get_properties_monitor_buf(struct udev_device * udev_device,const char ** buf)1905 ssize_t udev_device_get_properties_monitor_buf(struct udev_device *udev_device, const char **buf)
1906 {
1907         if (!udev_device->envp_uptodate)
1908                 if (update_envp_monitor_buf(udev_device) != 0)
1909                         return -EINVAL;
1910         *buf = udev_device->monitor_buf;
1911         return udev_device->monitor_buf_len;
1912 }
1913 
udev_device_get_devlink_priority(struct udev_device * udev_device)1914 int udev_device_get_devlink_priority(struct udev_device *udev_device)
1915 {
1916         if (!udev_device->info_loaded)
1917                 udev_device_read_db(udev_device);
1918         return udev_device->devlink_priority;
1919 }
1920 
udev_device_set_devlink_priority(struct udev_device * udev_device,int prio)1921 int udev_device_set_devlink_priority(struct udev_device *udev_device, int prio)
1922 {
1923          udev_device->devlink_priority = prio;
1924         return 0;
1925 }
1926 
udev_device_get_watch_handle(struct udev_device * udev_device)1927 int udev_device_get_watch_handle(struct udev_device *udev_device)
1928 {
1929         if (!udev_device->info_loaded)
1930                 udev_device_read_db(udev_device);
1931         return udev_device->watch_handle;
1932 }
1933 
udev_device_set_watch_handle(struct udev_device * udev_device,int handle)1934 int udev_device_set_watch_handle(struct udev_device *udev_device, int handle)
1935 {
1936         udev_device->watch_handle = handle;
1937         return 0;
1938 }
1939 
udev_device_get_db_persist(struct udev_device * udev_device)1940 bool udev_device_get_db_persist(struct udev_device *udev_device)
1941 {
1942         return udev_device->db_persist;
1943 }
1944 
udev_device_set_db_persist(struct udev_device * udev_device)1945 void udev_device_set_db_persist(struct udev_device *udev_device)
1946 {
1947         udev_device->db_persist = true;
1948 }
1949 
udev_device_rename(struct udev_device * udev_device,const char * name)1950 int udev_device_rename(struct udev_device *udev_device, const char *name)
1951 {
1952         _cleanup_free_ char *dirname = NULL;
1953         const char *interface;
1954         char *new_syspath;
1955         int r;
1956 
1957         if (udev_device == NULL || name == NULL)
1958                 return -EINVAL;
1959 
1960         dirname = dirname_malloc(udev_device->syspath);
1961         if (!dirname)
1962                 return -ENOMEM;
1963 
1964         new_syspath = strjoina(dirname, "/", name);
1965 
1966         r = udev_device_set_syspath(udev_device, new_syspath);
1967         if (r < 0)
1968                 return r;
1969 
1970         interface = udev_device_get_property_value(udev_device, "INTERFACE");
1971         if (interface) {
1972                 /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
1973                 udev_device_add_property_internal(udev_device, "INTERFACE_OLD", interface);
1974                 udev_device_add_property_internal(udev_device, "INTERFACE", name);
1975         }
1976 
1977         return 0;
1978 }
1979 
udev_device_shallow_clone(struct udev_device * old_device)1980 struct udev_device *udev_device_shallow_clone(struct udev_device *old_device)
1981 {
1982         struct udev_device *device;
1983 
1984         if (old_device == NULL)
1985                 return NULL;
1986 
1987         device = udev_device_new(old_device->udev);
1988         if (!device) {
1989                 errno = ENOMEM;
1990 
1991                 return NULL;
1992         }
1993 
1994         udev_device_set_syspath(device, udev_device_get_syspath(old_device));
1995         udev_device_set_subsystem(device, udev_device_get_subsystem(old_device));
1996         udev_device_set_devnum(device, udev_device_get_devnum(old_device));
1997 
1998         return device;
1999 }
2000 
udev_device_clone_with_db(struct udev_device * old_device)2001 struct udev_device *udev_device_clone_with_db(struct udev_device *old_device)
2002 {
2003         struct udev_device *device;
2004 
2005         device = udev_device_shallow_clone(old_device);
2006         if (!device)
2007                 return NULL;
2008 
2009         udev_device_read_db(device);
2010         udev_device_set_info_loaded(device);
2011 
2012         return device;
2013 }
2014 
udev_device_new_from_nulstr(struct udev * udev,char * nulstr,ssize_t buflen)2015 struct udev_device *udev_device_new_from_nulstr(struct udev *udev, char *nulstr, ssize_t buflen) {
2016         struct udev_device *device;
2017         ssize_t bufpos = 0;
2018 
2019         if (nulstr == NULL || buflen <= 0) {
2020                 errno = EINVAL;
2021 
2022                 return NULL;
2023         }
2024 
2025         device = udev_device_new(udev);
2026         if (!device) {
2027                 errno = ENOMEM;
2028 
2029                 return NULL;
2030         }
2031 
2032         udev_device_set_info_loaded(device);
2033 
2034         while (bufpos < buflen) {
2035                 char *key;
2036                 size_t keylen;
2037 
2038                 key = nulstr + bufpos;
2039                 keylen = strlen(key);
2040                 if (keylen == 0)
2041                         break;
2042 
2043                 bufpos += keylen + 1;
2044                 udev_device_add_property_from_string_parse(device, key);
2045         }
2046 
2047         if (udev_device_add_property_from_string_parse_finish(device) < 0) {
2048                 log_debug("missing values, invalid device");
2049 
2050                 udev_device_unref(device);
2051 
2052                 errno = EINVAL;
2053 
2054                 return NULL;
2055         }
2056 
2057         return device;
2058 }
2059 
udev_device_new_from_synthetic_event(struct udev * udev,const char * syspath,const char * action)2060 struct udev_device *udev_device_new_from_synthetic_event(struct udev *udev, const char *syspath, const char *action) {
2061         struct udev_device *ret;
2062         int r;
2063 
2064         if (!action) {
2065                 errno = EINVAL;
2066                 return NULL;
2067         }
2068 
2069         ret = udev_device_new_from_syspath(udev, syspath);
2070         if (!ret)
2071                 return NULL;
2072 
2073         r = udev_device_read_uevent_file(ret);
2074         if (r < 0) {
2075                 udev_device_unref(ret);
2076                 errno = -r;
2077                 return NULL;
2078         }
2079 
2080         r = udev_device_set_action(ret, action);
2081         if (r < 0) {
2082                 udev_device_unref(ret);
2083                 errno = -r;
2084                 return NULL;
2085         }
2086 
2087         return ret;
2088 }
2089 
udev_device_copy_properties(struct udev_device * dst,struct udev_device * src)2090 int udev_device_copy_properties(struct udev_device *dst, struct udev_device *src) {
2091         struct udev_list_entry *entry;
2092 
2093         for ((entry = udev_device_get_properties_list_entry(src)); entry; entry = udev_list_entry_get_next(entry)) {
2094                 const char *key, *value;
2095 
2096                 key = udev_list_entry_get_name(entry);
2097                 value = udev_list_entry_get_value(entry);
2098 
2099                 udev_device_add_property(dst, key, value);
2100         }
2101 
2102         return 0;
2103 }
2104