1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "berberis/base/config_globals.h"
18
19 #include <cstdlib>
20 #include <cstring>
21
22 #if defined(__BIONIC__)
23 #include <sys/system_properties.h>
24 #endif
25
26 #include <bitset>
27 #include <string_view>
28
29 #include "berberis/base/checks.h"
30 #include "berberis/base/forever_alloc.h"
31
32 namespace berberis {
33
34 namespace {
35
36 const char* g_main_executable_real_path = nullptr;
37
38 const char* g_app_package_name = nullptr;
39 const char* g_app_private_dir = nullptr;
40
MakeForeverCStr(std::string_view view)41 const char* MakeForeverCStr(std::string_view view) {
42 auto str = reinterpret_cast<char*>(AllocateForever(view.size() + 1, alignof(char)));
43 memcpy(str, view.data(), view.size());
44 str[view.size()] = '\0';
45 return str;
46 }
47
48 #if defined(__BIONIC__)
49
TryReadBionicSystemPropertyImpl(const std::string_view prop_name,const char ** value_ptr)50 bool TryReadBionicSystemPropertyImpl(const std::string_view prop_name, const char** value_ptr) {
51 auto pi = __system_property_find(prop_name.data());
52 if (!pi) {
53 return false;
54 }
55 __system_property_read_callback(
56 pi,
57 [](void* cookie, const char*, const char* value, unsigned) {
58 *reinterpret_cast<const char**>(cookie) = MakeForeverCStr(value);
59 },
60 value_ptr);
61 return true;
62 }
63
TryReadBionicSystemProperty(const std::string_view prop_name,const char ** value_ptr)64 bool TryReadBionicSystemProperty(const std::string_view prop_name, const char** value_ptr) {
65 // Allow properties without ro. prefix (they override ro. properties).
66 if (prop_name.size() > 3 && prop_name.substr(0, 3) == "ro." &&
67 TryReadBionicSystemPropertyImpl(prop_name.substr(3), value_ptr)) {
68 return true;
69 }
70
71 return TryReadBionicSystemPropertyImpl(prop_name, value_ptr);
72 }
73
74 #endif
75
TryReadConfig(const char * env_name,const std::string_view prop_name,const char ** value_ptr)76 bool TryReadConfig(const char* env_name,
77 [[maybe_unused]] const std::string_view prop_name,
78 const char** value_ptr) {
79 if (auto env = getenv(env_name)) {
80 *value_ptr = MakeForeverCStr(env);
81 return true;
82 }
83 #if defined(__BIONIC__)
84 return TryReadBionicSystemProperty(prop_name, value_ptr);
85 #else
86 return false;
87 #endif
88 }
89
90 } // namespace
91
ConfigStr(const char * env_name,const char * prop_name)92 ConfigStr::ConfigStr(const char* env_name, const char* prop_name) {
93 TryReadConfig(env_name, prop_name, &value_);
94 }
95
SetMainExecutableRealPath(std::string_view path)96 void SetMainExecutableRealPath(std::string_view path) {
97 CHECK(!path.empty());
98 CHECK_EQ('/', path[0]);
99 g_main_executable_real_path = MakeForeverCStr(path);
100 }
101
GetMainExecutableRealPath()102 const char* GetMainExecutableRealPath() {
103 return g_main_executable_real_path;
104 }
105
SetAppPackageName(std::string_view name)106 void SetAppPackageName(std::string_view name) {
107 CHECK(!name.empty());
108 g_app_package_name = MakeForeverCStr(name);
109 }
110
GetAppPackageName()111 const char* GetAppPackageName() {
112 return g_app_package_name;
113 }
114
SetAppPrivateDir(std::string_view name)115 void SetAppPrivateDir(std::string_view name) {
116 CHECK(!name.empty());
117 g_app_private_dir = MakeForeverCStr(name);
118 }
119
GetAppPrivateDir()120 const char* GetAppPrivateDir() {
121 return g_app_private_dir;
122 }
123
124 } // namespace berberis
125