aboutsummaryrefslogtreecommitdiff
path: root/gd/storage/legacy_osi_config.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gd/storage/legacy_osi_config.cc')
-rw-r--r--gd/storage/legacy_osi_config.cc456
1 files changed, 0 insertions, 456 deletions
diff --git a/gd/storage/legacy_osi_config.cc b/gd/storage/legacy_osi_config.cc
deleted file mode 100644
index b75d96ce8..000000000
--- a/gd/storage/legacy_osi_config.cc
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "storage/legacy_osi_config.h"
-
-#include <base/files/file_util.h>
-#include <fcntl.h>
-#include <string>
-
-#include "os/log.h"
-
-namespace {
-
-bool config_parse(FILE* fp, config_t* config);
-
-template <typename T,
- class = typename std::enable_if<std::is_same<config_t, typename std::remove_const<T>::type>::value>>
-auto section_find(T& config, const std::string& section) {
- return std::find_if(config.sections.begin(), config.sections.end(),
- [&section](const section_t& sec) { return sec.name == section; });
-}
-
-const entry_t* entry_find(const config_t& config, const std::string& section, const std::string& key) {
- auto sec = section_find(config, section);
- if (sec == config.sections.end()) return nullptr;
-
- for (const entry_t& entry : sec->entries) {
- if (entry.key == key) return &entry;
- }
-
- return nullptr;
-}
-
-char* trim(char* str) {
- while (isspace(*str)) ++str;
-
- if (!*str) return str;
-
- char* end_str = str + strlen(str) - 1;
- while (end_str > str && isspace(*end_str)) --end_str;
-
- end_str[1] = '\0';
- return str;
-}
-
-bool config_parse(FILE* fp, config_t* config) {
- CHECK(fp != nullptr);
- CHECK(config != nullptr);
-
- int line_num = 0;
- char line[1024];
- char section[1024];
- strcpy(section, CONFIG_DEFAULT_SECTION);
-
- while (fgets(line, sizeof(line), fp)) {
- char* line_ptr = trim(line);
- ++line_num;
-
- // Skip blank and comment lines.
- if (*line_ptr == '\0' || *line_ptr == '#') continue;
-
- if (*line_ptr == '[') {
- size_t len = strlen(line_ptr);
- if (line_ptr[len - 1] != ']') {
- VLOG(1) << __func__ << ": unterminated section name on line " << line_num;
- return false;
- }
- strncpy(section, line_ptr + 1, len - 2); // NOLINT (len < 1024)
- section[len - 2] = '\0';
- } else {
- char* split = strchr(line_ptr, '=');
- if (!split) {
- VLOG(1) << __func__ << ": no key/value separator found on line " << line_num;
- return false;
- }
-
- *split = '\0';
- bluetooth::legacy::osi::config::config_set_string(config, section, trim(line_ptr), trim(split + 1));
- }
- }
- return true;
-}
-
-} // namespace
-
-std::unique_ptr<config_t> bluetooth::legacy::osi::config::config_new_empty(void) {
- return std::make_unique<config_t>();
-}
-
-std::unique_ptr<config_t> bluetooth::legacy::osi::config::config_new(const char* filename) {
- CHECK(filename != nullptr);
-
- std::unique_ptr<config_t> config = config_new_empty();
-
- FILE* fp = fopen(filename, "rt");
- if (!fp) {
- LOG(ERROR) << __func__ << ": unable to open file '" << filename << "': " << strerror(errno);
- return nullptr;
- }
-
- if (!config_parse(fp, config.get())) {
- config.reset();
- }
-
- fclose(fp);
- return config;
-}
-
-std::string bluetooth::legacy::osi::config::checksum_read(const char* filename) {
- base::FilePath path(filename);
- if (!base::PathExists(path)) {
- LOG(ERROR) << __func__ << ": unable to locate file '" << filename << "'";
- return "";
- }
- std::string encrypted_hash;
- if (!base::ReadFileToString(path, &encrypted_hash)) {
- LOG(ERROR) << __func__ << ": unable to read file '" << filename << "'";
- }
- return encrypted_hash;
-}
-
-std::unique_ptr<config_t> bluetooth::legacy::osi::config::config_new_clone(const config_t& src) {
- std::unique_ptr<config_t> ret = config_new_empty();
-
- for (const section_t& sec : src.sections) {
- for (const entry_t& entry : sec.entries) {
- legacy::osi::config::config_set_string(ret.get(), sec.name, entry.key, entry.value);
- }
- }
-
- return ret;
-}
-
-bool bluetooth::legacy::osi::config::config_has_section(const config_t& config, const std::string& section) {
- return (section_find(config, section) != config.sections.end());
-}
-
-bool bluetooth::legacy::osi::config::config_has_key(const config_t& config, const std::string& section,
- const std::string& key) {
- return (entry_find(config, section, key) != nullptr);
-}
-
-int bluetooth::legacy::osi::config::config_get_int(const config_t& config, const std::string& section,
- const std::string& key, int def_value) {
- const entry_t* entry = entry_find(config, section, key);
- if (!entry) return def_value;
-
- char* endptr;
- int ret = strtol(entry->value.c_str(), &endptr, 0);
- return (*endptr == '\0') ? ret : def_value;
-}
-
-uint64_t bluetooth::legacy::osi::config::config_get_uint64(const config_t& config, const std::string& section,
- const std::string& key, uint64_t def_value) {
- const entry_t* entry = entry_find(config, section, key);
- if (!entry) return def_value;
-
- char* endptr;
- uint64_t ret = strtoull(entry->value.c_str(), &endptr, 0);
- return (*endptr == '\0') ? ret : def_value;
-}
-
-bool bluetooth::legacy::osi::config::config_get_bool(const config_t& config, const std::string& section,
- const std::string& key, bool def_value) {
- const entry_t* entry = entry_find(config, section, key);
- if (!entry) return def_value;
-
- if (entry->value == "true") return true;
- if (entry->value == "false") return false;
-
- return def_value;
-}
-
-const std::string* bluetooth::legacy::osi::config::config_get_string(const config_t& config, const std::string& section,
- const std::string& key,
- const std::string* def_value) {
- const entry_t* entry = entry_find(config, section, key);
- if (!entry) return def_value;
-
- return &entry->value;
-}
-
-void bluetooth::legacy::osi::config::config_set_int(config_t* config, const std::string& section,
- const std::string& key, int value) {
- legacy::osi::config::config_set_string(config, section, key, std::to_string(value));
-}
-
-void bluetooth::legacy::osi::config::config_set_uint64(config_t* config, const std::string& section,
- const std::string& key, uint64_t value) {
- legacy::osi::config::config_set_string(config, section, key, std::to_string(value));
-}
-
-void bluetooth::legacy::osi::config::config_set_bool(config_t* config, const std::string& section,
- const std::string& key, bool value) {
- legacy::osi::config::config_set_string(config, section, key, value ? "true" : "false");
-}
-
-void bluetooth::legacy::osi::config::config_set_string(config_t* config, const std::string& section,
- const std::string& key, const std::string& value) {
- CHECK(config);
-
- auto sec = section_find(*config, section);
- if (sec == config->sections.end()) {
- config->sections.emplace_back(section_t{.name = section});
- sec = std::prev(config->sections.end());
- }
-
- std::string value_no_newline;
- size_t newline_position = value.find('\n');
- if (newline_position != std::string::npos) {
- LOG_WARN("%s", "android_errorWriteLog(0x534e4554, 70808273)");
- value_no_newline = value.substr(0, newline_position);
- } else {
- value_no_newline = value;
- }
-
- for (entry_t& entry : sec->entries) {
- if (entry.key == key) {
- entry.value = value_no_newline;
- return;
- }
- }
-
- sec->entries.emplace_back(entry_t{.key = key, .value = value_no_newline});
-}
-
-bool bluetooth::legacy::osi::config::config_remove_section(config_t* config, const std::string& section) {
- CHECK(config);
-
- auto sec = section_find(*config, section);
- if (sec == config->sections.end()) return false;
-
- config->sections.erase(sec);
- return true;
-}
-
-bool bluetooth::legacy::osi::config::config_remove_key(config_t* config, const std::string& section,
- const std::string& key) {
- CHECK(config);
- auto sec = section_find(*config, section);
- if (sec == config->sections.end()) return false;
-
- for (auto entry = sec->entries.begin(); entry != sec->entries.end(); ++entry) {
- if (entry->key == key) {
- sec->entries.erase(entry);
- return true;
- }
- }
-
- return false;
-}
-
-bool bluetooth::legacy::osi::config::config_save(const config_t& config, const std::string& filename) {
- CHECK(!filename.empty());
-
- // Steps to ensure content of config file gets to disk:
- //
- // 1) Open and write to temp file (e.g. bt_config.conf.new).
- // 2) Flush the stream buffer to the temp file.
- // 3) Sync the temp file to disk with fsync().
- // 4) Rename temp file to actual config file (e.g. bt_config.conf).
- // This ensures atomic update.
- // 5) Sync directory that has the conf file with fsync().
- // This ensures directory entries are up-to-date.
- int dir_fd = -1;
- FILE* fp = nullptr;
- std::stringstream serialized;
-
- // Build temp config file based on config file (e.g. bt_config.conf.new).
- const std::string temp_filename = filename + ".new";
-
- // Extract directory from file path (e.g. /data/misc/bluedroid).
- const std::string directoryname = base::FilePath(filename).DirName().value();
- if (directoryname.empty()) {
- LOG(ERROR) << __func__ << ": error extracting directory from '" << filename << "': " << strerror(errno);
- goto error;
- }
-
- dir_fd = open(directoryname.c_str(), O_RDONLY);
- if (dir_fd < 0) {
- LOG(ERROR) << __func__ << ": unable to open dir '" << directoryname << "': " << strerror(errno);
- goto error;
- }
-
- fp = fopen(temp_filename.c_str(), "wt");
- if (!fp) {
- LOG(ERROR) << __func__ << ": unable to write to file '" << temp_filename << "': " << strerror(errno);
- goto error;
- }
-
- for (const section_t& section : config.sections) {
- serialized << "[" << section.name << "]" << std::endl;
-
- for (const entry_t& entry : section.entries) serialized << entry.key << " = " << entry.value << std::endl;
-
- serialized << std::endl;
- }
-
- if (fprintf(fp, "%s", serialized.str().c_str()) < 0) {
- LOG(ERROR) << __func__ << ": unable to write to file '" << temp_filename << "': " << strerror(errno);
- goto error;
- }
-
- // Flush the stream buffer to the temp file.
- if (fflush(fp) < 0) {
- LOG(ERROR) << __func__ << ": unable to write flush buffer to file '" << temp_filename << "': " << strerror(errno);
- goto error;
- }
-
- // Sync written temp file out to disk. fsync() is blocking until data makes it
- // to disk.
- if (fsync(fileno(fp)) < 0) {
- LOG(WARNING) << __func__ << ": unable to fsync file '" << temp_filename << "': " << strerror(errno);
- }
-
- if (fclose(fp) == EOF) {
- LOG(ERROR) << __func__ << ": unable to close file '" << temp_filename << "': " << strerror(errno);
- goto error;
- }
- fp = nullptr;
-
- // Change the file's permissions to Read/Write by User and Group
- if (chmod(temp_filename.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) == -1) {
- LOG(ERROR) << __func__ << ": unable to change file permissions '" << filename << "': " << strerror(errno);
- goto error;
- }
-
- // Rename written temp file to the actual config file.
- if (rename(temp_filename.c_str(), filename.c_str()) == -1) {
- LOG(ERROR) << __func__ << ": unable to commit file '" << filename << "': " << strerror(errno);
- goto error;
- }
-
- // This should ensure the directory is updated as well.
- if (fsync(dir_fd) < 0) {
- LOG(WARNING) << __func__ << ": unable to fsync dir '" << directoryname << "': " << strerror(errno);
- }
-
- if (close(dir_fd) < 0) {
- LOG(ERROR) << __func__ << ": unable to close dir '" << directoryname << "': " << strerror(errno);
- goto error;
- }
-
- return true;
-
-error:
- // This indicates there is a write issue. Unlink as partial data is not
- // acceptable.
- unlink(temp_filename.c_str());
- if (fp) fclose(fp);
- if (dir_fd != -1) close(dir_fd);
- return false;
-}
-
-bool bluetooth::legacy::osi::config::checksum_save(const std::string& checksum, const std::string& filename) {
- CHECK(!checksum.empty()) << __func__ << ": checksum cannot be empty";
- CHECK(!filename.empty()) << __func__ << ": filename cannot be empty";
-
- // Steps to ensure content of config checksum file gets to disk:
- //
- // 1) Open and write to temp file (e.g.
- // bt_config.conf.encrypted-checksum.new). 2) Sync the temp file to disk with
- // fsync(). 3) Rename temp file to actual config checksum file (e.g.
- // bt_config.conf.encrypted-checksum).
- // This ensures atomic update.
- // 4) Sync directory that has the conf file with fsync().
- // This ensures directory entries are up-to-date.
- FILE* fp = nullptr;
- int dir_fd = -1;
-
- // Build temp config checksum file based on config checksum file (e.g.
- // bt_config.conf.encrypted-checksum.new).
- const std::string temp_filename = filename + ".new";
- base::FilePath path(temp_filename);
-
- // Extract directory from file path (e.g. /data/misc/bluedroid).
- const std::string directoryname = base::FilePath(filename).DirName().value();
- if (directoryname.empty()) {
- LOG(ERROR) << __func__ << ": error extracting directory from '" << filename << "': " << strerror(errno);
- goto error2;
- }
-
- dir_fd = open(directoryname.c_str(), O_RDONLY);
- if (dir_fd < 0) {
- LOG(ERROR) << __func__ << ": unable to open dir '" << directoryname << "': " << strerror(errno);
- goto error2;
- }
-
- if (base::WriteFile(path, checksum.data(), checksum.size()) != (int)checksum.size()) {
- LOG(ERROR) << __func__ << ": unable to write file '" << filename.c_str();
- goto error2;
- }
-
- fp = fopen(temp_filename.c_str(), "rb");
- if (!fp) {
- LOG(ERROR) << __func__ << ": unable to write to file '" << temp_filename << "': " << strerror(errno);
- goto error2;
- }
-
- // Sync written temp file out to disk. fsync() is blocking until data makes it
- // to disk.
- if (fsync(fileno(fp)) < 0) {
- LOG(WARNING) << __func__ << ": unable to fsync file '" << temp_filename << "': " << strerror(errno);
- }
-
- if (fclose(fp) == EOF) {
- LOG(ERROR) << __func__ << ": unable to close file '" << temp_filename << "': " << strerror(errno);
- goto error2;
- }
- fp = nullptr;
-
- // Change the file's permissions to Read/Write by User and Group
- if (chmod(temp_filename.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) == -1) {
- LOG(ERROR) << __func__ << ": unable to change file permissions '" << filename << "': " << strerror(errno);
- goto error2;
- }
-
- // Rename written temp file to the actual config file.
- if (rename(temp_filename.c_str(), filename.c_str()) == -1) {
- LOG(ERROR) << __func__ << ": unable to commit file '" << filename << "': " << strerror(errno);
- goto error2;
- }
-
- // This should ensure the directory is updated as well.
- if (fsync(dir_fd) < 0) {
- LOG(WARNING) << __func__ << ": unable to fsync dir '" << directoryname << "': " << strerror(errno);
- }
-
- if (close(dir_fd) < 0) {
- LOG(ERROR) << __func__ << ": unable to close dir '" << directoryname << "': " << strerror(errno);
- goto error2;
- }
-
- return true;
-
-error2:
- // This indicates there is a write issue. Unlink as partial data is not
- // acceptable.
- unlink(temp_filename.c_str());
- if (fp) fclose(fp);
- if (dir_fd != -1) close(dir_fd);
- return false;
-}