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