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 23f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He#include <base/logging.h> 24d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati#include <ctype.h> 253fd6713276c37ffcec4e51afc21fa1514a10e0e7Elliott Hughes#include <errno.h> 2695dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung#include <fcntl.h> 2795dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung#include <libgen.h> 28d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati#include <stdio.h> 29d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati#include <stdlib.h> 30d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati#include <string.h> 314197cfdbd36d9f7f213df11b6fee795f22c867fdPavlin Radoslavov#include <sys/stat.h> 32b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson#include <unistd.h> 33d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 340f9b91e150e153229235c163861198e23600e636Sharvil Nanavati#include "osi/include/allocator.h" 350f9b91e150e153229235c163861198e23600e636Sharvil Nanavati#include "osi/include/list.h" 3644802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati#include "osi/include/log.h" 377f8bfcc35285ca6e93a4436699bc95c13b920cafHansong Zhang#include "log/log.h" 38d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 39d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatitypedef struct { 40b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson char* key; 41b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson char* value; 42d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} entry_t; 43d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 44d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatitypedef struct { 45b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson char* name; 46b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson list_t* entries; 47d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} section_t; 48d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 49d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavatistruct config_t { 50b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson list_t* sections; 51d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati}; 52d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 5336c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati// Empty definition; this type is aliased to list_node_t. 5436c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavatistruct config_section_iter_t {}; 5536c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 56b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonstatic bool config_parse(FILE* fp, config_t* config); 57d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 58b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonstatic section_t* section_new(const char* name); 59b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonstatic void section_free(void* ptr); 60b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonstatic section_t* section_find(const config_t* config, const char* section); 61d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 62b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonstatic entry_t* entry_new(const char* key, const char* value); 63b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonstatic void entry_free(void* ptr); 64b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonstatic entry_t* entry_find(const config_t* config, const char* section, 65b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson const char* key); 66d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 67b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonconfig_t* config_new_empty(void) { 68b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson config_t* config = static_cast<config_t*>(osi_calloc(sizeof(config_t))); 69d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 70d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati config->sections = list_new(section_free); 7136c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati if (!config->sections) { 72db554581079863974af8e1289646f5deea6fc044Marie Janssen LOG_ERROR(LOG_TAG, "%s unable to allocate list for sections.", __func__); 7336c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati goto error; 7436c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati } 75d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 76d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return config; 7736c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 7836c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavatierror:; 79ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson config_free(config); 807f280eb2f5f674e0329e21e0babe459a8b205b3fSharvil Nanavati return NULL; 817f280eb2f5f674e0329e21e0babe459a8b205b3fSharvil Nanavati} 8236c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 83b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonconfig_t* config_new(const char* filename) { 84f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(filename != NULL); 85d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 86b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson config_t* config = config_new_empty(); 87b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (!config) return NULL; 88d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 89b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson FILE* fp = fopen(filename, "rt"); 907f280eb2f5f674e0329e21e0babe459a8b205b3fSharvil Nanavati if (!fp) { 91b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson LOG_ERROR(LOG_TAG, "%s unable to open file '%s': %s", __func__, filename, 92b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson strerror(errno)); 937f280eb2f5f674e0329e21e0babe459a8b205b3fSharvil Nanavati config_free(config); 94d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return NULL; 95d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 9672a183d00c7534c80a4deb9fb41d38fd9e9455f6Ajay Panicker 9772a183d00c7534c80a4deb9fb41d38fd9e9455f6Ajay Panicker if (!config_parse(fp, config)) { 9872a183d00c7534c80a4deb9fb41d38fd9e9455f6Ajay Panicker config_free(config); 9972a183d00c7534c80a4deb9fb41d38fd9e9455f6Ajay Panicker config = NULL; 10072a183d00c7534c80a4deb9fb41d38fd9e9455f6Ajay Panicker } 10172a183d00c7534c80a4deb9fb41d38fd9e9455f6Ajay Panicker 102d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati fclose(fp); 103d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return config; 104d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 105d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 106b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonconfig_t* config_new_clone(const config_t* src) { 107f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(src != NULL); 108d9ebc239abf77a1133c3456db84444ccbc8d0fddMarie Janssen 109b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson config_t* ret = config_new_empty(); 110d9ebc239abf77a1133c3456db84444ccbc8d0fddMarie Janssen 111f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(ret != NULL); 112d9ebc239abf77a1133c3456db84444ccbc8d0fddMarie Janssen 113b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson for (const list_node_t* node = list_begin(src->sections); 114b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson node != list_end(src->sections); node = list_next(node)) { 115b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson section_t* sec = static_cast<section_t*>(list_node(node)); 116d9ebc239abf77a1133c3456db84444ccbc8d0fddMarie Janssen 117b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson for (const list_node_t* node_entry = list_begin(sec->entries); 118d9ebc239abf77a1133c3456db84444ccbc8d0fddMarie Janssen node_entry != list_end(sec->entries); 119d9ebc239abf77a1133c3456db84444ccbc8d0fddMarie Janssen node_entry = list_next(node_entry)) { 120b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson entry_t* entry = static_cast<entry_t*>(list_node(node_entry)); 121d9ebc239abf77a1133c3456db84444ccbc8d0fddMarie Janssen 122d9ebc239abf77a1133c3456db84444ccbc8d0fddMarie Janssen config_set_string(ret, sec->name, entry->key, entry->value); 123d9ebc239abf77a1133c3456db84444ccbc8d0fddMarie Janssen } 124d9ebc239abf77a1133c3456db84444ccbc8d0fddMarie Janssen } 125d9ebc239abf77a1133c3456db84444ccbc8d0fddMarie Janssen 126d9ebc239abf77a1133c3456db84444ccbc8d0fddMarie Janssen return ret; 127d9ebc239abf77a1133c3456db84444ccbc8d0fddMarie Janssen} 128d9ebc239abf77a1133c3456db84444ccbc8d0fddMarie Janssen 129b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonvoid config_free(config_t* config) { 130b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (!config) return; 131d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 132d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati list_free(config->sections); 133ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson osi_free(config); 134d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 135d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 136b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonbool config_has_section(const config_t* config, const char* section) { 137f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(config != NULL); 138f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(section != NULL); 139d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 140d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return (section_find(config, section) != NULL); 141d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 142d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 143b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonbool config_has_key(const config_t* config, const char* section, 144b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson const char* key) { 145f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(config != NULL); 146f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(section != NULL); 147f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(key != NULL); 148d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 149d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return (entry_find(config, section, key) != NULL); 150d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 151d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 152b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonint config_get_int(const config_t* config, const char* section, const char* key, 153b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson int def_value) { 154f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(config != NULL); 155f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(section != NULL); 156f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(key != NULL); 157d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 158b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson entry_t* entry = entry_find(config, section, key); 159b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (!entry) return def_value; 160d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 161b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson char* endptr; 162d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati int ret = strtol(entry->value, &endptr, 0); 163d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return (*endptr == '\0') ? ret : def_value; 164d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 165d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 166b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonbool config_get_bool(const config_t* config, const char* section, 167b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson const char* key, bool def_value) { 168f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(config != NULL); 169f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(section != NULL); 170f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(key != NULL); 171d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 172b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson entry_t* entry = entry_find(config, section, key); 173b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (!entry) return def_value; 174d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 175b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (!strcmp(entry->value, "true")) return true; 176b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (!strcmp(entry->value, "false")) return false; 177d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 178d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return def_value; 179d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 180d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 181b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonconst char* config_get_string(const config_t* config, const char* section, 182b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson const char* key, const char* def_value) { 183f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(config != NULL); 184f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(section != NULL); 185f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(key != NULL); 186d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 187b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson entry_t* entry = entry_find(config, section, key); 188b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (!entry) return def_value; 189d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 190d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return entry->value; 191d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 192d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 193b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonvoid config_set_int(config_t* config, const char* section, const char* key, 194b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson int value) { 195f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(config != NULL); 196f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(section != NULL); 197f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(key != NULL); 198d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 199b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson char value_str[32] = {0}; 20080d7f60680f483a71e413f2453ab20013aff5c5cGeorge Burgess IV snprintf(value_str, sizeof(value_str), "%d", value); 201d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati config_set_string(config, section, key, value_str); 202d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 203d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 204b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonvoid config_set_bool(config_t* config, const char* section, const char* key, 205b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson bool value) { 206f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(config != NULL); 207f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(section != NULL); 208f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(key != NULL); 209d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 210d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati config_set_string(config, section, key, value ? "true" : "false"); 211d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 212d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 213b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonvoid config_set_string(config_t* config, const char* section, const char* key, 214b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson const char* value) { 215b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson section_t* sec = section_find(config, section); 216d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (!sec) { 217d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati sec = section_new(section); 218d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati list_append(config->sections, sec); 219d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 220d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 2217f8bfcc35285ca6e93a4436699bc95c13b920cafHansong Zhang std::string value_string = value; 2227f8bfcc35285ca6e93a4436699bc95c13b920cafHansong Zhang std::string value_no_newline; 2237f8bfcc35285ca6e93a4436699bc95c13b920cafHansong Zhang size_t newline_position = value_string.find("\n"); 2247f8bfcc35285ca6e93a4436699bc95c13b920cafHansong Zhang if (newline_position != std::string::npos) { 2257f8bfcc35285ca6e93a4436699bc95c13b920cafHansong Zhang android_errorWriteLog(0x534e4554, "70808273"); 2267f8bfcc35285ca6e93a4436699bc95c13b920cafHansong Zhang value_no_newline = value_string.substr(0, newline_position); 2277f8bfcc35285ca6e93a4436699bc95c13b920cafHansong Zhang } else { 2287f8bfcc35285ca6e93a4436699bc95c13b920cafHansong Zhang value_no_newline = value_string; 2297f8bfcc35285ca6e93a4436699bc95c13b920cafHansong Zhang } 2307f8bfcc35285ca6e93a4436699bc95c13b920cafHansong Zhang 231b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson for (const list_node_t* node = list_begin(sec->entries); 232b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson node != list_end(sec->entries); node = list_next(node)) { 233b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson entry_t* entry = static_cast<entry_t*>(list_node(node)); 234d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (!strcmp(entry->key, key)) { 235ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson osi_free(entry->value); 2367f8bfcc35285ca6e93a4436699bc95c13b920cafHansong Zhang entry->value = osi_strdup(value_no_newline.c_str()); 237d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return; 238d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 239d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 240d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 2417f8bfcc35285ca6e93a4436699bc95c13b920cafHansong Zhang entry_t* entry = entry_new(key, value_no_newline.c_str()); 242d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati list_append(sec->entries, entry); 243d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 244d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 245b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonbool config_remove_section(config_t* config, const char* section) { 246f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(config != NULL); 247f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(section != NULL); 24836c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 249b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson section_t* sec = section_find(config, section); 250b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (!sec) return false; 25136c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 25236c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati return list_remove(config->sections, sec); 25336c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati} 25436c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 255b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonbool config_remove_key(config_t* config, const char* section, const char* key) { 256f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(config != NULL); 257f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(section != NULL); 258f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(key != NULL); 25936c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 260b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson section_t* sec = section_find(config, section); 261b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson entry_t* entry = entry_find(config, section, key); 262b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (!sec || !entry) return false; 26336c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 26436c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati return list_remove(sec->entries, entry); 26536c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati} 26636c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 267b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonconst config_section_node_t* config_section_begin(const config_t* config) { 268f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(config != NULL); 269b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson return (const config_section_node_t*)list_begin(config->sections); 27036c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati} 27136c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 272b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonconst config_section_node_t* config_section_end(const config_t* config) { 273f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(config != NULL); 274b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson return (const config_section_node_t*)list_end(config->sections); 27536c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati} 27636c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 277b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonconst config_section_node_t* config_section_next( 278b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson const config_section_node_t* node) { 279f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(node != NULL); 280b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson return (const config_section_node_t*)list_next((const list_node_t*)node); 28136c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati} 28236c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 283b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonconst char* config_section_name(const config_section_node_t* node) { 284f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(node != NULL); 285b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson const list_node_t* lnode = (const list_node_t*)node; 286b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson const section_t* section = (const section_t*)list_node(lnode); 28736c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati return section->name; 28836c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati} 28936c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 290b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonbool config_save(const config_t* config, const char* filename) { 291f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(config != NULL); 292f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(filename != NULL); 293f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(*filename != '\0'); 29436c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 29595dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung // Steps to ensure content of config file gets to disk: 29695dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung // 29795dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung // 1) Open and write to temp file (e.g. bt_config.conf.new). 29895dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung // 2) Sync the temp file to disk with fsync(). 29995dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung // 3) Rename temp file to actual config file (e.g. bt_config.conf). 30095dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung // This ensures atomic update. 30195dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung // 4) Sync directory that has the conf file with fsync(). 30295dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung // This ensures directory entries are up-to-date. 30395dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung int dir_fd = -1; 304b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson FILE* fp = NULL; 30595dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung 30695dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung // Build temp config file based on config file (e.g. bt_config.conf.new). 307b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson static const char* temp_file_ext = ".new"; 30895dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung const int filename_len = strlen(filename); 30995dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung const int temp_filename_len = filename_len + strlen(temp_file_ext) + 1; 310b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson char* temp_filename = static_cast<char*>(osi_calloc(temp_filename_len)); 31195dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung snprintf(temp_filename, temp_filename_len, "%s%s", filename, temp_file_ext); 31295dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung 31395dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung // Extract directory from file path (e.g. /data/misc/bluedroid). 314b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson char* temp_dirname = osi_strdup(filename); 315b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson const char* directoryname = dirname(temp_dirname); 31695dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung if (!directoryname) { 317b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson LOG_ERROR(LOG_TAG, "%s error extracting directory from '%s': %s", __func__, 318b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson filename, strerror(errno)); 31995dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung goto error; 32095dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung } 32136c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 32295dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung dir_fd = open(directoryname, O_RDONLY); 32395dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung if (dir_fd < 0) { 324b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson LOG_ERROR(LOG_TAG, "%s unable to open dir '%s': %s", __func__, 325b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson directoryname, strerror(errno)); 32695dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung goto error; 32795dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung } 3288772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati 32995dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung fp = fopen(temp_filename, "wt"); 3308772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati if (!fp) { 331b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson LOG_ERROR(LOG_TAG, "%s unable to write file '%s': %s", __func__, 332b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson temp_filename, strerror(errno)); 3338772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati goto error; 3348772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati } 3358772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati 336b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson for (const list_node_t* node = list_begin(config->sections); 337b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson node != list_end(config->sections); node = list_next(node)) { 338b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson const section_t* section = (const section_t*)list_node(node); 339fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski if (fprintf(fp, "[%s]\n", section->name) < 0) { 340b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson LOG_ERROR(LOG_TAG, "%s unable to write to file '%s': %s", __func__, 341b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson temp_filename, strerror(errno)); 342ed2267a0a66b1aec52d9039bc20a6c5099dbdae7Alain Vongsouvanh goto error; 343fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski } 34436c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 345b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson for (const list_node_t* enode = list_begin(section->entries); 346b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson enode != list_end(section->entries); enode = list_next(enode)) { 347b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson const entry_t* entry = (const entry_t*)list_node(enode); 348fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski if (fprintf(fp, "%s = %s\n", entry->key, entry->value) < 0) { 349b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson LOG_ERROR(LOG_TAG, "%s unable to write to file '%s': %s", __func__, 350b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson temp_filename, strerror(errno)); 351ed2267a0a66b1aec52d9039bc20a6c5099dbdae7Alain Vongsouvanh goto error; 352fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski } 35336c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati } 35436c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 35536c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati // Only add a separating newline if there are more sections. 356fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski if (list_next(node) != list_end(config->sections)) { 357fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski if (fputc('\n', fp) == EOF) { 358b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson LOG_ERROR(LOG_TAG, "%s unable to write to file '%s': %s", __func__, 359b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson temp_filename, strerror(errno)); 360ed2267a0a66b1aec52d9039bc20a6c5099dbdae7Alain Vongsouvanh goto error; 361fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski } 362fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski } 36336c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati } 36436c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 365b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson // Sync written temp file out to disk. fsync() is blocking until data makes it 366b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson // to disk. 36795dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung if (fsync(fileno(fp)) < 0) { 368b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson LOG_WARN(LOG_TAG, "%s unable to fsync file '%s': %s", __func__, 369b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson temp_filename, strerror(errno)); 37095dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung } 37195dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung 372fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski if (fclose(fp) == EOF) { 373b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson LOG_ERROR(LOG_TAG, "%s unable to close file '%s': %s", __func__, 374b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson temp_filename, strerror(errno)); 375fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski goto error; 376fd2f03a2e0ab304a2b67a5a3ecf2e4e73d58e6d9Amadeusz Slawinski } 377ed2267a0a66b1aec52d9039bc20a6c5099dbdae7Alain Vongsouvanh fp = NULL; 3788772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati 3794197cfdbd36d9f7f213df11b6fee795f22c867fdPavlin Radoslavov // Change the file's permissions to Read/Write by User and Group 3804197cfdbd36d9f7f213df11b6fee795f22c867fdPavlin Radoslavov if (chmod(temp_filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) == -1) { 381b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson LOG_ERROR(LOG_TAG, "%s unable to change file permissions '%s': %s", 382b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson __func__, filename, strerror(errno)); 3834197cfdbd36d9f7f213df11b6fee795f22c867fdPavlin Radoslavov goto error; 3844197cfdbd36d9f7f213df11b6fee795f22c867fdPavlin Radoslavov } 3854197cfdbd36d9f7f213df11b6fee795f22c867fdPavlin Radoslavov 38695dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung // Rename written temp file to the actual config file. 3878772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati if (rename(temp_filename, filename) == -1) { 388b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson LOG_ERROR(LOG_TAG, "%s unable to commit file '%s': %s", __func__, filename, 389b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson strerror(errno)); 3908772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati goto error; 3918772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati } 3928772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati 39395dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung // This should ensure the directory is updated as well. 39495dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung if (fsync(dir_fd) < 0) { 395b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson LOG_WARN(LOG_TAG, "%s unable to fsync dir '%s': %s", __func__, 396b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson directoryname, strerror(errno)); 39795dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung } 39895dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung 39995dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung if (close(dir_fd) < 0) { 400b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson LOG_ERROR(LOG_TAG, "%s unable to close dir '%s': %s", __func__, 401b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson directoryname, strerror(errno)); 40295dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung goto error; 40395dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung } 40495dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung 4058772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati osi_free(temp_filename); 40695dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung osi_free(temp_dirname); 40736c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati return true; 4088772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati 40995dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheungerror: 410b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson // This indicates there is a write issue. Unlink as partial data is not 411b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson // acceptable. 4128772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati unlink(temp_filename); 413b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (fp) fclose(fp); 414b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (dir_fd != -1) close(dir_fd); 4158772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati osi_free(temp_filename); 41695dbe03a693f4a920204b8c6acbba5269915a59fJacky Cheung osi_free(temp_dirname); 4178772a37805c112ecda63997f2221fe97944c5ecfSharvil Nanavati return false; 41836c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati} 41936c1c09593a58717c78497cd55c4ed1dcf52183eSharvil Nanavati 420b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonstatic char* trim(char* str) { 421b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson while (isspace(*str)) ++str; 422d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 423b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (!*str) return str; 424d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 425b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson char* end_str = str + strlen(str) - 1; 426b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson while (end_str > str && isspace(*end_str)) --end_str; 427d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 428d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati end_str[1] = '\0'; 429d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return str; 430d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 431d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 432b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonstatic bool config_parse(FILE* fp, config_t* config) { 433f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(fp != NULL); 434f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(config != NULL); 435d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 436d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati int line_num = 0; 437d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati char line[1024]; 438d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati char section[1024]; 439d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati strcpy(section, CONFIG_DEFAULT_SECTION); 440d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 441d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati while (fgets(line, sizeof(line), fp)) { 442b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson char* line_ptr = trim(line); 443d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati ++line_num; 444d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 445d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati // Skip blank and comment lines. 446b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (*line_ptr == '\0' || *line_ptr == '#') continue; 447d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 448d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (*line_ptr == '[') { 449d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati size_t len = strlen(line_ptr); 450d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (line_ptr[len - 1] != ']') { 451b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson LOG_DEBUG(LOG_TAG, "%s unterminated section name on line %d.", __func__, 452b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson line_num); 45372a183d00c7534c80a4deb9fb41d38fd9e9455f6Ajay Panicker return false; 454d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 455d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati strncpy(section, line_ptr + 1, len - 2); 456d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati section[len - 2] = '\0'; 457d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } else { 458b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson char* split = strchr(line_ptr, '='); 459d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati if (!split) { 460b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson LOG_DEBUG(LOG_TAG, "%s no key/value separator found on line %d.", 461b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson __func__, line_num); 46272a183d00c7534c80a4deb9fb41d38fd9e9455f6Ajay Panicker return false; 463d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 464d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 465d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati *split = '\0'; 466d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati config_set_string(config, section, trim(line_ptr), trim(split + 1)); 467d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 468d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 46972a183d00c7534c80a4deb9fb41d38fd9e9455f6Ajay Panicker return true; 470d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 471d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 472b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonstatic section_t* section_new(const char* name) { 473b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson section_t* section = static_cast<section_t*>(osi_calloc(sizeof(section_t))); 474d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 475ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson section->name = osi_strdup(name); 476d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati section->entries = list_new(entry_free); 477d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return section; 478d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 479d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 480b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonstatic void section_free(void* ptr) { 481b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (!ptr) return; 482d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 483b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson section_t* section = static_cast<section_t*>(ptr); 484ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson osi_free(section->name); 485d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati list_free(section->entries); 486ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson osi_free(section); 487d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 488d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 489b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonstatic section_t* section_find(const config_t* config, const char* section) { 490b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson for (const list_node_t* node = list_begin(config->sections); 491b2a292b5d8df2f359c38b0787bc01181225a9bc9Pavlin Radoslavov node != list_end(config->sections); node = list_next(node)) { 492b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson section_t* sec = static_cast<section_t*>(list_node(node)); 493b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (!strcmp(sec->name, section)) return sec; 494d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 495d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 496d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return NULL; 497d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 498d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 499b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonstatic entry_t* entry_new(const char* key, const char* value) { 500b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson entry_t* entry = static_cast<entry_t*>(osi_calloc(sizeof(entry_t))); 501d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 502ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson entry->key = osi_strdup(key); 503ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson entry->value = osi_strdup(value); 504d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return entry; 505d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 506d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 507b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonstatic void entry_free(void* ptr) { 508b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (!ptr) return; 509d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 510b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson entry_t* entry = static_cast<entry_t*>(ptr); 511ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson osi_free(entry->key); 512ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson osi_free(entry->value); 513ee2aa45def216a3c4d6a23481fa96f1b02a5de8cZach Johnson osi_free(entry); 514d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 515d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 516b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonstatic entry_t* entry_find(const config_t* config, const char* section, 517b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson const char* key) { 518b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson section_t* sec = section_find(config, section); 519b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (!sec) return NULL; 520d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 521b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson for (const list_node_t* node = list_begin(sec->entries); 522b2a292b5d8df2f359c38b0787bc01181225a9bc9Pavlin Radoslavov node != list_end(sec->entries); node = list_next(node)) { 523b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson entry_t* entry = static_cast<entry_t*>(list_node(node)); 524b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (!strcmp(entry->key, key)) return entry; 525d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati } 526d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati 527d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati return NULL; 528d1c453f4f9648bb5eef80df106e79e3f916f301cSharvil Nanavati} 529