Bug Summary

File:build-scan/../src/libsystemd/sd-device/sd-device.c
Warning:line 1826, column 9
Value stored to 'value' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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