]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-device/sd-device.c
sd-device: initialize variable
[thirdparty/systemd.git] / src / libsystemd / sd-device / sd-device.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
5 Copyright 2014 Tom Gundersen <teg@jklm.no>
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <ctype.h>
22 #include <sys/types.h>
23 #include <net/if.h>
24
25 #include "util.h"
26 #include "macro.h"
27 #include "path-util.h"
28 #include "strxcpyx.h"
29 #include "fileio.h"
30 #include "hashmap.h"
31 #include "set.h"
32 #include "strv.h"
33
34 #include "sd-device.h"
35
36 #include "device-util.h"
37 #include "device-private.h"
38 #include "device-internal.h"
39
40 int device_new_aux(sd_device **ret) {
41 _cleanup_device_unref_ sd_device *device = NULL;
42
43 assert(ret);
44
45 device = new0(sd_device, 1);
46 if (!device)
47 return -ENOMEM;
48
49 device->n_ref = 1;
50 device->watch_handle = -1;
51
52 *ret = device;
53 device = NULL;
54
55 return 0;
56 }
57
58 _public_ sd_device *sd_device_ref(sd_device *device) {
59 if (device)
60 assert_se(++ device->n_ref >= 2);
61
62 return device;
63 }
64
65 _public_ sd_device *sd_device_unref(sd_device *device) {
66 if (device && -- device->n_ref == 0) {
67 sd_device_unref(device->parent);
68 free(device->syspath);
69 free(device->sysname);
70 free(device->devtype);
71 free(device->devname);
72 free(device->subsystem);
73 free(device->driver);
74 free(device->id_filename);
75 free(device->properties_strv);
76 free(device->properties_nulstr);
77
78 ordered_hashmap_free_free_free(device->properties);
79 ordered_hashmap_free_free_free(device->properties_db);
80 hashmap_free_free_free(device->sysattr_values);
81 set_free_free(device->sysattrs);
82 set_free_free(device->tags);
83 set_free_free(device->devlinks);
84
85 free(device);
86 }
87
88 return NULL;
89 }
90
91 int device_add_property_aux(sd_device *device, const char *_key, const char *_value, bool db) {
92 OrderedHashmap **properties;
93
94 assert(device);
95 assert(_key);
96
97 if (db)
98 properties = &device->properties_db;
99 else
100 properties = &device->properties;
101
102 if (_value) {
103 _cleanup_free_ char *key = NULL, *value = NULL, *old_key = NULL, *old_value = NULL;
104 int r;
105
106 r = ordered_hashmap_ensure_allocated(properties, &string_hash_ops);
107 if (r < 0)
108 return r;
109
110 key = strdup(_key);
111 if (!key)
112 return -ENOMEM;
113
114 value = strdup(_value);
115 if (!value)
116 return -ENOMEM;
117
118 old_value = ordered_hashmap_get2(*properties, key, (void**) &old_key);
119
120 r = ordered_hashmap_replace(*properties, key, value);
121 if (r < 0)
122 return r;
123
124 key = NULL;
125 value = NULL;
126 } else {
127 _cleanup_free_ char *key = NULL;
128 _cleanup_free_ char *value = NULL;
129
130 value = ordered_hashmap_remove2(*properties, _key, (void**) &key);
131 }
132
133 if (!db) {
134 device->properties_generation ++;
135 device->properties_buf_outdated = true;
136 }
137
138 return 0;
139 }
140
141 int device_add_property_internal(sd_device *device, const char *key, const char *value) {
142 return device_add_property_aux(device, key, value, false);
143 }
144
145 int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
146 _cleanup_free_ char *syspath = NULL;
147 const char *devpath;
148 int r;
149
150 assert(device);
151 assert(_syspath);
152
153 /* must be a subdirectory of /sys */
154 if (!path_startswith(_syspath, "/sys/")) {
155 log_debug("sd-device: syspath '%s' is not a subdirectory of /sys", _syspath);
156 return -EINVAL;
157 }
158
159 if (verify) {
160 r = readlink_and_canonicalize(_syspath, &syspath);
161 if (r == -EINVAL) {
162 /* not a symlink */
163 syspath = canonicalize_file_name(_syspath);
164 if (!syspath) {
165 log_debug("sd-device: could not canonicalize '%s': %m", _syspath);
166 return -errno;
167 }
168 /* ignore errors due to the link not being a symlink */
169 } else if (r < 0 && r != -EINVAL) {
170 log_debug("sd-device: could not get target of '%s': %s", _syspath, strerror(-r));
171 return r;
172 }
173
174 if (path_startswith(syspath, "/sys/devices/")) {
175 char *path;
176
177 /* all 'devices' require an 'uevent' file */
178 path = strjoina(syspath, "/uevent");
179 r = access(path, F_OK);
180 if (r < 0) {
181 log_debug("sd-device: %s does not have an uevent file: %m", syspath);
182 return -errno;
183 }
184 } else {
185 /* everything else just just needs to be a directory */
186 if (!is_dir(syspath, false)) {
187 log_debug("sd-device: %s is not a directory", syspath);
188 return -EINVAL;
189 }
190 }
191 } else {
192 syspath = strdup(_syspath);
193 if (!syspath)
194 return -ENOMEM;
195 }
196
197 devpath = syspath + strlen("/sys");
198
199 r = device_add_property_internal(device, "DEVPATH", devpath);
200 if (r < 0)
201 return r;
202
203 free(device->syspath);
204 device->syspath = syspath;
205 syspath = NULL;
206
207 device->devpath = devpath;
208
209 return 0;
210 }
211
212 _public_ int sd_device_new_from_syspath(sd_device **ret, const char *syspath) {
213 _cleanup_device_unref_ sd_device *device = NULL;
214 int r;
215
216 assert_return(ret, -EINVAL);
217 assert_return(syspath, -EINVAL);
218
219 r = device_new_aux(&device);
220 if (r < 0)
221 return r;
222
223 r = device_set_syspath(device, syspath, true);
224 if (r < 0)
225 return r;
226
227 *ret = device;
228 device = NULL;
229
230 return 0;
231 }
232
233 _public_ int sd_device_new_from_devnum(sd_device **ret, char type, dev_t devnum) {
234 char *syspath;
235 char id[DECIMAL_STR_MAX(unsigned) * 2 + 1];
236
237 assert_return(ret, -EINVAL);
238 assert_return(type == 'b' || type == 'c', -EINVAL);
239
240 /* use /sys/dev/{block,char}/<maj>:<min> link */
241 snprintf(id, sizeof(id), "%u:%u", major(devnum), minor(devnum));
242
243 syspath = strjoina("/sys/dev/", (type == 'b' ? "block" : "char"), "/", id);
244
245 return sd_device_new_from_syspath(ret, syspath);
246 }
247
248 _public_ int sd_device_new_from_subsystem_sysname(sd_device **ret, const char *subsystem, const char *sysname) {
249 char *syspath;
250
251 assert_return(ret, -EINVAL);
252 assert_return(subsystem, -EINVAL);
253 assert_return(sysname, -EINVAL);
254
255 if (streq(subsystem, "subsystem")) {
256 syspath = strjoina("/sys/subsystem/", sysname);
257 if (access(syspath, F_OK) >= 0)
258 return sd_device_new_from_syspath(ret, syspath);
259
260 syspath = strjoina("/sys/bus/", sysname);
261 if (access(syspath, F_OK) >= 0)
262 return sd_device_new_from_syspath(ret, syspath);
263
264 syspath = strjoina("/sys/class/", sysname);
265 if (access(syspath, F_OK) >= 0)
266 return sd_device_new_from_syspath(ret, syspath);
267 } else if (streq(subsystem, "module")) {
268 syspath = strjoina("/sys/module/", sysname);
269 if (access(syspath, F_OK) >= 0)
270 return sd_device_new_from_syspath(ret, syspath);
271 } else if (streq(subsystem, "drivers")) {
272 char subsys[PATH_MAX];
273 char *driver;
274
275 strscpy(subsys, sizeof(subsys), sysname);
276 driver = strchr(subsys, ':');
277 if (driver) {
278 driver[0] = '\0';
279 driver++;
280
281 syspath = strjoina("/sys/subsystem/", subsys, "/drivers/", driver);
282 if (access(syspath, F_OK) >= 0)
283 return sd_device_new_from_syspath(ret, syspath);
284
285 syspath = strjoina("/sys/bus/", subsys, "/drivers/", driver);
286 if (access(syspath, F_OK) >= 0)
287 return sd_device_new_from_syspath(ret, syspath);
288 } else
289 return -EINVAL;
290 } else {
291 syspath = strjoina("/sys/subsystem/", subsystem, "/devices/", sysname);
292 if (access(syspath, F_OK) >= 0)
293 return sd_device_new_from_syspath(ret, syspath);
294
295 syspath = strjoina("/sys/bus/", subsystem, "/devices/", sysname);
296 if (access(syspath, F_OK) >= 0)
297 return sd_device_new_from_syspath(ret, syspath);
298
299 syspath = strjoina("/sys/class/", subsystem, "/", sysname);
300 if (access(syspath, F_OK) >= 0)
301 return sd_device_new_from_syspath(ret, syspath);
302 }
303
304 return -ENOENT;
305 }
306
307 int device_set_devtype(sd_device *device, const char *_devtype) {
308 _cleanup_free_ char *devtype = NULL;
309 int r;
310
311 assert(device);
312 assert(_devtype);
313
314 devtype = strdup(_devtype);
315 if (!devtype)
316 return -ENOMEM;
317
318 r = device_add_property_internal(device, "DEVTYPE", devtype);
319 if (r < 0)
320 return r;
321
322 free(device->devtype);
323 device->devtype = devtype;
324 devtype = NULL;
325
326 return 0;
327 }
328
329 int device_set_ifindex(sd_device *device, const char *_ifindex) {
330 int ifindex, r;
331
332 assert(device);
333 assert(_ifindex);
334
335 r = safe_atoi(_ifindex, &ifindex);
336 if (r < 0)
337 return r;
338
339 if (ifindex <= 0)
340 return -EINVAL;
341
342 r = device_add_property_internal(device, "IFINDEX", _ifindex);
343 if (r < 0)
344 return r;
345
346 device->ifindex = ifindex;
347
348 return 0;
349 }
350
351 int device_set_devname(sd_device *device, const char *_devname) {
352 _cleanup_free_ char *devname = NULL;
353 int r;
354
355 assert(device);
356 assert(_devname);
357
358 if (_devname[0] != '/') {
359 r = asprintf(&devname, "/dev/%s", _devname);
360 if (r < 0)
361 return -ENOMEM;
362 } else {
363 devname = strdup(_devname);
364 if (!devname)
365 return -ENOMEM;
366 }
367
368 r = device_add_property_internal(device, "DEVNAME", devname);
369 if (r < 0)
370 return r;
371
372 free(device->devname);
373 device->devname = devname;
374 devname = NULL;
375
376 return 0;
377 }
378
379 int device_set_devmode(sd_device *device, const char *_devmode) {
380 unsigned devmode;
381 int r;
382
383 assert(device);
384 assert(_devmode);
385
386 r = safe_atou(_devmode, &devmode);
387 if (r < 0)
388 return r;
389
390 if (devmode > 07777)
391 return -EINVAL;
392
393 r = device_add_property_internal(device, "DEVMODE", _devmode);
394 if (r < 0)
395 return r;
396
397 device->devmode = devmode;
398
399 return 0;
400 }
401
402 int device_set_devnum(sd_device *device, const char *major, const char *minor) {
403 unsigned maj = 0, min = 0;
404 int r;
405
406 assert(device);
407 assert(major);
408
409 r = safe_atou(major, &maj);
410 if (r < 0)
411 return r;
412 if (!maj)
413 return 0;
414
415 if (minor) {
416 r = safe_atou(minor, &min);
417 if (r < 0)
418 return r;
419 }
420
421 r = device_add_property_internal(device, "MAJOR", major);
422 if (r < 0)
423 return r;
424
425 if (minor) {
426 r = device_add_property_internal(device, "MINOR", minor);
427 if (r < 0)
428 return r;
429 }
430
431 device->devnum = makedev(maj, min);
432
433 return 0;
434 }
435
436 static int handle_uevent_line(sd_device *device, const char *key, const char *value, const char **major, const char **minor) {
437 int r;
438
439 assert(device);
440 assert(key);
441 assert(value);
442 assert(major);
443 assert(minor);
444
445 if (streq(key, "DEVTYPE")) {
446 r = device_set_devtype(device, value);
447 if (r < 0)
448 return r;
449 } else if (streq(key, "IFINDEX")) {
450 r = device_set_ifindex(device, value);
451 if (r < 0)
452 return r;
453 } else if (streq(key, "DEVNAME")) {
454 r = device_set_devname(device, value);
455 if (r < 0)
456 return r;
457 } else if (streq(key, "DEVMODE")) {
458 r = device_set_devmode(device, value);
459 if (r < 0)
460 return r;
461 } else if (streq(key, "MAJOR"))
462 *major = value;
463 else if (streq(key, "MINOR"))
464 *minor = value;
465 else {
466 r = device_add_property_internal(device, key, value);
467 if (r < 0)
468 return r;
469 }
470
471 return 0;
472 }
473
474 int device_read_uevent_file(sd_device *device) {
475 _cleanup_free_ char *uevent = NULL;
476 const char *syspath, *key, *value, *major = NULL, *minor = NULL;
477 char *path;
478 size_t uevent_len;
479 unsigned i;
480 int r;
481
482 enum {
483 PRE_KEY,
484 KEY,
485 PRE_VALUE,
486 VALUE,
487 INVALID_LINE,
488 } state = PRE_KEY;
489
490 assert(device);
491
492 if (device->uevent_loaded || device->sealed)
493 return 0;
494
495 r = sd_device_get_syspath(device, &syspath);
496 if (r < 0)
497 return r;
498
499 path = strjoina(syspath, "/uevent");
500
501 r = read_full_file(path, &uevent, &uevent_len);
502 if (r < 0) {
503 log_debug("sd-device: failed to read uevent file '%s': %s", path, strerror(-r));
504 return r;
505 }
506
507 for (i = 0; i < uevent_len; i++) {
508 switch (state) {
509 case PRE_KEY:
510 if (!strchr(NEWLINE, uevent[i])) {
511 key = &uevent[i];
512
513 state = KEY;
514 }
515
516 break;
517 case KEY:
518 if (uevent[i] == '=') {
519 uevent[i] = '\0';
520
521 state = PRE_VALUE;
522 } else if (strchr(NEWLINE, uevent[i])) {
523 uevent[i] = '\0';
524 log_debug("sd-device: ignoring invalid uevent line '%s'", key);
525
526 state = PRE_KEY;
527 }
528
529 break;
530 case PRE_VALUE:
531 value = &uevent[i];
532
533 state = VALUE;
534
535 break;
536 case VALUE:
537 if (strchr(NEWLINE, uevent[i])) {
538 uevent[i] = '\0';
539
540 r = handle_uevent_line(device, key, value, &major, &minor);
541 if (r < 0)
542 log_debug("sd-device: failed to handle uevent entry '%s=%s': %s", key, value, strerror(-r));
543
544 state = PRE_KEY;
545 }
546
547 break;
548 default:
549 assert_not_reached("invalid state when parsing uevent file");
550 }
551 }
552
553 if (major) {
554 r = device_set_devnum(device, major, minor);
555 if (r < 0)
556 log_debug("sd-device: could not set 'MAJOR=%s' or 'MINOR=%s' from '%s': %s", major, minor, path, strerror(-r));
557 }
558
559 device->uevent_loaded = true;
560
561 return 0;
562 }
563
564 _public_ int sd_device_get_ifindex(sd_device *device, int *ifindex) {
565 int r;
566
567 assert_return(device, -EINVAL);
568 assert_return(ifindex, -EINVAL);
569
570 r = device_read_uevent_file(device);
571 if (r < 0)
572 return r;
573
574 *ifindex = device->ifindex;
575
576 return 0;
577 }
578
579 _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
580 int r;
581
582 assert_return(ret, -EINVAL);
583 assert_return(id, -EINVAL);
584
585 switch (id[0]) {
586 case 'b':
587 case 'c':
588 {
589 char type;
590 int maj, min;
591
592 r = sscanf(id, "%c%i:%i", &type, &maj, &min);
593 if (r != 3)
594 return -EINVAL;
595
596 return sd_device_new_from_devnum(ret, type, makedev(maj, min));
597 }
598 case 'n':
599 {
600 _cleanup_device_unref_ sd_device *device = NULL;
601 _cleanup_close_ int sk = -1;
602 struct ifreq ifr = {};
603 int ifindex;
604
605 r = safe_atoi(&id[1], &ifr.ifr_ifindex);
606 if (r < 0)
607 return r;
608 else if (ifr.ifr_ifindex <= 0)
609 return -EINVAL;
610
611 sk = socket(PF_INET, SOCK_DGRAM, 0);
612 if (sk < 0)
613 return -errno;
614
615 r = ioctl(sk, SIOCGIFNAME, &ifr);
616 if (r < 0)
617 return -errno;
618
619 r = sd_device_new_from_subsystem_sysname(&device, "net", ifr.ifr_name);
620 if (r < 0)
621 return r;
622
623 r = sd_device_get_ifindex(device, &ifindex);
624 if (r < 0)
625 return r;
626
627 /* this si racey, so we might end up with the wrong device */
628 if (ifr.ifr_ifindex != ifindex)
629 return -ENODEV;
630
631 *ret = device;
632 device = NULL;
633
634 return 0;
635 }
636 case '+':
637 {
638 char subsys[PATH_MAX];
639 char *sysname;
640
641 (void)strscpy(subsys, sizeof(subsys), id + 1);
642 sysname = strchr(subsys, ':');
643 if (!sysname)
644 return -EINVAL;
645
646 sysname[0] = '\0';
647 sysname ++;
648
649 return sd_device_new_from_subsystem_sysname(ret, subsys, sysname);
650 }
651 default:
652 return -EINVAL;
653 }
654 }
655
656 _public_ int sd_device_get_syspath(sd_device *device, const char **ret) {
657 assert_return(device, -EINVAL);
658 assert_return(ret, -EINVAL);
659
660 assert(path_startswith(device->syspath, "/sys/"));
661
662 *ret = device->syspath;
663
664 return 0;
665 }
666
667 static int device_new_from_child(sd_device **ret, sd_device *child) {
668 _cleanup_free_ char *path = NULL;
669 const char *subdir, *syspath;
670 int r;
671
672 assert(ret);
673 assert(child);
674
675 r = sd_device_get_syspath(child, &syspath);
676 if (r < 0)
677 return r;
678
679 path = strdup(syspath);
680 if (!path)
681 return -ENOMEM;
682 subdir = path + strlen("/sys");
683
684 for (;;) {
685 char *pos;
686
687 pos = strrchr(subdir, '/');
688 if (!pos || pos < subdir + 2)
689 break;
690
691 *pos = '\0';
692
693 r = sd_device_new_from_syspath(ret, path);
694 if (r < 0)
695 continue;
696
697 return 0;
698 }
699
700 return -ENOENT;
701 }
702
703 _public_ int sd_device_get_parent(sd_device *child, sd_device **ret) {
704
705 assert_return(ret, -EINVAL);
706 assert_return(child, -EINVAL);
707
708 if (!child->parent_set) {
709 child->parent_set = true;
710
711 (void)device_new_from_child(&child->parent, child);
712 }
713
714 if (!child->parent)
715 return -ENOENT;
716
717 *ret = child->parent;
718
719 return 0;
720 }
721
722 int device_set_subsystem(sd_device *device, const char *_subsystem) {
723 _cleanup_free_ char *subsystem = NULL;
724 int r;
725
726 assert(device);
727 assert(_subsystem);
728
729 subsystem = strdup(_subsystem);
730 if (!subsystem)
731 return -ENOMEM;
732
733 r = device_add_property_internal(device, "SUBSYSTEM", subsystem);
734 if (r < 0)
735 return r;
736
737 free(device->subsystem);
738 device->subsystem = subsystem;
739 subsystem = NULL;
740
741 device->subsystem_set = true;
742
743 return 0;
744 }
745
746 _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) {
747 assert_return(ret, -EINVAL);
748 assert_return(device, -EINVAL);
749
750 if (!device->subsystem_set) {
751 _cleanup_free_ char *subsystem = NULL;
752 const char *syspath;
753 char *path;
754 int r;
755
756 /* read 'subsystem' link */
757 r = sd_device_get_syspath(device, &syspath);
758 if (r < 0)
759 return r;
760
761 path = strjoina(syspath, "/subsystem");
762 r = readlink_value(path, &subsystem);
763 if (r >= 0)
764 r = device_set_subsystem(device, subsystem);
765 /* use implicit names */
766 else if (path_startswith(device->devpath, "/module/"))
767 r = device_set_subsystem(device, "module");
768 else if (strstr(device->devpath, "/drivers/"))
769 r = device_set_subsystem(device, "drivers");
770 else if (path_startswith(device->devpath, "/subsystem/") ||
771 path_startswith(device->devpath, "/class/") ||
772 path_startswith(device->devpath, "/buss/"))
773 r = device_set_subsystem(device, "subsystem");
774 if (r < 0)
775 return r;
776
777 device->subsystem_set = true;
778 }
779
780 *ret = device->subsystem;
781
782 return 0;
783 }
784
785 _public_ int sd_device_get_devtype(sd_device *device, const char **devtype) {
786 int r;
787
788 assert(devtype);
789 assert(device);
790
791 r = device_read_uevent_file(device);
792 if (r < 0)
793 return r;
794
795 *devtype = device->devtype;
796
797 return 0;
798 }
799
800 _public_ int sd_device_get_parent_with_subsystem_devtype(sd_device *child, const char *subsystem, const char *devtype, sd_device **ret) {
801 sd_device *parent = NULL;
802 int r;
803
804 assert_return(child, -EINVAL);
805 assert_return(subsystem, -EINVAL);
806
807 r = sd_device_get_parent(child, &parent);
808 while (r >= 0) {
809 const char *parent_subsystem = NULL;
810 const char *parent_devtype = NULL;
811
812 (void)sd_device_get_subsystem(parent, &parent_subsystem);
813 if (streq_ptr(parent_subsystem, subsystem)) {
814 if (!devtype)
815 break;
816
817 (void)sd_device_get_devtype(parent, &parent_devtype);
818 if (streq_ptr(parent_devtype, devtype))
819 break;
820 }
821 r = sd_device_get_parent(parent, &parent);
822 }
823
824 if (r < 0)
825 return r;
826
827 *ret = parent;
828
829 return 0;
830 }
831
832 _public_ int sd_device_get_devnum(sd_device *device, dev_t *devnum) {
833 int r;
834
835 assert_return(device, -EINVAL);
836 assert_return(devnum, -EINVAL);
837
838 r = device_read_uevent_file(device);
839 if (r < 0)
840 return r;
841
842 *devnum = device->devnum;
843
844 return 0;
845 }
846
847 int device_set_driver(sd_device *device, const char *_driver) {
848 _cleanup_free_ char *driver = NULL;
849 int r;
850
851 assert(device);
852 assert(_driver);
853
854 driver = strdup(_driver);
855 if (!driver)
856 return -ENOMEM;
857
858 r = device_add_property_internal(device, "DRIVER", driver);
859 if (r < 0)
860 return r;
861
862 free(device->driver);
863 device->driver = driver;
864 driver = NULL;
865
866 device->driver_set = true;
867
868 return 0;
869 }
870
871 _public_ int sd_device_get_driver(sd_device *device, const char **ret) {
872 assert_return(device, -EINVAL);
873 assert_return(ret, -EINVAL);
874
875 if (!device->driver_set) {
876 _cleanup_free_ char *driver = NULL;
877 const char *syspath;
878 char *path;
879 int r;
880
881 r = sd_device_get_syspath(device, &syspath);
882 if (r < 0)
883 return r;
884
885 path = strjoina(syspath, "/driver");
886 r = readlink_value(path, &driver);
887 if (r >= 0) {
888 r = device_set_driver(device, driver);
889 if (r < 0)
890 return r;
891 }
892 }
893
894 *ret = device->driver;
895
896 return 0;
897 }
898
899 _public_ int sd_device_get_devpath(sd_device *device, const char **devpath) {
900 assert_return(device, -EINVAL);
901 assert_return(devpath, -EINVAL);
902
903 assert(device->devpath);
904 assert(device->devpath[0] == '/');
905
906 *devpath = device->devpath;
907
908 return 0;
909 }
910
911 _public_ int sd_device_get_devname(sd_device *device, const char **devname) {
912 int r;
913
914 assert_return(device, -EINVAL);
915 assert_return(devname, -EINVAL);
916
917 r = device_read_uevent_file(device);
918 if (r < 0)
919 return r;
920
921 if (!device->devname)
922 return -ENOENT;
923
924 assert(path_startswith(device->devname, "/dev/"));
925
926 *devname = device->devname;
927
928 return 0;
929 }
930
931 static int device_set_sysname(sd_device *device) {
932 _cleanup_free_ char *sysname = NULL;
933 const char *sysnum = NULL;
934 const char *pos;
935 size_t len = 0;
936
937 pos = strrchr(device->devpath, '/');
938 if (!pos)
939 return -EINVAL;
940 pos ++;
941
942 /* devpath is not a root directory */
943 if (*pos == '\0' || pos <= device->devpath)
944 return -EINVAL;
945
946 sysname = strdup(pos);
947 if (!sysname)
948 return -ENOMEM;
949
950 /* some devices have '!' in their name, change that to '/' */
951 while (sysname[len] != '\0') {
952 if (sysname[len] == '!')
953 sysname[len] = '/';
954
955 len ++;
956 }
957
958 /* trailing number */
959 while (len > 0 && isdigit(sysname[--len]))
960 sysnum = &sysname[len];
961
962 if (len == 0)
963 sysnum = NULL;
964
965 free(device->sysname);
966 device->sysname = sysname;
967 sysname = NULL;
968
969 device->sysnum = sysnum;
970
971 device->sysname_set = true;
972
973 return 0;
974 }
975
976 _public_ int sd_device_get_sysname(sd_device *device, const char **ret) {
977 int r;
978
979 assert_return(device, -EINVAL);
980 assert_return(ret, -EINVAL);
981
982 if (!device->sysname_set) {
983 r = device_set_sysname(device);
984 if (r < 0)
985 return r;
986 }
987
988 *ret = device->sysname;
989
990 return 0;
991 }
992
993 _public_ int sd_device_get_sysnum(sd_device *device, const char **ret) {
994 int r;
995
996 assert_return(device, -EINVAL);
997 assert_return(ret, -EINVAL);
998
999 if (!device->sysname_set) {
1000 r = device_set_sysname(device);
1001 if (r < 0)
1002 return r;
1003 }
1004
1005 *ret = device->sysnum;
1006
1007 return 0;
1008 }
1009
1010 static bool is_valid_tag(const char *tag) {
1011 assert(tag);
1012
1013 return !strchr(tag, ':') && !strchr(tag, ' ');
1014 }
1015
1016 int device_add_tag(sd_device *device, const char *tag) {
1017 int r;
1018
1019 assert(device);
1020 assert(tag);
1021
1022 if (!is_valid_tag(tag))
1023 return -EINVAL;
1024
1025 r = set_ensure_allocated(&device->tags, &string_hash_ops);
1026 if (r < 0)
1027 return r;
1028
1029 r = set_put_strdup(device->tags, tag);
1030 if (r < 0)
1031 return r;
1032
1033 device->tags_generation ++;
1034 device->property_tags_outdated = true;
1035
1036 return 0;
1037 }
1038
1039 int device_add_devlink(sd_device *device, const char *devlink) {
1040 int r;
1041
1042 assert(device);
1043 assert(devlink);
1044
1045 r = set_ensure_allocated(&device->devlinks, &string_hash_ops);
1046 if (r < 0)
1047 return r;
1048
1049 r = set_put_strdup(device->devlinks, devlink);
1050 if (r < 0)
1051 return r;
1052
1053 device->devlinks_generation ++;
1054 device->property_devlinks_outdated = true;
1055
1056 return 0;
1057 }
1058
1059 static int device_add_property_internal_from_string(sd_device *device, const char *str) {
1060 _cleanup_free_ char *key = NULL;
1061 char *value;
1062
1063 assert(device);
1064 assert(str);
1065
1066 key = strdup(str);
1067 if (!key)
1068 return -ENOMEM;
1069
1070 value = strchr(key, '=');
1071 if (!value)
1072 return -EINVAL;
1073
1074 *value = '\0';
1075
1076 if (isempty(++value))
1077 value = NULL;
1078
1079 return device_add_property_internal(device, key, value);
1080 }
1081
1082 int device_set_usec_initialized(sd_device *device, const char *initialized) {
1083 uint64_t usec_initialized;
1084 int r;
1085
1086 assert(device);
1087 assert(initialized);
1088
1089 r = safe_atou64(initialized, &usec_initialized);
1090 if (r < 0)
1091 return r;
1092
1093 r = device_add_property_internal(device, "USEC_INITIALIZED", initialized);
1094 if (r < 0)
1095 return r;
1096
1097 device->usec_initialized = usec_initialized;
1098
1099 return 0;
1100 }
1101
1102 static int handle_db_line(sd_device *device, char key, const char *value) {
1103 char *path;
1104 int r;
1105
1106 assert(device);
1107 assert(value);
1108
1109 switch (key) {
1110 case 'G':
1111 r = device_add_tag(device, value);
1112 if (r < 0)
1113 return r;
1114
1115 break;
1116 case 'S':
1117 path = strjoina("/dev/", value);
1118 r = device_add_devlink(device, path);
1119 if (r < 0)
1120 return r;
1121
1122 break;
1123 case 'E':
1124 r = device_add_property_internal_from_string(device, value);
1125 if (r < 0)
1126 return r;
1127
1128 break;
1129 case 'I':
1130 r = device_set_usec_initialized(device, value);
1131 if (r < 0)
1132 return r;
1133
1134 break;
1135 case 'L':
1136 r = safe_atoi(value, &device->devlink_priority);
1137 if (r < 0)
1138 return r;
1139
1140 break;
1141 case 'W':
1142 r = safe_atoi(value, &device->watch_handle);
1143 if (r < 0)
1144 return r;
1145
1146 break;
1147 default:
1148 log_debug("device db: unknown key '%c'", key);
1149 }
1150
1151 return 0;
1152 }
1153
1154 int device_get_id_filename(sd_device *device, const char **ret) {
1155 assert(device);
1156 assert(ret);
1157
1158 if (!device->id_filename) {
1159 _cleanup_free_ char *id = NULL;
1160 const char *subsystem;
1161 dev_t devnum;
1162 int ifindex, r;
1163
1164 r = sd_device_get_subsystem(device, &subsystem);
1165 if (r < 0)
1166 return r;
1167
1168 r = sd_device_get_devnum(device, &devnum);
1169 if (r < 0)
1170 return r;
1171
1172 r = sd_device_get_ifindex(device, &ifindex);
1173 if (r < 0)
1174 return r;
1175
1176 if (major(devnum) > 0) {
1177 /* use dev_t -- b259:131072, c254:0 */
1178 r = asprintf(&id, "%c%u:%u",
1179 streq(subsystem, "block") ? 'b' : 'c',
1180 major(devnum), minor(devnum));
1181 if (r < 0)
1182 return -errno;
1183 } else if (ifindex > 0) {
1184 /* use netdev ifindex -- n3 */
1185 r = asprintf(&id, "n%u", ifindex);
1186 if (r < 0)
1187 return -errno;
1188 } else {
1189 /* use $subsys:$sysname -- pci:0000:00:1f.2
1190 * sysname() has '!' translated, get it from devpath
1191 */
1192 const char *sysname;
1193
1194 sysname = basename(device->devpath);
1195 if (!sysname)
1196 return -EINVAL;
1197
1198 r = asprintf(&id, "+%s:%s", subsystem, sysname);
1199 if (r < 0)
1200 return -errno;
1201 }
1202
1203 device->id_filename = id;
1204 id = NULL;
1205 }
1206
1207 *ret = device->id_filename;
1208
1209 return 0;
1210 }
1211
1212 static int device_read_db(sd_device *device) {
1213 _cleanup_free_ char *db = NULL;
1214 char *path;
1215 const char *id, *value;
1216 char key;
1217 size_t db_len;
1218 unsigned i;
1219 int r;
1220
1221 enum {
1222 PRE_KEY,
1223 KEY,
1224 PRE_VALUE,
1225 VALUE,
1226 INVALID_LINE,
1227 } state = PRE_KEY;
1228
1229 if (device->db_loaded || device->sealed)
1230 return 0;
1231
1232 r = device_get_id_filename(device, &id);
1233 if (r < 0)
1234 return r;
1235
1236 path = strjoina("/run/udev/data/", id);
1237
1238 r = read_full_file(path, &db, &db_len);
1239 if (r < 0) {
1240 if (r == -ENOENT)
1241 return 0;
1242 else {
1243 log_debug("sd-device: failed to read db '%s': %s", path, strerror(-r));
1244 return r;
1245 }
1246 }
1247
1248 /* devices with a database entry are initialized */
1249 device->is_initialized = true;;
1250
1251 for (i = 0; i < db_len; i++) {
1252 switch (state) {
1253 case PRE_KEY:
1254 if (!strchr(NEWLINE, db[i])) {
1255 key = db[i];
1256
1257 state = KEY;
1258 }
1259
1260 break;
1261 case KEY:
1262 if (db[i] != ':') {
1263 log_debug("sd-device: ignoring invalid db entry with key '%c'", key);
1264
1265 state = INVALID_LINE;
1266 } else {
1267 db[i] = '\0';
1268
1269 state = PRE_VALUE;
1270 }
1271
1272 break;
1273 case PRE_VALUE:
1274 value = &db[i];
1275
1276 state = VALUE;
1277
1278 break;
1279 case INVALID_LINE:
1280 if (strchr(NEWLINE, db[i]))
1281 state = PRE_KEY;
1282
1283 break;
1284 case VALUE:
1285 if (strchr(NEWLINE, db[i])) {
1286 db[i] = '\0';
1287 r = handle_db_line(device, key, value);
1288 if (r < 0)
1289 log_debug("sd-device: failed to handle db entry '%c:%s': %s", key, value, strerror(-r));
1290
1291 state = PRE_KEY;
1292 }
1293
1294 break;
1295 default:
1296 assert_not_reached("invalid state when parsing db");
1297 }
1298 }
1299
1300 device->db_loaded = true;
1301
1302 return 0;
1303 }
1304
1305 _public_ int sd_device_get_is_initialized(sd_device *device, int *initialized) {
1306 int r;
1307
1308 assert_return(device, -EINVAL);
1309 assert_return(initialized, -EINVAL);
1310
1311 r = device_read_db(device);
1312 if (r < 0)
1313 return r;
1314
1315 *initialized = device->is_initialized;
1316
1317 return 0;
1318 }
1319
1320 _public_ int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *usec) {
1321 usec_t now_ts;
1322 int r;
1323
1324 assert_return(device, -EINVAL);
1325 assert_return(usec, -EINVAL);
1326
1327 r = device_read_db(device);
1328 if (r < 0)
1329 return r;
1330
1331 if (!device->is_initialized)
1332 return -EBUSY;
1333
1334 if (!device->usec_initialized)
1335 return -ENODATA;
1336
1337 now_ts = now(clock_boottime_or_monotonic());
1338
1339 if (now_ts < device->usec_initialized)
1340 return -EIO;
1341
1342 *usec = now_ts - device->usec_initialized;
1343
1344 return 0;
1345 }
1346
1347 _public_ const char *sd_device_get_tag_first(sd_device *device) {
1348 assert_return(device, NULL);
1349
1350 (void) device_read_db(device);
1351
1352 device->tags_iterator_generation = device->tags_generation;
1353 device->tags_iterator = ITERATOR_FIRST;
1354
1355 return set_iterate(device->tags, &device->tags_iterator);
1356 }
1357
1358 _public_ const char *sd_device_get_tag_next(sd_device *device) {
1359 assert_return(device, NULL);
1360
1361 (void) device_read_db(device);
1362
1363 if (device->tags_iterator_generation != device->tags_generation)
1364 return NULL;
1365
1366 return set_iterate(device->tags, &device->tags_iterator);
1367 }
1368
1369 _public_ const char *sd_device_get_devlink_first(sd_device *device) {
1370 assert_return(device, NULL);
1371
1372 (void) device_read_db(device);
1373
1374 device->devlinks_iterator_generation = device->devlinks_generation;
1375 device->devlinks_iterator = ITERATOR_FIRST;
1376
1377 return set_iterate(device->devlinks, &device->devlinks_iterator);
1378 }
1379
1380 _public_ const char *sd_device_get_devlink_next(sd_device *device) {
1381 assert_return(device, NULL);
1382
1383 (void) device_read_db(device);
1384
1385 if (device->devlinks_iterator_generation != device->devlinks_generation)
1386 return NULL;
1387
1388 return set_iterate(device->devlinks, &device->devlinks_iterator);
1389 }
1390
1391 static int device_properties_prepare(sd_device *device) {
1392 int r;
1393
1394 assert(device);
1395
1396 r = device_read_uevent_file(device);
1397 if (r < 0)
1398 return r;
1399
1400 r = device_read_db(device);
1401 if (r < 0)
1402 return r;
1403
1404 if (device->property_devlinks_outdated) {
1405 char *devlinks = NULL;
1406 const char *devlink;
1407
1408 devlink = sd_device_get_devlink_first(device);
1409 if (devlink)
1410 devlinks = strdupa(devlink);
1411
1412 while ((devlink = sd_device_get_devlink_next(device)))
1413 devlinks = strjoina(devlinks, " ", devlink);
1414
1415 r = device_add_property_internal(device, "DEVLINKS", devlinks);
1416 if (r < 0)
1417 return r;
1418
1419 device->property_devlinks_outdated = false;
1420 }
1421
1422 if (device->property_tags_outdated) {
1423 char *tags = NULL;
1424 const char *tag;
1425
1426 tag = sd_device_get_tag_first(device);
1427 if (tag)
1428 tags = strjoina(":", tag);
1429
1430 while ((tag = sd_device_get_tag_next(device)))
1431 tags = strjoina(tags, ":", tag);
1432
1433 tags = strjoina(tags, ":");
1434
1435 r = device_add_property_internal(device, "TAGS", tags);
1436 if (r < 0)
1437 return r;
1438
1439 device->property_tags_outdated = false;
1440 }
1441
1442 return 0;
1443 }
1444
1445 _public_ const char *sd_device_get_property_first(sd_device *device, const char **_value) {
1446 const char *key;
1447 const char *value;
1448 int r;
1449
1450 assert_return(device, NULL);
1451
1452 r = device_properties_prepare(device);
1453 if (r < 0)
1454 return NULL;
1455
1456 device->properties_iterator_generation = device->properties_generation;
1457 device->properties_iterator = ITERATOR_FIRST;
1458
1459 value = ordered_hashmap_iterate(device->properties, &device->properties_iterator, (const void**)&key);
1460
1461 if (_value)
1462 *_value = value;
1463
1464 return key;
1465 }
1466
1467 _public_ const char *sd_device_get_property_next(sd_device *device, const char **_value) {
1468 const char *key;
1469 const char *value;
1470 int r;
1471
1472 assert_return(device, NULL);
1473
1474 r = device_properties_prepare(device);
1475 if (r < 0)
1476 return NULL;
1477
1478 if (device->properties_iterator_generation != device->properties_generation)
1479 return NULL;
1480
1481 value = ordered_hashmap_iterate(device->properties, &device->properties_iterator, (const void**)&key);
1482
1483 if (_value)
1484 *_value = value;
1485
1486 return key;
1487 }
1488
1489 static int device_sysattrs_read_all(sd_device *device) {
1490 _cleanup_closedir_ DIR *dir = NULL;
1491 const char *syspath;
1492 struct dirent *dent;
1493 int r;
1494
1495 assert(device);
1496
1497 if (device->sysattrs_read)
1498 return 0;
1499
1500 r = sd_device_get_syspath(device, &syspath);
1501 if (r < 0)
1502 return r;
1503
1504 dir = opendir(syspath);
1505 if (!dir)
1506 return -errno;
1507
1508 r = set_ensure_allocated(&device->sysattrs, &string_hash_ops);
1509 if (r < 0)
1510 return r;
1511
1512 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
1513 char *path;
1514 struct stat statbuf;
1515
1516 /* only handle symlinks and regular files */
1517 if (dent->d_type != DT_LNK && dent->d_type != DT_REG)
1518 continue;
1519
1520 path = strjoina(syspath, "/", dent->d_name);
1521
1522 if (lstat(path, &statbuf) != 0)
1523 continue;
1524
1525 if (!(statbuf.st_mode & S_IRUSR))
1526 continue;
1527
1528 r = set_put_strdup(device->sysattrs, dent->d_name);
1529 if (r < 0)
1530 return r;
1531 }
1532
1533 device->sysattrs_read = true;
1534
1535 return 0;
1536 }
1537
1538 _public_ const char *sd_device_get_sysattr_first(sd_device *device) {
1539 int r;
1540
1541 assert_return(device, NULL);
1542
1543 if (!device->sysattrs_read) {
1544 r = device_sysattrs_read_all(device);
1545 if (r < 0) {
1546 errno = -r;
1547 return NULL;
1548 }
1549 }
1550
1551 device->sysattrs_iterator = ITERATOR_FIRST;
1552
1553 return set_iterate(device->sysattrs, &device->sysattrs_iterator);
1554 }
1555
1556 _public_ const char *sd_device_get_sysattr_next(sd_device *device) {
1557 assert_return(device, NULL);
1558
1559 if (!device->sysattrs_read)
1560 return NULL;
1561
1562 return set_iterate(device->sysattrs, &device->sysattrs_iterator);
1563 }
1564
1565 _public_ int sd_device_has_tag(sd_device *device, const char *tag) {
1566 assert_return(device, -EINVAL);
1567 assert_return(tag, -EINVAL);
1568
1569 (void) device_read_db(device);
1570
1571 return !!set_contains(device->tags, tag);
1572 }
1573
1574 _public_ int sd_device_get_property_value(sd_device *device, const char *key, const char **_value) {
1575 char *value;
1576 int r;
1577
1578 assert_return(device, -EINVAL);
1579 assert_return(key, -EINVAL);
1580 assert_return(_value, -EINVAL);
1581
1582 r = device_properties_prepare(device);
1583 if (r < 0)
1584 return r;
1585
1586 value = ordered_hashmap_get(device->properties, key);
1587 if (!value)
1588 return -ENOENT;
1589
1590 *_value = value;
1591
1592 return 0;
1593 }
1594
1595 /* replaces the value if it already exists */
1596 static int device_add_sysattr_value(sd_device *device, const char *_key, const char *_value) {
1597 _cleanup_free_ char *key = NULL;
1598 _cleanup_free_ char *value = NULL;
1599 int r;
1600
1601 assert(device);
1602 assert(_key);
1603
1604 r = hashmap_ensure_allocated(&device->sysattr_values, &string_hash_ops);
1605 if (r < 0)
1606 return r;
1607
1608 value = hashmap_remove2(device->sysattr_values, _key, (void **)&key);
1609 if (!key) {
1610 key = strdup(_key);
1611 if (!key)
1612 return -ENOMEM;
1613 }
1614
1615 free(value);
1616 value = NULL;
1617
1618 if (_value) {
1619 value = strdup(_value);
1620 if (!value)
1621 return -ENOMEM;
1622 }
1623
1624 r = hashmap_put(device->sysattr_values, key, value);
1625 if (r < 0)
1626 return r;
1627
1628 key = NULL;
1629 value = NULL;
1630
1631 return 0;
1632 }
1633
1634 static int device_get_sysattr_value(sd_device *device, const char *_key, const char **_value) {
1635 const char *key = NULL, *value;
1636
1637 assert(device);
1638 assert(_key);
1639
1640 value = hashmap_get2(device->sysattr_values, _key, (void **) &key);
1641 if (!key)
1642 return -ENOENT;
1643
1644 if (_value)
1645 *_value = value;
1646
1647 return 0;
1648 }
1649
1650 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1651 * with a NULL value in the cache, otherwise the returned string is stored */
1652 _public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value) {
1653 _cleanup_free_ char *value = NULL;
1654 const char *syspath, *cached_value = NULL;
1655 char *path;
1656 struct stat statbuf;
1657 int r;
1658
1659 assert_return(device, -EINVAL);
1660 assert_return(sysattr, -EINVAL);
1661
1662 /* look for possibly already cached result */
1663 r = device_get_sysattr_value(device, sysattr, &cached_value);
1664 if (r != -ENOENT) {
1665 if (r < 0)
1666 return r;
1667
1668 if (!cached_value)
1669 /* we looked up the sysattr before and it did not exist */
1670 return -ENOENT;
1671
1672 if (_value)
1673 *_value = cached_value;
1674
1675 return 0;
1676 }
1677
1678 r = sd_device_get_syspath(device, &syspath);
1679 if (r < 0)
1680 return r;
1681
1682 path = strjoina(syspath, "/", sysattr);
1683 r = lstat(path, &statbuf);
1684 if (r < 0) {
1685 /* remember that we could not access the sysattr */
1686 r = device_add_sysattr_value(device, sysattr, NULL);
1687 if (r < 0)
1688 return r;
1689
1690 return -ENOENT;
1691 } else if (S_ISLNK(statbuf.st_mode)) {
1692 /* Some core links return only the last element of the target path,
1693 * these are just values, the paths should not be exposed. */
1694 if (STR_IN_SET(sysattr, "driver", "subsystem", "module")) {
1695 r = readlink_value(path, &value);
1696 if (r < 0)
1697 return r;
1698 } else
1699 return -EINVAL;
1700 } else if (S_ISDIR(statbuf.st_mode)) {
1701 /* skip directories */
1702 return -EINVAL;
1703 } else if (!(statbuf.st_mode & S_IRUSR)) {
1704 /* skip non-readable files */
1705 return -EPERM;
1706 } else {
1707 size_t size;
1708
1709 /* read attribute value */
1710 r = read_full_file(path, &value, &size);
1711 if (r < 0)
1712 return r;
1713
1714 /* drop trailing newlines */
1715 while (size > 0 && value[--size] == '\n')
1716 value[size] = '\0';
1717 }
1718
1719 r = device_add_sysattr_value(device, sysattr, value);
1720 if (r < 0)
1721 return r;
1722
1723 *_value = value;
1724 value = NULL;
1725
1726 return 0;
1727 }
1728
1729 static void device_remove_sysattr_value(sd_device *device, const char *_key) {
1730 _cleanup_free_ char *key = NULL;
1731 _cleanup_free_ char *value = NULL;
1732
1733 assert(device);
1734 assert(_key);
1735
1736 value = hashmap_remove2(device->sysattr_values, _key, (void **) &key);
1737
1738 return;
1739 }
1740
1741 /* set the attribute and save it in the cache. If a NULL value is passed the
1742 * attribute is cleared from the cache */
1743 _public_ int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, char *value) {
1744 _cleanup_close_ int fd = -1;
1745 const char *syspath;
1746 char *path;
1747 struct stat statbuf;
1748 size_t value_len = 0;
1749 ssize_t size;
1750 int r;
1751
1752 assert_return(device, -EINVAL);
1753 assert_return(sysattr, -EINVAL);
1754
1755 if (!value) {
1756 device_remove_sysattr_value(device, sysattr);
1757
1758 return 0;
1759 }
1760
1761 r = sd_device_get_syspath(device, &syspath);
1762 if (r < 0)
1763 return r;
1764
1765 path = strjoina(syspath, "/", sysattr);
1766 r = lstat(path, &statbuf);
1767 if (r < 0) {
1768 r = device_add_sysattr_value(device, sysattr, "");
1769 if (r < 0)
1770 return r;
1771
1772 return -ENXIO;
1773 }
1774
1775 if (S_ISLNK(statbuf.st_mode))
1776 return -EINVAL;
1777
1778 /* skip directories */
1779 if (S_ISDIR(statbuf.st_mode))
1780 return -EISDIR;
1781
1782 /* skip non-readable files */
1783 if ((statbuf.st_mode & S_IRUSR) == 0)
1784 return -EACCES;
1785
1786 value_len = strlen(value);
1787
1788 /* drop trailing newlines */
1789 while (value_len > 0 && value[--value_len] == '\n')
1790 value[value_len] = '\0';
1791
1792 /* value length is limited to 4k */
1793 if (value_len > 4096)
1794 return -EINVAL;
1795
1796 fd = open(path, O_WRONLY | O_CLOEXEC);
1797 if (fd < 0)
1798 return -errno;
1799
1800 size = write(fd, value, value_len);
1801 if (size < 0)
1802 return -errno;
1803
1804 if ((size_t)size != value_len)
1805 return -EIO;
1806
1807 r = device_add_sysattr_value(device, sysattr, value);
1808 if (r < 0)
1809 return r;
1810
1811 return 0;
1812 }