18772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati/****************************************************************************** 28772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati * 38772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati * Copyright (C) 2014 Google, Inc. 48772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati * 58772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati * Licensed under the Apache License, Version 2.0 (the "License"); 68772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati * you may not use this file except in compliance with the License. 78772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati * You may obtain a copy of the License at: 88772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati * 98772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati * http://www.apache.org/licenses/LICENSE-2.0 108772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati * 118772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati * Unless required by applicable law or agreed to in writing, software 128772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati * distributed under the License is distributed on an "AS IS" BASIS, 138772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 148772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati * See the License for the specific language governing permissions and 158772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati * limitations under the License. 168772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati * 178772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati ******************************************************************************/ 188772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati 19d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati#define LOG_TAG "bt_osi_config" 20d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 2149a86709488e5cfd5e23759da18bf9613e15b04dMarie Janssen#include "osi/include/config.h" 2249a86709488e5cfd5e23759da18bf9613e15b04dMarie Janssen 23d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati#include <assert.h> 24d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati#include <ctype.h> 253fd6713276c37ffcec4e51afc21fa1514a10e0e7Elliott Hughes#include <errno.h> 263114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung#include <fcntl.h> 273114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung#include <libgen.h> 28d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati#include <stdio.h> 29d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati#include <stdlib.h> 30d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati#include <string.h> 31bb6836b8e3145522c119e9478d5c7e7df75c3890Arman Uguray#include <unistd.h> 324197cfdbd36d9f7f213df11b6fee795f22c867fdPavlin Radoslavov#include <sys/stat.h> 33d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 340f9b91e150e153229235c163861198e23600e636Sharvil Nanavati#include "osi/include/allocator.h" 350f9b91e150e153229235c163861198e23600e636Sharvil Nanavati#include "osi/include/list.h" 3644802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati#include "osi/include/log.h" 37d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 38d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatitypedef struct { 39d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati char *key; 40d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati char *value; 41d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} entry_t; 42d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 43d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatitypedef struct { 44d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati char *name; 45d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati list_t *entries; 46d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} section_t; 47d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 48d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatistruct config_t { 49d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati list_t *sections; 50d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati}; 51d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 5236c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati// Empty definition; this type is aliased to list_node_t. 5336c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavatistruct config_section_iter_t {}; 5436c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 559eb556804ae753b6fabc66329952dae596f378b7Ajay Panickerstatic bool config_parse(FILE *fp, config_t *config); 56d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 57d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatistatic section_t *section_new(const char *name); 58d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatistatic void section_free(void *ptr); 59d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatistatic section_t *section_find(const config_t *config, const char *section); 60d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 61d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatistatic entry_t *entry_new(const char *key, const char *value); 62d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatistatic void entry_free(void *ptr); 63d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatistatic entry_t *entry_find(const config_t *config, const char *section, const char *key); 64d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 657f280eb2f5f674e0329e21e0babe459a8b205b3fSharvil Nanavaticonfig_t *config_new_empty(void) { 66ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson config_t *config = osi_calloc(sizeof(config_t)); 67d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 68d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati config->sections = list_new(section_free); 6936c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati if (!config->sections) { 70db554581079863974af8e1289646f5deea6fc044Marie Janssen LOG_ERROR(LOG_TAG, "%s unable to allocate list for sections.", __func__); 7136c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati goto error; 7236c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati } 73d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 74d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return config; 7536c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 7636c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavatierror:; 77ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson config_free(config); 787f280eb2f5f674e0329e21e0babe459a8b205b3fSharvil Nanavati return NULL; 797f280eb2f5f674e0329e21e0babe459a8b205b3fSharvil Nanavati} 8036c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 81d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavaticonfig_t *config_new(const char *filename) { 82d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(filename != NULL); 83d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 847f280eb2f5f674e0329e21e0babe459a8b205b3fSharvil Nanavati config_t *config = config_new_empty(); 857f280eb2f5f674e0329e21e0babe459a8b205b3fSharvil Nanavati if (!config) 86d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return NULL; 87d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 887f280eb2f5f674e0329e21e0babe459a8b205b3fSharvil Nanavati FILE *fp = fopen(filename, "rt"); 897f280eb2f5f674e0329e21e0babe459a8b205b3fSharvil Nanavati if (!fp) { 90db554581079863974af8e1289646f5deea6fc044Marie Janssen LOG_ERROR(LOG_TAG, "%s unable to open file '%s': %s", __func__, filename, strerror(errno)); 917f280eb2f5f674e0329e21e0babe459a8b205b3fSharvil Nanavati config_free(config); 92d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return NULL; 93d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 949eb556804ae753b6fabc66329952dae596f378b7Ajay Panicker 959eb556804ae753b6fabc66329952dae596f378b7Ajay Panicker if (!config_parse(fp, config)) { 969eb556804ae753b6fabc66329952dae596f378b7Ajay Panicker config_free(config); 979eb556804ae753b6fabc66329952dae596f378b7Ajay Panicker config = NULL; 989eb556804ae753b6fabc66329952dae596f378b7Ajay Panicker } 999eb556804ae753b6fabc66329952dae596f378b7Ajay Panicker 100d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati fclose(fp); 101d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return config; 102d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 103d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 104da576af1312568c4892e6b217d89a82897d60d91Marie Janssenconfig_t *config_new_clone(const config_t *src) { 105b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen assert(src != NULL); 106b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen 107b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen config_t *ret = config_new_empty(); 108b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen 109b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen assert(ret != NULL); 110b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen 111b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen for (const list_node_t *node = list_begin(src->sections); 112b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen node != list_end(src->sections); 113b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen node = list_next(node)) { 114b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen section_t *sec = list_node(node); 115b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen 116b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen for (const list_node_t *node_entry = list_begin(sec->entries); 117b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen node_entry != list_end(sec->entries); 118b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen node_entry = list_next(node_entry)) { 119b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen entry_t *entry = list_node(node_entry); 120b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen 121b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen config_set_string(ret, sec->name, entry->key, entry->value); 122b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen } 123b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen } 124b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen 125b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen return ret; 126b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen} 127b9d28c30f9ef9f8f046bb08238abef9cba445be6Marie Janssen 128d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavativoid config_free(config_t *config) { 129d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (!config) 130d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return; 131d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 132d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati list_free(config->sections); 133ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson osi_free(config); 134d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 135d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 136d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatibool config_has_section(const config_t *config, const char *section) { 137d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(config != NULL); 138d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(section != NULL); 139d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 140d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return (section_find(config, section) != NULL); 141d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 142d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 143d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatibool config_has_key(const config_t *config, const char *section, const char *key) { 144d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(config != NULL); 145d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(section != NULL); 146d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(key != NULL); 147d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 148d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return (entry_find(config, section, key) != NULL); 149d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 150d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 151d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatiint config_get_int(const config_t *config, const char *section, const char *key, int def_value) { 152d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(config != NULL); 153d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(section != NULL); 154d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(key != NULL); 155d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 156d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati entry_t *entry = entry_find(config, section, key); 157d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (!entry) 158d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return def_value; 159d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 160d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati char *endptr; 161d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati int ret = strtol(entry->value, &endptr, 0); 162d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return (*endptr == '\0') ? ret : def_value; 163d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 164d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 165d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatibool config_get_bool(const config_t *config, const char *section, const char *key, bool def_value) { 166d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(config != NULL); 167d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(section != NULL); 168d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(key != NULL); 169d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 170d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati entry_t *entry = entry_find(config, section, key); 171d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (!entry) 172d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return def_value; 173d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 174d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (!strcmp(entry->value, "true")) 175d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return true; 176d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (!strcmp(entry->value, "false")) 177d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return false; 178d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 179d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return def_value; 180d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 181d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 182d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavaticonst char *config_get_string(const config_t *config, const char *section, const char *key, const char *def_value) { 183d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(config != NULL); 184d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(section != NULL); 185d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(key != NULL); 186d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 187d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati entry_t *entry = entry_find(config, section, key); 188d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (!entry) 189d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return def_value; 190d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 191d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return entry->value; 192d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 193d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 194d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavativoid config_set_int(config_t *config, const char *section, const char *key, int value) { 195d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(config != NULL); 196d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(section != NULL); 197d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(key != NULL); 198d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 199d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati char value_str[32] = { 0 }; 200d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati sprintf(value_str, "%d", value); 201d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati config_set_string(config, section, key, value_str); 202d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 203d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 204d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavativoid config_set_bool(config_t *config, const char *section, const char *key, bool value) { 205d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(config != NULL); 206d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(section != NULL); 207d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(key != NULL); 208d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 209d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati config_set_string(config, section, key, value ? "true" : "false"); 210d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 211d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 212d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavativoid config_set_string(config_t *config, const char *section, const char *key, const char *value) { 213d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati section_t *sec = section_find(config, section); 214d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (!sec) { 215d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati sec = section_new(section); 216d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati list_append(config->sections, sec); 217d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 218d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 219d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati for (const list_node_t *node = list_begin(sec->entries); node != list_end(sec->entries); node = list_next(node)) { 220d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati entry_t *entry = list_node(node); 221d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (!strcmp(entry->key, key)) { 222ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson osi_free(entry->value); 223ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson entry->value = osi_strdup(value); 224d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return; 225d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 226d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 227d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 228d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati entry_t *entry = entry_new(key, value); 229d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati list_append(sec->entries, entry); 230d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 231d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 23236c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavatibool config_remove_section(config_t *config, const char *section) { 23336c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati assert(config != NULL); 23436c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati assert(section != NULL); 23536c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 23636c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati section_t *sec = section_find(config, section); 23736c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati if (!sec) 23836c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati return false; 23936c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 24036c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati return list_remove(config->sections, sec); 24136c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati} 24236c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 24336c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavatibool config_remove_key(config_t *config, const char *section, const char *key) { 24436c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati assert(config != NULL); 24536c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati assert(section != NULL); 24636c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati assert(key != NULL); 24736c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 24836c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati section_t *sec = section_find(config, section); 24936c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati entry_t *entry = entry_find(config, section, key); 25036c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati if (!sec || !entry) 25136c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati return false; 25236c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 25336c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati return list_remove(sec->entries, entry); 25436c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati} 25536c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 25636c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavaticonst config_section_node_t *config_section_begin(const config_t *config) { 25736c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati assert(config != NULL); 25836c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati return (const config_section_node_t *)list_begin(config->sections); 25936c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati} 26036c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 26136c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavaticonst config_section_node_t *config_section_end(const config_t *config) { 26236c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati assert(config != NULL); 26336c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati return (const config_section_node_t *)list_end(config->sections); 26436c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati} 26536c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 26636c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavaticonst config_section_node_t *config_section_next(const config_section_node_t *node) { 26736c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati assert(node != NULL); 26836c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati return (const config_section_node_t *)list_next((const list_node_t *)node); 26936c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati} 27036c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 27136c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavaticonst char *config_section_name(const config_section_node_t *node) { 27236c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati assert(node != NULL); 27336c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati const list_node_t *lnode = (const list_node_t *)node; 27436c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati const section_t *section = (const section_t *)list_node(lnode); 27536c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati return section->name; 27636c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati} 27736c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 27836c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavatibool config_save(const config_t *config, const char *filename) { 27936c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati assert(config != NULL); 28036c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati assert(filename != NULL); 28136c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati assert(*filename != '\0'); 28236c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 2833114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung // Steps to ensure content of config file gets to disk: 2843114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung // 2853114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung // 1) Open and write to temp file (e.g. bt_config.conf.new). 2863114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung // 2) Sync the temp file to disk with fsync(). 2873114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung // 3) Rename temp file to actual config file (e.g. bt_config.conf). 2883114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung // This ensures atomic update. 2893114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung // 4) Sync directory that has the conf file with fsync(). 2903114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung // This ensures directory entries are up-to-date. 2913114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung int dir_fd = -1; 2923114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung FILE *fp = NULL; 2933114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung 2943114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung // Build temp config file based on config file (e.g. bt_config.conf.new). 2953114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung static const char *temp_file_ext = ".new"; 2963114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung const int filename_len = strlen(filename); 2973114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung const int temp_filename_len = filename_len + strlen(temp_file_ext) + 1; 2983114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung char *temp_filename = osi_calloc(temp_filename_len); 2993114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung snprintf(temp_filename, temp_filename_len, "%s%s", filename, temp_file_ext); 3003114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung 3013114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung // Extract directory from file path (e.g. /data/misc/bluedroid). 3023114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung char *temp_dirname = osi_strdup(filename); 3033114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung const char *directoryname = dirname(temp_dirname); 3043114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung if (!directoryname) { 3053114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung LOG_ERROR(LOG_TAG, "%s error extracting directory from '%s': %s", __func__, filename, strerror(errno)); 3063114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung goto error; 3073114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung } 30836c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 3093114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung dir_fd = open(directoryname, O_RDONLY); 3103114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung if (dir_fd < 0) { 3113114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung LOG_ERROR(LOG_TAG, "%s unable to open dir '%s': %s", __func__, directoryname, strerror(errno)); 3123114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung goto error; 3133114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung } 3148772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati 3153114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung fp = fopen(temp_filename, "wt"); 3168772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati if (!fp) { 317db554581079863974af8e1289646f5deea6fc044Marie Janssen LOG_ERROR(LOG_TAG, "%s unable to write file '%s': %s", __func__, temp_filename, strerror(errno)); 3188772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati goto error; 3198772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati } 3208772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati 32136c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati for (const list_node_t *node = list_begin(config->sections); node != list_end(config->sections); node = list_next(node)) { 32236c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati const section_t *section = (const section_t *)list_node(node); 323fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski if (fprintf(fp, "[%s]\n", section->name) < 0) { 324fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski LOG_ERROR(LOG_TAG, "%s unable to write to file '%s': %s", __func__, temp_filename, strerror(errno)); 325ed2267a0a66b1aec52d9039bc20a6c5099dbdae7Alain Vongsouvanh goto error; 326fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski } 32736c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 32836c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati for (const list_node_t *enode = list_begin(section->entries); enode != list_end(section->entries); enode = list_next(enode)) { 32936c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati const entry_t *entry = (const entry_t *)list_node(enode); 330fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski if (fprintf(fp, "%s = %s\n", entry->key, entry->value) < 0) { 331fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski LOG_ERROR(LOG_TAG, "%s unable to write to file '%s': %s", __func__, temp_filename, strerror(errno)); 332ed2267a0a66b1aec52d9039bc20a6c5099dbdae7Alain Vongsouvanh goto error; 333fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski } 33436c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati } 33536c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 33636c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati // Only add a separating newline if there are more sections. 337fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski if (list_next(node) != list_end(config->sections)) { 338fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski if (fputc('\n', fp) == EOF) { 339fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski LOG_ERROR(LOG_TAG, "%s unable to write to file '%s': %s", __func__, temp_filename, strerror(errno)); 340ed2267a0a66b1aec52d9039bc20a6c5099dbdae7Alain Vongsouvanh goto error; 341fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski } 342fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski } 34336c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati } 34436c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 3453114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung // Sync written temp file out to disk. fsync() is blocking until data makes it to disk. 3463114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung if (fsync(fileno(fp)) < 0) { 3473114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung LOG_WARN(LOG_TAG, "%s unable to fsync file '%s': %s", __func__, temp_filename, strerror(errno)); 3483114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung } 3493114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung 350fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski if (fclose(fp) == EOF) { 351fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski LOG_ERROR(LOG_TAG, "%s unable to close file '%s': %s", __func__, temp_filename, strerror(errno)); 352fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski goto error; 353fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski } 354ed2267a0a66b1aec52d9039bc20a6c5099dbdae7Alain Vongsouvanh fp = NULL; 3558772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati 3564197cfdbd36d9f7f213df11b6fee795f22c867fdPavlin Radoslavov // Change the file's permissions to Read/Write by User and Group 3574197cfdbd36d9f7f213df11b6fee795f22c867fdPavlin Radoslavov if (chmod(temp_filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) == -1) { 3581dffda3bb0c946be415fb3ceabb337694abdf488Marie Janssen LOG_ERROR(LOG_TAG, "%s unable to change file permissions '%s': %s", __func__, filename, strerror(errno)); 3594197cfdbd36d9f7f213df11b6fee795f22c867fdPavlin Radoslavov goto error; 3604197cfdbd36d9f7f213df11b6fee795f22c867fdPavlin Radoslavov } 3614197cfdbd36d9f7f213df11b6fee795f22c867fdPavlin Radoslavov 3623114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung // Rename written temp file to the actual config file. 3638772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati if (rename(temp_filename, filename) == -1) { 364db554581079863974af8e1289646f5deea6fc044Marie Janssen LOG_ERROR(LOG_TAG, "%s unable to commit file '%s': %s", __func__, filename, strerror(errno)); 3658772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati goto error; 3668772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati } 3678772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati 3683114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung // This should ensure the directory is updated as well. 3693114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung if (fsync(dir_fd) < 0) { 3703114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung LOG_WARN(LOG_TAG, "%s unable to fsync dir '%s': %s", __func__, directoryname, strerror(errno)); 3713114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung } 3723114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung 3733114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung if (close(dir_fd) < 0) { 3743114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung LOG_ERROR(LOG_TAG, "%s unable to close dir '%s': %s", __func__, directoryname, strerror(errno)); 3753114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung goto error; 3763114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung } 3773114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung 3788772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati osi_free(temp_filename); 3793114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung osi_free(temp_dirname); 38036c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati return true; 3818772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati 3823114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheungerror: 3833114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung // This indicates there is a write issue. Unlink as partial data is not acceptable. 3848772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati unlink(temp_filename); 3853114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung if (fp) 3863114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung fclose(fp); 3873114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung if (dir_fd != -1) 3883114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung close(dir_fd); 3898772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati osi_free(temp_filename); 3903114ad623ca39bf6cbcee7f4841c00077faafcbaJacky Cheung osi_free(temp_dirname); 3918772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati return false; 39236c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati} 39336c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 394d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatistatic char *trim(char *str) { 395d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati while (isspace(*str)) 396d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati ++str; 397d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 398d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (!*str) 399d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return str; 400d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 401d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati char *end_str = str + strlen(str) - 1; 402d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati while (end_str > str && isspace(*end_str)) 403d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati --end_str; 404d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 405d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati end_str[1] = '\0'; 406d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return str; 407d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 408d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 4099eb556804ae753b6fabc66329952dae596f378b7Ajay Panickerstatic bool config_parse(FILE *fp, config_t *config) { 410d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(fp != NULL); 411d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati assert(config != NULL); 412d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 413d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati int line_num = 0; 414d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati char line[1024]; 415d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati char section[1024]; 416d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati strcpy(section, CONFIG_DEFAULT_SECTION); 417d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 418d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati while (fgets(line, sizeof(line), fp)) { 419d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati char *line_ptr = trim(line); 420d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati ++line_num; 421d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 422d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati // Skip blank and comment lines. 423d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (*line_ptr == '\0' || *line_ptr == '#') 424d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati continue; 425d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 426d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (*line_ptr == '[') { 427d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati size_t len = strlen(line_ptr); 428d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (line_ptr[len - 1] != ']') { 429db554581079863974af8e1289646f5deea6fc044Marie Janssen LOG_DEBUG(LOG_TAG, "%s unterminated section name on line %d.", __func__, line_num); 4309eb556804ae753b6fabc66329952dae596f378b7Ajay Panicker return false; 431d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 432d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati strncpy(section, line_ptr + 1, len - 2); 433d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati section[len - 2] = '\0'; 434d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } else { 435d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati char *split = strchr(line_ptr, '='); 436d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (!split) { 437db554581079863974af8e1289646f5deea6fc044Marie Janssen LOG_DEBUG(LOG_TAG, "%s no key/value separator found on line %d.", __func__, line_num); 4389eb556804ae753b6fabc66329952dae596f378b7Ajay Panicker return false; 439d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 440d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 441d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati *split = '\0'; 442d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati config_set_string(config, section, trim(line_ptr), trim(split + 1)); 443d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 444d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 4459eb556804ae753b6fabc66329952dae596f378b7Ajay Panicker return true; 446d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 447d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 448d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatistatic section_t *section_new(const char *name) { 449ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson section_t *section = osi_calloc(sizeof(section_t)); 450d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 451ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson section->name = osi_strdup(name); 452d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati section->entries = list_new(entry_free); 453d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return section; 454d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 455d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 456d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatistatic void section_free(void *ptr) { 457d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (!ptr) 458d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return; 459d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 460d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati section_t *section = ptr; 461ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson osi_free(section->name); 462d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati list_free(section->entries); 463ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson osi_free(section); 464d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 465d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 466d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatistatic section_t *section_find(const config_t *config, const char *section) { 467d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati for (const list_node_t *node = list_begin(config->sections); node != list_end(config->sections); node = list_next(node)) { 468d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati section_t *sec = list_node(node); 469d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (!strcmp(sec->name, section)) 470d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return sec; 471d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 472d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 473d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return NULL; 474d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 475d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 476d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatistatic entry_t *entry_new(const char *key, const char *value) { 477ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson entry_t *entry = osi_calloc(sizeof(entry_t)); 478d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 479ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson entry->key = osi_strdup(key); 480ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson entry->value = osi_strdup(value); 481d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return entry; 482d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 483d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 484d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatistatic void entry_free(void *ptr) { 485d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (!ptr) 486d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return; 487d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 488d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati entry_t *entry = ptr; 489ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson osi_free(entry->key); 490ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson osi_free(entry->value); 491ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson osi_free(entry); 492d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 493d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 494d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatistatic entry_t *entry_find(const config_t *config, const char *section, const char *key) { 495d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati section_t *sec = section_find(config, section); 496d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (!sec) 497d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return NULL; 498d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 499d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati for (const list_node_t *node = list_begin(sec->entries); node != list_end(sec->entries); node = list_next(node)) { 500d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati entry_t *entry = list_node(node); 501d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (!strcmp(entry->key, key)) 502d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return entry; 503d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 504d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 505d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return NULL; 506d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 507