Bug Summary

File:build-scan/../src/shared/sleep-config.c
Warning:line 281, column 18
Result of 'calloc' is converted to a pointer of type 'struct fiemap', which is incompatible with sizeof operand type 'struct fiemap_extent'

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 sleep-config.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/shared/libsystemd-shared-239.a.p -I src/shared -I ../src/shared -I src/basic -I ../src/basic -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 .. -I /usr/include/blkid -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/shared/sleep-config.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2/***
3 Copyright © 2018 Dell Inc.
4***/
5
6#include <errno(*__errno_location ()).h>
7#include <linux1/fs.h>
8#include <stdbool.h>
9#include <stddef.h>
10#include <stdio.h>
11#include <string.h>
12#include <syslog.h>
13#include <unistd.h>
14
15#include "alloc-util.h"
16#include "conf-parser.h"
17#include "def.h"
18#include "env-util.h"
19#include "fd-util.h"
20#include "fileio.h"
21#include "log.h"
22#include "macro.h"
23#include "parse-util.h"
24#include "path-util.h"
25#include "sleep-config.h"
26#include "string-util.h"
27#include "strv.h"
28
29int parse_sleep_config(const char *verb, char ***_modes, char ***_states, usec_t *_delay) {
30
31 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char
32 **suspend_mode = NULL((void*)0), **suspend_state = NULL((void*)0),
33 **hibernate_mode = NULL((void*)0), **hibernate_state = NULL((void*)0),
34 **hybrid_mode = NULL((void*)0), **hybrid_state = NULL((void*)0);
35 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **modes, **states; /* always initialized below */
36 usec_t delay = 180 * USEC_PER_MINUTE((usec_t) (60ULL*((usec_t) 1000000ULL)));
37
38 const ConfigTableItem items[] = {
39 { "Sleep", "SuspendMode", config_parse_strv, 0, &suspend_mode },
40 { "Sleep", "SuspendState", config_parse_strv, 0, &suspend_state },
41 { "Sleep", "HibernateMode", config_parse_strv, 0, &hibernate_mode },
42 { "Sleep", "HibernateState", config_parse_strv, 0, &hibernate_state },
43 { "Sleep", "HybridSleepMode", config_parse_strv, 0, &hybrid_mode },
44 { "Sleep", "HybridSleepState", config_parse_strv, 0, &hybrid_state },
45 { "Sleep", "HibernateDelaySec", config_parse_sec, 0, &delay},
46 {}
47 };
48
49 (void) config_parse_many_nulstr(PKGSYSCONFDIR"/etc/systemd" "/sleep.conf",
50 CONF_PATHS_NULSTR("systemd/sleep.conf.d")"/etc/" "systemd/sleep.conf.d" "\0" "/run/" "systemd/sleep.conf.d"
"\0" "/usr/local/lib/" "systemd/sleep.conf.d" "\0" "/usr/lib/"
"systemd/sleep.conf.d" "\0"
,
51 "Sleep\0", config_item_table_lookup, items,
52 CONFIG_PARSE_WARN, NULL((void*)0));
53
54 if (streq(verb, "suspend")(strcmp((verb),("suspend")) == 0)) {
55 /* empty by default */
56 modes = TAKE_PTR(suspend_mode)({ typeof(suspend_mode) _ptr_ = (suspend_mode); (suspend_mode
) = ((void*)0); _ptr_; })
;
57
58 if (suspend_state)
59 states = TAKE_PTR(suspend_state)({ typeof(suspend_state) _ptr_ = (suspend_state); (suspend_state
) = ((void*)0); _ptr_; })
;
60 else
61 states = strv_new("mem", "standby", "freeze", NULL((void*)0));
62
63 } else if (streq(verb, "hibernate")(strcmp((verb),("hibernate")) == 0)) {
64 if (hibernate_mode)
65 modes = TAKE_PTR(hibernate_mode)({ typeof(hibernate_mode) _ptr_ = (hibernate_mode); (hibernate_mode
) = ((void*)0); _ptr_; })
;
66 else
67 modes = strv_new("platform", "shutdown", NULL((void*)0));
68
69 if (hibernate_state)
70 states = TAKE_PTR(hibernate_state)({ typeof(hibernate_state) _ptr_ = (hibernate_state); (hibernate_state
) = ((void*)0); _ptr_; })
;
71 else
72 states = strv_new("disk", NULL((void*)0));
73
74 } else if (streq(verb, "hybrid-sleep")(strcmp((verb),("hybrid-sleep")) == 0)) {
75 if (hybrid_mode)
76 modes = TAKE_PTR(hybrid_mode)({ typeof(hybrid_mode) _ptr_ = (hybrid_mode); (hybrid_mode) =
((void*)0); _ptr_; })
;
77 else
78 modes = strv_new("suspend", "platform", "shutdown", NULL((void*)0));
79
80 if (hybrid_state)
81 states = TAKE_PTR(hybrid_state)({ typeof(hybrid_state) _ptr_ = (hybrid_state); (hybrid_state
) = ((void*)0); _ptr_; })
;
82 else
83 states = strv_new("disk", NULL((void*)0));
84
85 } else if (streq(verb, "suspend-then-hibernate")(strcmp((verb),("suspend-then-hibernate")) == 0))
86 modes = states = NULL((void*)0);
87 else
88 assert_not_reached("what verb")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, (
"what verb"), "../src/shared/sleep-config.c", 88, __PRETTY_FUNCTION__
); } while (0)
;
89
90 if ((!modes && STR_IN_SET(verb, "hibernate", "hybrid-sleep")(!!strv_find((((char**) ((const char*[]) { "hibernate", "hybrid-sleep"
, ((void*)0) }))), (verb)))
) ||
91 (!states && !streq(verb, "suspend-then-hibernate")(strcmp((verb),("suspend-then-hibernate")) == 0)))
92 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/shared/sleep-config.c"
, 92, __func__)
;
93
94 if (_modes)
95 *_modes = TAKE_PTR(modes)({ typeof(modes) _ptr_ = (modes); (modes) = ((void*)0); _ptr_
; })
;
96 if (_states)
97 *_states = TAKE_PTR(states)({ typeof(states) _ptr_ = (states); (states) = ((void*)0); _ptr_
; })
;
98 if (_delay)
99 *_delay = delay;
100
101 return 0;
102}
103
104int can_sleep_state(char **types) {
105 char **type;
106 int r;
107 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
108
109 if (strv_isempty(types))
110 return true1;
111
112 /* If /sys is read-only we cannot sleep */
113 if (access("/sys/power/state", W_OK2) < 0)
114 return false0;
115
116 r = read_one_line_file("/sys/power/state", &p);
117 if (r < 0)
118 return false0;
119
120 STRV_FOREACH(type, types)for ((type) = (types); (type) && *(type); (type)++) {
121 const char *word, *state;
122 size_t l, k;
123
124 k = strlen(*type);
125 FOREACH_WORD_SEPARATOR(word, l, p, WHITESPACE, state)for ((state) = (p), (word) = split(&(state), &(l), (" \t\n\r"
), (0)); (word); (word) = split(&(state), &(l), (" \t\n\r"
), (0)))
126 if (l == k && memcmp(word, *type, l) == 0)
127 return true1;
128 }
129
130 return false0;
131}
132
133int can_sleep_disk(char **types) {
134 char **type;
135 int r;
136 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
137
138 if (strv_isempty(types))
139 return true1;
140
141 /* If /sys is read-only we cannot sleep */
142 if (access("/sys/power/disk", W_OK2) < 0)
143 return false0;
144
145 r = read_one_line_file("/sys/power/disk", &p);
146 if (r < 0)
147 return false0;
148
149 STRV_FOREACH(type, types)for ((type) = (types); (type) && *(type); (type)++) {
150 const char *word, *state;
151 size_t l, k;
152
153 k = strlen(*type);
154 FOREACH_WORD_SEPARATOR(word, l, p, WHITESPACE, state)for ((state) = (p), (word) = split(&(state), &(l), (" \t\n\r"
), (0)); (word); (word) = split(&(state), &(l), (" \t\n\r"
), (0)))
{
155 if (l == k && memcmp(word, *type, l) == 0)
156 return true1;
157
158 if (l == k + 2 &&
159 word[0] == '[' &&
160 memcmp(word + 1, *type, l - 2) == 0 &&
161 word[l-1] == ']')
162 return true1;
163 }
164 }
165
166 return false0;
167}
168
169#define HIBERNATION_SWAP_THRESHOLD0.98 0.98
170
171int find_hibernate_location(char **device, char **type, size_t *size, size_t *used) {
172 _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f;
173 unsigned i;
174
175 f = fopen("/proc/swaps", "re");
176 if (!f) {
177 log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,({ int _level = ((((*__errno_location ()) == 2 ? 7 : 4))), _e
= ((0)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm
(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((
_realm) << 10 | (_level)), _e, "../src/shared/sleep-config.c"
, 178, __func__, "Failed to retrieve open /proc/swaps: %m") :
-abs(_e); })
178 "Failed to retrieve open /proc/swaps: %m")({ int _level = ((((*__errno_location ()) == 2 ? 7 : 4))), _e
= ((0)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm
(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((
_realm) << 10 | (_level)), _e, "../src/shared/sleep-config.c"
, 178, __func__, "Failed to retrieve open /proc/swaps: %m") :
-abs(_e); })
;
179 assert(errno > 0)do { if ((__builtin_expect(!!(!((*__errno_location ()) > 0
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("errno > 0"
), "../src/shared/sleep-config.c", 179, __PRETTY_FUNCTION__);
} while (0)
;
180 return -errno(*__errno_location ());
181 }
182
183 (void) fscanf(f, "%*s %*s %*s %*s %*s\n");
184
185 for (i = 1;; i++) {
186 _cleanup_free___attribute__((cleanup(freep))) char *dev_field = NULL((void*)0), *type_field = NULL((void*)0);
187 size_t size_field, used_field;
188 int k;
189
190 k = fscanf(f,
191 "%ms " /* device/file */
192 "%ms " /* type of swap */
193 "%zu " /* swap size */
194 "%zu " /* used */
195 "%*i\n", /* priority */
196 &dev_field, &type_field, &size_field, &used_field);
197 if (k != 4) {
198 if (k == EOF(-1))
199 break;
200
201 log_warning("Failed to parse /proc/swaps:%u", i)({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/sleep-config.c", 201, __func__, "Failed to parse /proc/swaps:%u"
, i) : -abs(_e); })
;
202 continue;
203 }
204
205 if (streq(type_field, "partition")(strcmp((type_field),("partition")) == 0)) {
206 if (endswith(dev_field, "\\040(deleted)")) {
207 log_warning("Ignoring deleted swapfile '%s'.", dev_field)({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/sleep-config.c", 207, __func__, "Ignoring deleted swapfile '%s'."
, dev_field) : -abs(_e); })
;
208 continue;
209 }
210
211 const char *fn;
212 fn = path_startswith(dev_field, "/dev/");
213 if (fn && startswith(fn, "zram")) {
214 log_debug("Ignoring compressed ram swap device '%s'.", dev_field)({ 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/shared/sleep-config.c", 214, __func__, "Ignoring compressed ram swap device '%s'."
, dev_field) : -abs(_e); })
;
215 continue;
216 }
217 }
218 if (device)
219 *device = TAKE_PTR(dev_field)({ typeof(dev_field) _ptr_ = (dev_field); (dev_field) = ((void
*)0); _ptr_; })
;
220 if (type)
221 *type = TAKE_PTR(type_field)({ typeof(type_field) _ptr_ = (type_field); (type_field) = ((
void*)0); _ptr_; })
;
222 if (size)
223 *size = size_field;
224 if (used)
225 *used = used_field;
226 return 0;
227 }
228
229 log_debug("No swap partitions were found.")({ 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/shared/sleep-config.c", 229, __func__, "No swap partitions were found."
) : -abs(_e); })
;
230 return -ENOSYS38;
231}
232
233static bool_Bool enough_swap_for_hibernation(void) {
234 _cleanup_free___attribute__((cleanup(freep))) char *active = NULL((void*)0);
235 unsigned long long act = 0;
236 size_t size = 0, used = 0;
237 int r;
238
239 if (getenv_bool("SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK") > 0)
240 return true1;
241
242 r = find_hibernate_location(NULL((void*)0), NULL((void*)0), &size, &used);
243 if (r < 0)
244 return false0;
245
246 r = get_proc_field("/proc/meminfo", "Active(anon)", WHITESPACE" \t\n\r", &active);
247 if (r < 0) {
248 log_error_errno(r, "Failed to retrieve Active(anon) from /proc/meminfo: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/sleep-config.c", 248, __func__, "Failed to retrieve Active(anon) from /proc/meminfo: %m"
) : -abs(_e); })
;
249 return false0;
250 }
251
252 r = safe_atollu(active, &act);
253 if (r < 0) {
254 log_error_errno(r, "Failed to parse Active(anon) from /proc/meminfo: %s: %m",({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/sleep-config.c", 255, __func__, "Failed to parse Active(anon) from /proc/meminfo: %s: %m"
, active) : -abs(_e); })
255 active)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/shared/sleep-config.c", 255, __func__, "Failed to parse Active(anon) from /proc/meminfo: %s: %m"
, active) : -abs(_e); })
;
256 return false0;
257 }
258
259 r = act <= (size - used) * HIBERNATION_SWAP_THRESHOLD0.98;
260 log_debug("Hibernation is %spossible, Active(anon)=%llu kB, size=%zu kB, used=%zu kB, threshold=%.2g%%",({ 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/shared/sleep-config.c", 261, __func__, "Hibernation is %spossible, Active(anon)=%llu kB, size=%zu kB, used=%zu kB, threshold=%.2g%%"
, r ? "" : "im", act, size, used, 100*0.98) : -abs(_e); })
261 r ? "" : "im", act, size, used, 100*HIBERNATION_SWAP_THRESHOLD)({ 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/shared/sleep-config.c", 261, __func__, "Hibernation is %spossible, Active(anon)=%llu kB, size=%zu kB, used=%zu kB, threshold=%.2g%%"
, r ? "" : "im", act, size, used, 100*0.98) : -abs(_e); })
;
262
263 return r;
264}
265
266int read_fiemap(int fd, struct fiemap **ret) {
267 _cleanup_free___attribute__((cleanup(freep))) struct fiemap *fiemap = NULL((void*)0), *result_fiemap = NULL((void*)0);
268 struct stat statinfo;
269 uint32_t result_extents = 0;
270 uint64_t fiemap_start = 0, fiemap_length;
271 const size_t n_extra = DIV_ROUND_UP(sizeof(struct fiemap), sizeof(struct fiemap_extent))({ const typeof((sizeof(struct fiemap))) __unique_prefix_X10 =
((sizeof(struct fiemap))); const typeof((sizeof(struct fiemap_extent
))) __unique_prefix_Y11 = ((sizeof(struct fiemap_extent))); (
__unique_prefix_X10 / __unique_prefix_Y11 + !!(__unique_prefix_X10
% __unique_prefix_Y11)); })
;
272 size_t fiemap_allocated = n_extra, result_fiemap_allocated = n_extra;
273
274 if (fstat(fd, &statinfo) < 0)
275 return log_debug_errno(errno, "Cannot determine file size: %m")({ 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/shared/sleep-config.c", 275, __func__
, "Cannot determine file size: %m") : -abs(_e); })
;
276 if (!S_ISREG(statinfo.st_mode)((((statinfo.st_mode)) & 0170000) == (0100000)))
277 return -ENOTTY25;
278 fiemap_length = statinfo.st_size;
279
280 /* Zero this out in case we run on a file with no extents */
281 fiemap = calloc(n_extra, sizeof(struct fiemap_extent));
Result of 'calloc' is converted to a pointer of type 'struct fiemap', which is incompatible with sizeof operand type 'struct fiemap_extent'
282 if (!fiemap)
283 return -ENOMEM12;
284
285 result_fiemap = malloc_multiply(n_extra, sizeof(struct fiemap_extent));
286 if (!result_fiemap)
287 return -ENOMEM12;
288
289 /* XFS filesystem has incorrect implementation of fiemap ioctl and
290 * returns extents for only one block-group at a time, so we need
291 * to handle it manually, starting the next fiemap call from the end
292 * of the last extent
293 */
294 while (fiemap_start < fiemap_length) {
295 *fiemap = (struct fiemap) {
296 .fm_start = fiemap_start,
297 .fm_length = fiemap_length,
298 .fm_flags = FIEMAP_FLAG_SYNC0x00000001,
299 };
300
301 /* Find out how many extents there are */
302 if (ioctl(fd, FS_IOC_FIEMAP(((2U|1U) << (((0 +8)+8)+14)) | ((('f')) << (0 +8
)) | (((11)) << 0) | ((((sizeof(struct fiemap)))) <<
((0 +8)+8)))
, fiemap) < 0)
303 return log_debug_errno(errno, "Failed to read extents: %m")({ 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/shared/sleep-config.c", 303, __func__
, "Failed to read extents: %m") : -abs(_e); })
;
304
305 /* Nothing to process */
306 if (fiemap->fm_mapped_extents == 0)
307 break;
308
309 /* Resize fiemap to allow us to read in the extents, result fiemap has to hold all
310 * the extents for the whole file. Add space for the initial struct fiemap. */
311 if (!greedy_realloc0((void**) &fiemap, &fiemap_allocated,
312 n_extra + fiemap->fm_mapped_extents, sizeof(struct fiemap_extent)))
313 return -ENOMEM12;
314
315 fiemap->fm_extent_count = fiemap->fm_mapped_extents;
316 fiemap->fm_mapped_extents = 0;
317
318 if (ioctl(fd, FS_IOC_FIEMAP(((2U|1U) << (((0 +8)+8)+14)) | ((('f')) << (0 +8
)) | (((11)) << 0) | ((((sizeof(struct fiemap)))) <<
((0 +8)+8)))
, fiemap) < 0)
319 return log_debug_errno(errno, "Failed to read extents: %m")({ 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/shared/sleep-config.c", 319, __func__
, "Failed to read extents: %m") : -abs(_e); })
;
320
321 /* Resize result_fiemap to allow us to copy in the extents */
322 if (!greedy_realloc((void**) &result_fiemap, &result_fiemap_allocated,
323 n_extra + result_extents + fiemap->fm_mapped_extents, sizeof(struct fiemap_extent)))
324 return -ENOMEM12;
325
326 memcpy(result_fiemap->fm_extents + result_extents,
327 fiemap->fm_extents,
328 sizeof(struct fiemap_extent) * fiemap->fm_mapped_extents);
329
330 result_extents += fiemap->fm_mapped_extents;
331
332 /* Highly unlikely that it is zero */
333 if (_likely_(fiemap->fm_mapped_extents > 0)(__builtin_expect(!!(fiemap->fm_mapped_extents > 0),1))) {
334 uint32_t i = fiemap->fm_mapped_extents - 1;
335
336 fiemap_start = fiemap->fm_extents[i].fe_logical +
337 fiemap->fm_extents[i].fe_length;
338
339 if (fiemap->fm_extents[i].fe_flags & FIEMAP_EXTENT_LAST0x00000001)
340 break;
341 }
342 }
343
344 memcpy(result_fiemap, fiemap, sizeof(struct fiemap));
345 result_fiemap->fm_mapped_extents = result_extents;
346 *ret = TAKE_PTR(result_fiemap)({ typeof(result_fiemap) _ptr_ = (result_fiemap); (result_fiemap
) = ((void*)0); _ptr_; })
;
347 return 0;
348}
349
350static bool_Bool can_s2h(void) {
351 const char *p;
352 int r;
353
354 r = access("/sys/class/rtc/rtc0/wakealarm", W_OK2);
355 if (r < 0) {
356 log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,({ int _level = ((((*__errno_location ()) == 2 ? 7 : 4))), _e
= ((0)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm
(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((
_realm) << 10 | (_level)), _e, "../src/shared/sleep-config.c"
, 357, __func__, "/sys/class/rct/rct0/wakealarm is not writable %m"
) : -abs(_e); })
357 "/sys/class/rct/rct0/wakealarm is not writable %m")({ int _level = ((((*__errno_location ()) == 2 ? 7 : 4))), _e
= ((0)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm
(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((
_realm) << 10 | (_level)), _e, "../src/shared/sleep-config.c"
, 357, __func__, "/sys/class/rct/rct0/wakealarm is not writable %m"
) : -abs(_e); })
;
358 return false0;
359 }
360
361 FOREACH_STRING(p, "suspend", "hibernate")for (char **_l = ({ char **_ll = ((char**) ((const char*[]) {
"suspend", "hibernate", ((void*)0) })); p = _ll ? _ll[0] : (
(void*)0); _ll; }); _l && *_l; p = ({ _l ++; _l[0]; }
))
{
362 r = can_sleep(p);
363 if (IN_SET(r, 0, -ENOSPC)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){0, -28})/sizeof(int)]; switch(r) { case 0
: case -28: _found = 1; break; default: break; } _found; })
) {
364 log_debug("Unable to %s system.", p)({ 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/shared/sleep-config.c", 364, __func__, "Unable to %s system."
, p) : -abs(_e); })
;
365 return false0;
366 }
367 if (r < 0)
368 return log_debug_errno(r, "Failed to check if %s is possible: %m", p)({ 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/shared/sleep-config.c", 368, __func__, "Failed to check if %s is possible: %m"
, p) : -abs(_e); })
;
369 }
370
371 return true1;
372}
373
374int can_sleep(const char *verb) {
375 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **modes = NULL((void*)0), **states = NULL((void*)0);
376 int r;
377
378 assert(STR_IN_SET(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate"))do { if ((__builtin_expect(!!(!((!!strv_find((((char**) ((const
char*[]) { "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate"
, ((void*)0) }))), (verb))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("STR_IN_SET(verb, \"suspend\", \"hibernate\", \"hybrid-sleep\", \"suspend-then-hibernate\")"
), "../src/shared/sleep-config.c", 378, __PRETTY_FUNCTION__);
} while (0)
;
379
380 if (streq(verb, "suspend-then-hibernate")(strcmp((verb),("suspend-then-hibernate")) == 0))
381 return can_s2h();
382
383 r = parse_sleep_config(verb, &modes, &states, NULL((void*)0));
384 if (r < 0)
385 return false0;
386
387 if (!can_sleep_state(states) || !can_sleep_disk(modes))
388 return false0;
389
390 if (streq(verb, "suspend")(strcmp((verb),("suspend")) == 0))
391 return true1;
392
393 if (!enough_swap_for_hibernation())
394 return -ENOSPC28;
395
396 return true1;
397}