* [BlueZ 4/5] main: Use _cleanup_() to simplify configuration parsing
2026-05-06 9:14 [BlueZ 0/5] Add helper for "cleanup" variable attribute Bastien Nocera
` (2 preceding siblings ...)
2026-05-06 9:14 ` [BlueZ 3/5] doc: Recommend using _cleanup_ and friends Bastien Nocera
@ 2026-05-06 9:14 ` Bastien Nocera
2026-05-06 9:14 ` [BlueZ 5/5] main: Use _cleanup_() to simplify GError-handling Bastien Nocera
4 siblings, 0 replies; 7+ messages in thread
From: Bastien Nocera @ 2026-05-06 9:14 UTC (permalink / raw)
To: linux-bluetooth
Makes dealing with the error path easier.
---
src/main.c | 70 ++++++++++++++++--------------------------------------
1 file changed, 20 insertions(+), 50 deletions(-)
diff --git a/src/main.c b/src/main.c
index 8aa19a3e3346..3a2c3e645a74 100644
--- a/src/main.c
+++ b/src/main.c
@@ -462,7 +462,7 @@ static bool parse_config_int(GKeyFile *config, const char *group,
size_t min, size_t max)
{
size_t tmp;
- char *str = NULL;
+ _cleanup_(g_free) char *str = NULL;
char *endptr = NULL;
if (!parse_config_string(config, group, key, &str))
@@ -471,25 +471,21 @@ static bool parse_config_int(GKeyFile *config, const char *group,
tmp = strtol(str, &endptr, 0);
if (!endptr || *endptr != '\0') {
error("%s.%s = %s is not integer", group, key, str);
- g_free(str);
return false;
}
if (tmp < min) {
- g_free(str);
warn("%s.%s = %zu is out of range (< %zu)", group, key, tmp,
min);
return false;
}
if (tmp > max) {
- g_free(str);
warn("%s.%s = %zu is out of range (> %zu)", group, key, tmp,
max);
return false;
}
- g_free(str);
if (val)
*val = tmp;
@@ -500,10 +496,9 @@ static bool parse_config_signed_int(GKeyFile *config, const char *group,
const char *key, int8_t *val,
long min, long max)
{
- char *str = NULL;
+ _cleanup_(g_free) char *str = NULL;
char *endptr = NULL;
long tmp;
- bool result = false;
str = g_key_file_get_string(config, group, key, NULL);
if (!str)
@@ -512,28 +507,24 @@ static bool parse_config_signed_int(GKeyFile *config, const char *group,
tmp = strtol(str, &endptr, 0);
if (!endptr || *endptr != '\0') {
warn("%s.%s = %s is not integer", group, key, str);
- goto cleanup;
+ return false;
}
if (tmp < min) {
warn("%s.%s = %ld is out of range (< %ld)", group, key, tmp,
min);
- goto cleanup;
+ return false;
}
if (tmp > max) {
warn("%s.%s = %ld is out of range (> %ld)", group, key, tmp,
max);
- goto cleanup;
+ return false;
}
if (val)
*val = (int8_t) tmp;
- result = true;
-
-cleanup:
- g_free(str);
- return result;
+ return true;
}
struct config_param {
@@ -915,7 +906,7 @@ static bool parse_config_bool(GKeyFile *config, const char *group,
static void parse_privacy(GKeyFile *config)
{
- char *str = NULL;
+ _cleanup_(g_free) char *str = NULL;
if (!parse_config_string(config, "General", "Privacy", &str)) {
btd_opts.privacy = 0x00;
@@ -948,13 +939,11 @@ static void parse_privacy(GKeyFile *config)
DBG("Invalid privacy option: %s", str);
btd_opts.privacy = 0x00;
}
-
- g_free(str);
}
static void parse_repairing(GKeyFile *config)
{
- char *str = NULL;
+ _cleanup_(g_free) char *str = NULL;
if (!parse_config_string(config, "General", "JustWorksRepairing",
&str)) {
@@ -963,13 +952,12 @@ static void parse_repairing(GKeyFile *config)
}
btd_opts.jw_repairing = parse_jw_repairing(str);
- g_free(str);
}
static bool parse_config_hex(GKeyFile *config, char *group,
const char *key, uint32_t *val)
{
- char *str = NULL;
+ _cleanup_(g_free) char *str = NULL;
if (!parse_config_string(config, group, key, &str))
return false;
@@ -977,37 +965,34 @@ static bool parse_config_hex(GKeyFile *config, char *group,
if (val)
*val = strtol(str, NULL, 16);
- g_free(str);
return true;
}
static void parse_device_id(GKeyFile *config)
{
- char *str = NULL;
+ _cleanup_(g_free) char *str = NULL;
parse_config_string(config, "General", "DeviceID", &str);
if (!str)
return;
parse_did(str);
- g_free(str);
}
static void parse_ctrl_mode(GKeyFile *config)
{
- char *str = NULL;
+ _cleanup_(g_free) char *str = NULL;
parse_config_string(config, "General", "ControllerMode", &str);
if (!str)
return;
btd_opts.mode = get_mode(str);
- g_free(str);
}
static void parse_multi_profile(GKeyFile *config)
{
- char *str = NULL;
+ _cleanup_(g_free) char *str = NULL;
parse_config_string(config, "General", "MultiProfile", &str);
if (!str)
@@ -1019,8 +1004,6 @@ static void parse_multi_profile(GKeyFile *config)
btd_opts.mps = MPS_MULTIPLE;
else
btd_opts.mps = MPS_OFF;
-
- g_free(str);
}
static gboolean parse_kernel_experimental(const char *key, const char *value,
@@ -1043,20 +1026,18 @@ static gboolean parse_kernel_experimental(const char *key, const char *value,
static void parse_kernel_exp(GKeyFile *config)
{
- char *str = NULL;
+ _cleanup_(g_free) char *str = NULL;
if (!parse_config_string(config, "General", "KernelExperimental",
&str))
return;
parse_kernel_experimental(NULL, str, NULL, NULL);
-
- g_free(str);
}
static void parse_secure_conns(GKeyFile *config)
{
- char *str = NULL;
+ _cleanup_(g_free) char *str = NULL;
if (!parse_config_string(config, "General", "SecureConnections",
&str))
@@ -1068,8 +1049,6 @@ static void parse_secure_conns(GKeyFile *config)
btd_opts.secure_conn = SC_ON;
else if (!strcmp(str, "only"))
btd_opts.secure_conn = SC_ONLY;
-
- g_free(str);
}
static void parse_general(GKeyFile *config)
@@ -1120,14 +1099,13 @@ static void parse_general(GKeyFile *config)
static void parse_gatt_cache(GKeyFile *config)
{
- char *str = NULL;
+ _cleanup_(g_free) char *str = NULL;
parse_config_string(config, "GATT", "Cache", &str);
if (!str)
return;
btd_opts.gatt_cache = parse_gatt_cache_str(str);
- g_free(str);
}
static enum bt_gatt_export_t parse_gatt_export_str(const char *str)
@@ -1147,14 +1125,13 @@ static enum bt_gatt_export_t parse_gatt_export_str(const char *str)
static void parse_gatt_export(GKeyFile *config)
{
- char *str = NULL;
+ _cleanup_(g_free) char *str = NULL;
parse_config_string(config, "GATT", "ExportClaimedServices", &str);
if (!str)
return;
btd_opts.gatt_export = parse_gatt_export_str(str);
- g_free(str);
}
static uint8_t parse_gatt_seclevel_str(const char *str)
@@ -1176,7 +1153,7 @@ static uint8_t parse_gatt_seclevel_str(const char *str)
static void parse_gatt_seclevel(GKeyFile *config)
{
- char *str = NULL;
+ _cleanup_(g_free) char *str = NULL;
if (!btd_opts.testing)
return;
@@ -1186,7 +1163,6 @@ static void parse_gatt_seclevel(GKeyFile *config)
return;
btd_opts.gatt_seclevel = parse_gatt_seclevel_str(str);
- g_free(str);
}
static void parse_gatt(GKeyFile *config)
@@ -1204,7 +1180,7 @@ static void parse_gatt(GKeyFile *config)
static void parse_csis_sirk(GKeyFile *config)
{
- char *str = NULL;
+ _cleanup_(g_free) char *str = NULL;
if (!parse_config_string(config, "CSIS", "SIRK", &str))
return;
@@ -1213,8 +1189,6 @@ static void parse_csis_sirk(GKeyFile *config)
hex2bin(str, btd_opts.csis.sirk, sizeof(btd_opts.csis.sirk));
else if (!gen_sirk(str))
DBG("Unable to generate SIRK from string");
-
- g_free(str);
}
static void parse_csis(GKeyFile *config)
@@ -1305,7 +1279,7 @@ static void parse_le_cs_config(GKeyFile *config)
static void parse_avdtp_session_mode(GKeyFile *config)
{
- char *str = NULL;
+ _cleanup_(g_free) char *str = NULL;
if (!parse_config_string(config, "AVDTP", "SessionMode", &str))
return;
@@ -1318,13 +1292,11 @@ static void parse_avdtp_session_mode(GKeyFile *config)
DBG("Invalid mode option: %s", str);
btd_opts.avdtp.session_mode = BT_IO_MODE_BASIC;
}
-
- g_free(str);
}
static void parse_avdtp_stream_mode(GKeyFile *config)
{
- char *str = NULL;
+ _cleanup_(g_free) char *str = NULL;
if (!parse_config_string(config, "AVDTP", "StreamMode", &str))
return;
@@ -1337,8 +1309,6 @@ static void parse_avdtp_stream_mode(GKeyFile *config)
DBG("Invalid mode option: %s", str);
btd_opts.avdtp.stream_mode = BT_IO_MODE_BASIC;
}
-
- g_free(str);
}
static void parse_avdtp(GKeyFile *config)
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [BlueZ 5/5] main: Use _cleanup_() to simplify GError-handling
2026-05-06 9:14 [BlueZ 0/5] Add helper for "cleanup" variable attribute Bastien Nocera
` (3 preceding siblings ...)
2026-05-06 9:14 ` [BlueZ 4/5] main: Use _cleanup_() to simplify configuration parsing Bastien Nocera
@ 2026-05-06 9:14 ` Bastien Nocera
4 siblings, 0 replies; 7+ messages in thread
From: Bastien Nocera @ 2026-05-06 9:14 UTC (permalink / raw)
To: linux-bluetooth
Use _cleanup_() to simplify GError-handling in the error paths.
---
src/main.c | 29 ++++++++++++-----------------
1 file changed, 12 insertions(+), 17 deletions(-)
diff --git a/src/main.c b/src/main.c
index 3a2c3e645a74..a2fe3ffdc914 100644
--- a/src/main.c
+++ b/src/main.c
@@ -205,6 +205,12 @@ static const struct group_table {
{ }
};
+static inline void free_error(void *err) {
+ g_error_free(*(void**) err);
+}
+
+#define _cleanup_error_ _cleanup_(free_error)
+
static int8_t check_sirk_alpha_numeric(char *str)
{
int8_t val = 0;
@@ -252,7 +258,7 @@ GKeyFile *btd_get_main_conf(void)
static GKeyFile *load_config(const char *name)
{
- GError *err = NULL;
+ _cleanup_error_ GError *err = NULL;
GKeyFile *keyfile;
int len;
@@ -285,7 +291,6 @@ static GKeyFile *load_config(const char *name)
if (!g_error_matches(err, G_FILE_ERROR, G_FILE_ERROR_NOENT))
error("Parsing %s failed: %s", main_conf_file_path,
err->message);
- g_error_free(err);
g_key_file_free(keyfile);
return NULL;
}
@@ -436,14 +441,13 @@ static int get_mode(const char *str)
static bool parse_config_string(GKeyFile *config, const char *group,
const char *key, char **val)
{
- GError *err = NULL;
+ _cleanup_error_ GError *err = NULL;
char *tmp;
tmp = g_key_file_get_string(config, group, key, &err);
if (err) {
if (err->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND)
DBG("%s", err->message);
- g_error_free(err);
return false;
}
@@ -885,14 +889,13 @@ static bool parse_config_u8(GKeyFile *config, const char *group,
static bool parse_config_bool(GKeyFile *config, const char *group,
const char *key, bool *val)
{
- GError *err = NULL;
+ _cleanup_error_ GError *err = NULL;
gboolean tmp;
tmp = g_key_file_get_boolean(config, group, key, &err);
if (err) {
if (err->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND)
DBG("%s", err->message);
- g_error_free(err);
return false;
}
@@ -1205,8 +1208,8 @@ static void parse_csis(GKeyFile *config)
static bool parse_cs_role(GKeyFile *config, const char *group,
const char *key, uint8_t *val)
{
- GError *err = NULL;
- char *str = NULL;
+ _cleanup_error_ GError *err = NULL;
+ _cleanup_(g_free) char *str = NULL;
char *endptr = NULL;
int numeric_val;
@@ -1215,7 +1218,6 @@ static bool parse_cs_role(GKeyFile *config, const char *group,
if (err) {
if (err->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND)
DBG("%s", err->message);
- g_error_free(err);
return false;
}
@@ -1225,17 +1227,14 @@ static bool parse_cs_role(GKeyFile *config, const char *group,
if (!strcmp(str, "Initiator") || !strcmp(str, "initiator")) {
if (val)
*val = 1;
- g_free(str);
return true;
} else if (!strcmp(str, "Reflector") || !strcmp(str, "reflector")) {
if (val)
*val = 2;
- g_free(str);
return true;
} else if (!strcmp(str, "Both") || !strcmp(str, "both")) {
if (val)
*val = 3;
- g_free(str);
return true;
}
@@ -1246,7 +1245,6 @@ static bool parse_cs_role(GKeyFile *config, const char *group,
warn("%s.%s = %s is not a valid value. "
"Expected: 1/Initiator, 2/Reflector, or 3/Both",
group, key, str);
- g_free(str);
return false;
}
@@ -1254,14 +1252,12 @@ static bool parse_cs_role(GKeyFile *config, const char *group,
warn("%s.%s = %d is out of range. "
"Valid values: 1 (Initiator), 2 (Reflector), 3 (Both)",
group, key, numeric_val);
- g_free(str);
return false;
}
if (val)
*val = numeric_val;
- g_free(str);
return true;
}
@@ -1575,7 +1571,7 @@ static GOptionEntry options[] = {
int main(int argc, char *argv[])
{
GOptionContext *context;
- GError *err = NULL;
+ _cleanup_error_ GError *err = NULL;
uint16_t sdp_mtu = 0;
uint32_t sdp_flags = 0;
int gdbus_flags = 0;
@@ -1588,7 +1584,6 @@ int main(int argc, char *argv[])
if (g_option_context_parse(context, &argc, &argv, &err) == FALSE) {
if (err != NULL) {
g_printerr("%s\n", err->message);
- g_error_free(err);
} else
g_printerr("An unknown error occurred\n");
exit(1);
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread