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 #endif // ANGLE_PLATFORM_ANDROID
74 // Return the environment variable's value.
75 return GetEnvironmentVar(variableName);
76 }
77
GetBoolEnvironmentVar(const char * variableName)78 bool GetBoolEnvironmentVar(const char *variableName)
79 {
80 std::string envVarString = GetEnvironmentVar(variableName);
81 return (!envVarString.empty() && envVarString == "1");
82 }
83
PrependPathToEnvironmentVar(const char * variableName,const char * path)84 bool PrependPathToEnvironmentVar(const char *variableName, const char *path)
85 {
86 std::string oldValue = GetEnvironmentVar(variableName);
87 const char *newValue = nullptr;
88 std::string buf;
89 if (oldValue.empty())
90 {
91 newValue = path;
92 }
93 else
94 {
95 buf = path;
96 buf += GetPathSeparatorForEnvironmentVar();
97 buf += oldValue;
98 newValue = buf.c_str();
99 }
100 return SetEnvironmentVar(variableName, newValue);
101 }
102
IsFullPath(std::string dirName)103 bool IsFullPath(std::string dirName)
104 {
105 if (dirName.find(GetRootDirectory()) == 0)
106 {
107 return true;
108 }
109 return false;
110 }
111
ConcatenatePath(std::string first,std::string second)112 std::string ConcatenatePath(std::string first, std::string second)
113 {
114 if (first.empty())
115 {
116 return second;
117 }
118 if (second.empty())
119 {
120 return first;
121 }
122 if (IsFullPath(second))
123 {
124 return first;
125 }
126 bool firstRedundantPathSeparator = first.find_last_of(GetPathSeparator()) == first.length() - 1;
127 bool secondRedundantPathSeparator = second.find(GetPathSeparator()) == 0;
128 if (firstRedundantPathSeparator && secondRedundantPathSeparator)
129 {
130 return first + second.substr(1);
131 }
132 else if (firstRedundantPathSeparator || secondRedundantPathSeparator)
133 {
134 return first + second;
135 }
136 return first + GetPathSeparator() + second;
137 }
138 } // namespace angle
139