1 //
2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // system_utils.cpp: Implementation of common functions
8
9 #include "common/system_utils.h"
10
11 #include <stdlib.h>
12
13 #if defined(ANGLE_PLATFORM_ANDROID)
14 # include <sys/system_properties.h>
15 #endif
16
17 namespace angle
18 {
GetExecutableName()19 std::string GetExecutableName()
20 {
21 #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 21
22 // Support for "getprogname" function in bionic was introduced in L (API level 21)
23 const char *executableName = getprogname();
24 return (executableName) ? std::string(executableName) : "ANGLE";
25 #else
26 std::string executableName = GetExecutablePath();
27 size_t lastPathSepLoc = executableName.find_last_of(GetPathSeparator());
28 return (lastPathSepLoc > 0 ? executableName.substr(lastPathSepLoc + 1, executableName.length())
29 : "ANGLE");
30 #endif // ANGLE_PLATFORM_ANDROID
31 }
32
33 // On Android return value cached in the process environment, if none, call
34 // GetEnvironmentVarOrUnCachedAndroidProperty if not in environment.
GetEnvironmentVarOrAndroidProperty(const char * variableName,const char * propertyName)35 std::string GetEnvironmentVarOrAndroidProperty(const char *variableName, const char *propertyName)
36 {
37 #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 21
38 // Can't use GetEnvironmentVar here because that won't allow us to distinguish between the
39 // environment being set to an empty string vs. not set at all.
40 const char *variableValue = getenv(variableName);
41 if (variableValue != nullptr)
42 {
43 std::string value(variableValue);
44 return value;
45 }
46 #endif
47 return GetEnvironmentVarOrUnCachedAndroidProperty(variableName, propertyName);
48 }
49
50 // Call out to 'getprop' on a shell to get an Android property. If the value was set, set an
51 // environment variable with that value. Return the value of the environment variable.
GetEnvironmentVarOrUnCachedAndroidProperty(const char * variableName,const char * propertyName)52 std::string GetEnvironmentVarOrUnCachedAndroidProperty(const char *variableName,
53 const char *propertyName)
54 {
55 #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 26
56 std::string propertyValue;
57
58 const prop_info *propertyInfo = __system_property_find(propertyName);
59 if (propertyInfo != nullptr)
60 {
61 __system_property_read_callback(
62 propertyInfo,
63 [](void *cookie, const char *, const char *value, unsigned) {
64 auto propertyValue = reinterpret_cast<std::string *>(cookie);
65 *propertyValue = value;
66 },
67 &propertyValue);
68 }
69
70 // Set the environment variable with the value.
71 SetEnvironmentVar(variableName, propertyValue.c_str());
72 return propertyValue;
73 #else
74 // Return the environment variable's value.
75 return GetEnvironmentVar(variableName);
76 #endif // ANGLE_PLATFORM_ANDROID
77 }
78
GetBoolEnvironmentVar(const char * variableName)79 bool GetBoolEnvironmentVar(const char *variableName)
80 {
81 std::string envVarString = GetEnvironmentVar(variableName);
82 return (!envVarString.empty() && envVarString == "1");
83 }
84
PrependPathToEnvironmentVar(const char * variableName,const char * path)85 bool PrependPathToEnvironmentVar(const char *variableName, const char *path)
86 {
87 std::string oldValue = GetEnvironmentVar(variableName);
88 const char *newValue = nullptr;
89 std::string buf;
90 if (oldValue.empty())
91 {
92 newValue = path;
93 }
94 else
95 {
96 buf = path;
97 buf += GetPathSeparatorForEnvironmentVar();
98 buf += oldValue;
99 newValue = buf.c_str();
100 }
101 return SetEnvironmentVar(variableName, newValue);
102 }
103
IsFullPath(std::string dirName)104 bool IsFullPath(std::string dirName)
105 {
106 if (dirName.find(GetRootDirectory()) == 0)
107 {
108 return true;
109 }
110 return false;
111 }
112
ConcatenatePath(std::string first,std::string second)113 std::string ConcatenatePath(std::string first, std::string second)
114 {
115 if (first.empty())
116 {
117 return second;
118 }
119 if (second.empty())
120 {
121 return first;
122 }
123 if (IsFullPath(second))
124 {
125 return second;
126 }
127 bool firstRedundantPathSeparator = first.find_last_of(GetPathSeparator()) == first.length() - 1;
128 bool secondRedundantPathSeparator = second.find(GetPathSeparator()) == 0;
129 if (firstRedundantPathSeparator && secondRedundantPathSeparator)
130 {
131 return first + second.substr(1);
132 }
133 else if (firstRedundantPathSeparator || secondRedundantPathSeparator)
134 {
135 return first + second;
136 }
137 return first + GetPathSeparator() + second;
138 }
139 } // namespace angle
140