// // Copyright 2018 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // system_utils.cpp: Implementation of common functions #include "common/system_utils.h" #include #if defined(ANGLE_PLATFORM_ANDROID) # include #endif namespace angle { std::string GetExecutableName() { #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 21 // Support for "getprogname" function in bionic was introduced in L (API level 21) const char *executableName = getprogname(); return (executableName) ? std::string(executableName) : "ANGLE"; #else std::string executableName = GetExecutablePath(); size_t lastPathSepLoc = executableName.find_last_of(GetPathSeparator()); return (lastPathSepLoc > 0 ? executableName.substr(lastPathSepLoc + 1, executableName.length()) : "ANGLE"); #endif // ANGLE_PLATFORM_ANDROID } // On Android return value cached in the process environment, if none, call // GetEnvironmentVarOrUnCachedAndroidProperty if not in environment. std::string GetEnvironmentVarOrAndroidProperty(const char *variableName, const char *propertyName) { #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 21 // Can't use GetEnvironmentVar here because that won't allow us to distinguish between the // environment being set to an empty string vs. not set at all. const char *variableValue = getenv(variableName); if (variableValue != nullptr) { std::string value(variableValue); return value; } #endif return GetEnvironmentVarOrUnCachedAndroidProperty(variableName, propertyName); } // Call out to 'getprop' on a shell to get an Android property. If the value was set, set an // environment variable with that value. Return the value of the environment variable. std::string GetEnvironmentVarOrUnCachedAndroidProperty(const char *variableName, const char *propertyName) { #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 26 std::string propertyValue; const prop_info *propertyInfo = __system_property_find(propertyName); if (propertyInfo != nullptr) { __system_property_read_callback( propertyInfo, [](void *cookie, const char *, const char *value, unsigned) { auto propertyValue = reinterpret_cast(cookie); *propertyValue = value; }, &propertyValue); } // Set the environment variable with the value. SetEnvironmentVar(variableName, propertyValue.c_str()); return propertyValue; #endif // ANGLE_PLATFORM_ANDROID // Return the environment variable's value. return GetEnvironmentVar(variableName); } bool GetBoolEnvironmentVar(const char *variableName) { std::string envVarString = GetEnvironmentVar(variableName); return (!envVarString.empty() && envVarString == "1"); } bool PrependPathToEnvironmentVar(const char *variableName, const char *path) { std::string oldValue = GetEnvironmentVar(variableName); const char *newValue = nullptr; std::string buf; if (oldValue.empty()) { newValue = path; } else { buf = path; buf += GetPathSeparatorForEnvironmentVar(); buf += oldValue; newValue = buf.c_str(); } return SetEnvironmentVar(variableName, newValue); } bool IsFullPath(std::string dirName) { if (dirName.find(GetRootDirectory()) == 0) { return true; } return false; } std::string ConcatenatePath(std::string first, std::string second) { if (first.empty()) { return second; } if (second.empty()) { return first; } if (IsFullPath(second)) { return first; } bool firstRedundantPathSeparator = first.find_last_of(GetPathSeparator()) == first.length() - 1; bool secondRedundantPathSeparator = second.find(GetPathSeparator()) == 0; if (firstRedundantPathSeparator && secondRedundantPathSeparator) { return first + second.substr(1); } else if (firstRedundantPathSeparator || secondRedundantPathSeparator) { return first + second; } return first + GetPathSeparator() + second; } } // namespace angle