Bug Summary

File:battstat/battstat-upower.c
Warning:line 96, column 17
Value stored to 'cancellable' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name battstat-upower.c -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 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/battstat -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/cafe-panel-4.0/libcafe-panel-applet -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libpng16 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/libupower-glib -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I ./apmlib/ -D G_LOG_DOMAIN="battstat_applet" -D BATTSTAT_MENU_UI_DIR="/usr/share/cafe/ui" -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/battstat -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-04-16-120712-85887-1 -x c battstat-upower.c
1/*
2 * Copyright (C) 2010 by Joachim Breitner <mail@joachim-breitner.de>
3 *
4 * Based on battstat-hal.c:
5 * Copyright (C) 2005 by Ryan Lortie <desrt@desrt.ca>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 * $Id$
22 */
23
24#include <config.h>
25
26#ifdef HAVE_UPOWER1
27
28#include <upower.h>
29#include <math.h>
30
31#include "battstat-upower.h"
32
33static UpClient *upc;
34static void (*status_updated_callback) (void);
35
36
37/* status_updated_callback() can not be called directly because at the time of
38 * the device-remove signal, the device is not actually removed from the list
39 * of devices known to the up_client object (see libupower-glib/up-client.c in
40 * upower). Waiting for the next idle timer works around this issue and has has
41 * the additionaly benefit of possibly running status_updated_callback only
42 * once when several events happen very soon after each other.
43 */
44static gboolean status_update_scheduled;
45
46static gboolean
47update_status_idle (gpointer junk)
48{
49 if (status_updated_callback)
50 status_updated_callback ();
51
52 return status_update_scheduled = FALSE(0);
53}
54
55static void
56schedule_status_callback (void)
57{
58 if (status_update_scheduled)
59 return;
60
61 status_update_scheduled = TRUE(!(0));
62 g_idle_add (update_status_idle, NULL((void*)0));
63}
64
65static void
66device_cb (UpClient *client, UpDevice *device, gpointer user_data) {
67 schedule_status_callback();
68}
69
70#if UP_CHECK_VERSION (0, 99, 0)((1) > (0) || ((1) == (0) && (90) > (99)) || ((
1) == (0) && (90) == (99) && (2) >= (0)))
71static void
72device_removed_cb (UpClient *client, const gchar *object_path, gpointer user_data) {
73 schedule_status_callback();
74}
75#endif
76
77/* ---- public functions ---- */
78
79char *
80battstat_upower_initialise (void (*callback) (void))
81{
82 char *error_str;
83 int i, num;
84
85 status_updated_callback = callback;
86#if UP_CHECK_VERSION (0, 99, 0)((1) > (0) || ((1) == (0) && (90) > (99)) || ((
1) == (0) && (90) == (99) && (2) >= (0)))
87 GPtrArray *devices;
88#endif
89
90 if( upc != NULL((void*)0) )
91 return g_strdup( "Already initialised!" )g_strdup_inline ("Already initialised!");
92
93 if( (upc = up_client_new() ) == NULL((void*)0) )
94 goto error_out;
95
96 GCancellable *cancellable = g_cancellable_new();
Value stored to 'cancellable' during its initialization is never read
97 GError *gerror;
98
99#if UP_CHECK_VERSION(0, 99, 0)((1) > (0) || ((1) == (0) && (90) > (99)) || ((
1) == (0) && (90) == (99) && (2) >= (0)))
100 devices = up_client_get_devices2(upc);
101 if (!devices) {
102 goto error_shutdownclient;
103 }
104 g_ptr_array_unref(devices);
105#else
106 if (! up_client_enumerate_devices_sync( upc, cancellable, &gerror ) ) {
107 sprintf(error_str, "Unable to enumerate upower devices: %s\n", gerror->message);
108 goto error_shutdownclient;
109 }
110#endif
111
112 g_signal_connect_after( upc, "device-added", G_CALLBACK (device_cb), NULL )g_signal_connect_data ((upc), ("device-added"), (((GCallback)
(device_cb))), (((void*)0)), ((void*)0), G_CONNECT_AFTER)
;
113#if UP_CHECK_VERSION(0, 99, 0)((1) > (0) || ((1) == (0) && (90) > (99)) || ((
1) == (0) && (90) == (99) && (2) >= (0)))
114 g_signal_connect_after( upc, "device-removed", G_CALLBACK (device_removed_cb), NULL )g_signal_connect_data ((upc), ("device-removed"), (((GCallback
) (device_removed_cb))), (((void*)0)), ((void*)0), G_CONNECT_AFTER
)
;
115#else
116 g_signal_connect_after( upc, "device-changed", G_CALLBACK (device_cb), NULL )g_signal_connect_data ((upc), ("device-changed"), (((GCallback
) (device_cb))), (((void*)0)), ((void*)0), G_CONNECT_AFTER)
;
117 g_signal_connect_after( upc, "device-removed", G_CALLBACK (device_cb), NULL )g_signal_connect_data ((upc), ("device-removed"), (((GCallback
) (device_cb))), (((void*)0)), ((void*)0), G_CONNECT_AFTER)
;
118#endif
119
120 return NULL((void*)0);
121
122error_shutdownclient:
123 g_object_unref( upc );
124 upc = NULL((void*)0);
125
126error_out:
127 return "Can not initialize upower";
128}
129
130void
131battstat_upower_cleanup( void )
132{
133 if( upc == NULL((void*)0) )
134 return;
135
136 g_object_unref( upc );
137 upc = NULL((void*)0);
138}
139
140#include "battstat.h"
141
142/* This function currently exists to allow the multiple batteries supported
143 * by the upower backend to appear as a single composite battery device (since
144 * at the current time this is all that battstat supports).
145 *
146 * This entire function is filled with logic to make multiple batteries
147 * appear as one "composite" battery. Comments included as appropriate.
148 *
149 * For more information about some of the assumptions made in the following
150 * code please see the following mailing list post and the resulting thread:
151 *
152 * http://lists.freedesktop.org/archives/hal/2005-July/002841.html
153 */
154void
155battstat_upower_get_battery_info( BatteryStatus *status )
156{
157
158 GPtrArray *devices = up_client_get_devices2( upc );
159
160 /* The calculation to get overall percentage power remaining is as follows:
161 *
162 * Sum( Current charges ) / Sum( Full Capacities )
163 *
164 * We can't just take an average of all of the percentages since this
165 * doesn't deal with the case that one battery might have a larger
166 * capacity than the other.
167 *
168 * In order to do this calculation, we need to keep a running total of
169 * current charge and full capacities.
170 */
171 double current_charge_total = 0, full_capacity_total = 0;
172
173 /* Record the time remaining as reported by upower. This is used in the event
174 * that the system has exactly one battery (since, then, upower is capable
175 * of providing an accurate time remaining report and we should trust it.)
176 */
177 gint64 remaining_time = 0;
178
179 /* The total (dis)charge rate of the system is the sum of the rates of
180 * the individual batteries.
181 */
182 double rate_total = 0;
183
184 /* We need to know if we should report the composite battery as present
185 * at all. The logic is that if at least one actual battery is installed
186 * then the composite battery will be reported to exist.
187 */
188 int present = 0;
189
190 /* We need to know if we are on AC power or not. Eventually, we can look
191 * at the AC adaptor upower devices to determine that. For now, we assume that
192 * if any battery is discharging then we must not be on AC power. Else, by
193 * default, we must be on AC.
194 */
195 int on_ac_power = 1;
196
197 /* Finally, we consider the composite battery to be "charging" if at least
198 * one of the actual batteries in the system is charging.
199 */
200 int charging = 0;
201
202 /* A list iterator. */
203 GSList *item;
204
205 /* For each physical battery bay... */
206 int i;
207 for( i = 0; i < devices->len; i++ )
208 {
209 UpDevice *upd = g_ptr_array_index( devices, i )((devices)->pdata)[i];
210
211 int type, state;
212 double current_charge, full_capacity, rate;
213 gint64 time_to_full, time_to_empty;
214
215 g_object_get( upd,
216 "kind", &type,
217 "state", &state,
218 "energy", &current_charge,
219 "energy-full", &full_capacity,
220 "energy-rate", &rate,
221 "time-to-full", &time_to_full,
222 "time-to-empty", &time_to_empty,
223 NULL((void*)0) );
224
225 /* Only count batteries here */
226
227 if (type != UP_DEVICE_KIND_BATTERY)
228 continue;
229
230 /* At least one battery present -> composite battery is present. */
231 present++;
232
233 /* At least one battery charging -> composite battery is charging. */
234 if( state == UP_DEVICE_STATE_CHARGING )
235 charging = 1;
236
237 /* At least one battery is discharging -> we're not on AC. */
238 if( state == UP_DEVICE_STATE_DISCHARGING )
239 on_ac_power = 0;
240
241 /* Sum the totals for current charge, design capacity, (dis)charge rate. */
242 current_charge_total += current_charge;
243 full_capacity_total += full_capacity;
244 rate_total += rate;
245
246 /* Record remaining time too, incase this is the only battery. */
247 remaining_time = (state == UP_DEVICE_STATE_DISCHARGING ? time_to_empty : time_to_full);
248 }
249
250 if( !present || full_capacity_total <= 0 || (charging && !on_ac_power) )
251 {
252 /* Either no battery is present or something has gone horribly wrong.
253 * In either case we must return that the composite battery is not
254 * present.
255 */
256 status->present = FALSE(0);
257 status->percent = 0;
258 status->minutes = -1;
259 status->on_ac_power = TRUE(!(0));
260 status->charging = FALSE(0);
261
262 g_ptr_array_unref( devices );
263 return;
264 }
265
266 /* Else, our composite battery is present. */
267 status->present = TRUE(!(0));
268
269 /* As per above, overall charge is:
270 *
271 * Sum( Current charges ) / Sum( Full Capacities )
272 */
273 status->percent = ( current_charge_total / full_capacity_total ) * 100.0 + 0.5;
274
275 if( present == 1 )
276 {
277 /* In the case of exactly one battery, report the time remaining figure
278 * from upower directly since it might have come from an authorative source
279 * (ie: the PMU or APM subsystem).
280 *
281 * upower gives remaining time in seconds with a 0 to mean that the
282 * remaining time is unknown. Battstat uses minutes and -1 for
283 * unknown time remaining.
284 */
285
286 if( remaining_time == 0 )
287 status->minutes = -1;
288 else
289 status->minutes = (remaining_time + 30) / 60;
290 }
291 /* Rest of cases to deal with multiple battery systems... */
292 else if( !on_ac_power && rate_total != 0 )
293 {
294 /* Then we're discharging. Calculate time remaining until at zero. */
295
296 double remaining;
297
298 remaining = current_charge_total;
299 remaining /= rate_total;
300 status->minutes = (int) floor( remaining * 60.0 + 0.5 );
301 }
302 else if( charging && rate_total != 0 )
303 {
304 /* Calculate time remaining until charged. For systems with more than
305 * one battery, this code is very approxicafe. The assumption is that if
306 * one battery reaches full charge before the other that the other will
307 * start charging faster due to the increase in available power (similar
308 * to how a laptop will charge faster if you're not using it).
309 */
310
311 double remaining;
312
313 remaining = full_capacity_total - current_charge_total;
314 if( remaining < 0 )
315 remaining = 0;
316 remaining /= rate_total;
317
318 status->minutes = (int) floor( remaining * 60.0 + 0.5 );
319 }
320 else
321 {
322 /* On AC power and not charging -or- rate is unknown. */
323 status->minutes = -1;
324 }
325
326 /* These are simple and well-explained above. */
327 status->charging = charging;
328 status->on_ac_power = on_ac_power;
329
330 g_ptr_array_unref( devices );
331}
332
333void
334error_dialog( const char *fmt , ...)
335{
336 va_list ap;
337 va_start(ap, fmt)__builtin_va_start(ap, fmt);
338 char str[1000];
339 vsprintf(str, fmt, ap);
340 va_end(ap)__builtin_va_end(ap);
341 CtkWidget *dialog;
342
343 dialog = ctk_message_dialog_new( NULL((void*)0), 0, CTK_MESSAGE_ERROR,
344 CTK_BUTTONS_OK, "%s", str);
345
346 g_signal_connect_swapped( G_OBJECT (dialog), "response",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((dialog)), (((GType) ((20) << (2)))
)))))), ("response"), (((GCallback) (ctk_widget_destroy))), (
((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), (((GType) ((20) << (2))))))))), ((void*)
0), G_CONNECT_SWAPPED)
347 G_CALLBACK (ctk_widget_destroy),g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((dialog)), (((GType) ((20) << (2)))
)))))), ("response"), (((GCallback) (ctk_widget_destroy))), (
((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), (((GType) ((20) << (2))))))))), ((void*)
0), G_CONNECT_SWAPPED)
348 G_OBJECT (dialog) )g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((dialog)), (((GType) ((20) << (2)))
)))))), ("response"), (((GCallback) (ctk_widget_destroy))), (
((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), (((GType) ((20) << (2))))))))), ((void*)
0), G_CONNECT_SWAPPED)
;
349
350 ctk_widget_show_all( dialog );
351}
352
353#endif /* HAVE_UPOWER */