tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

system_utils.cpp (8853B)


      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 #include "common/debug.h"
     11 
     12 #include <stdlib.h>
     13 #include <atomic>
     14 
     15 #if defined(ANGLE_PLATFORM_ANDROID)
     16 #    include <sys/system_properties.h>
     17 #endif
     18 
     19 #if defined(ANGLE_PLATFORM_APPLE)
     20 #    include <dispatch/dispatch.h>
     21 #    include <pthread.h>
     22 #endif
     23 
     24 namespace angle
     25 {
     26 std::string GetExecutableName()
     27 {
     28 #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 21
     29    // Support for "getprogname" function in bionic was introduced in L (API level 21)
     30    const char *executableName = getprogname();
     31    return (executableName) ? std::string(executableName) : "ANGLE";
     32 #else
     33    std::string executableName = GetExecutablePath();
     34    size_t lastPathSepLoc      = executableName.find_last_of(GetPathSeparator());
     35    return (lastPathSepLoc > 0 ? executableName.substr(lastPathSepLoc + 1, executableName.length())
     36                               : "ANGLE");
     37 #endif  // ANGLE_PLATFORM_ANDROID
     38 }
     39 
     40 // On Android return value cached in the process environment, if none, call
     41 // GetEnvironmentVarOrUnCachedAndroidProperty if not in environment.
     42 std::string GetEnvironmentVarOrAndroidProperty(const char *variableName, const char *propertyName)
     43 {
     44 #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 21
     45    // Can't use GetEnvironmentVar here because that won't allow us to distinguish between the
     46    // environment being set to an empty string vs. not set at all.
     47    const char *variableValue = getenv(variableName);
     48    if (variableValue != nullptr)
     49    {
     50        std::string value(variableValue);
     51        return value;
     52    }
     53 #endif
     54    return GetEnvironmentVarOrUnCachedAndroidProperty(variableName, propertyName);
     55 }
     56 
     57 // On Android call out to 'getprop' on a shell to get an Android property.  On desktop, return
     58 // the value of the environment variable.
     59 std::string GetEnvironmentVarOrUnCachedAndroidProperty(const char *variableName,
     60                                                       const char *propertyName)
     61 {
     62 #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 26
     63    std::string propertyValue;
     64 
     65    const prop_info *propertyInfo = __system_property_find(propertyName);
     66    if (propertyInfo != nullptr)
     67    {
     68        __system_property_read_callback(
     69            propertyInfo,
     70            [](void *cookie, const char *, const char *value, unsigned) {
     71                auto propertyValue = reinterpret_cast<std::string *>(cookie);
     72                *propertyValue     = value;
     73            },
     74            &propertyValue);
     75    }
     76 
     77    return propertyValue;
     78 #else
     79    // Return the environment variable's value.
     80    return GetEnvironmentVar(variableName);
     81 #endif  // ANGLE_PLATFORM_ANDROID
     82 }
     83 
     84 // Look up a property and add it to the application's environment.
     85 // Adding to the env is a performance optimization, as getting properties is expensive.
     86 // This should only be used in non-Release paths, i.e. when using FrameCapture or DebugUtils.
     87 // It can cause race conditions in stress testing. See http://anglebug.com/6822
     88 std::string GetAndSetEnvironmentVarOrUnCachedAndroidProperty(const char *variableName,
     89                                                             const char *propertyName)
     90 {
     91    std::string value = GetEnvironmentVarOrUnCachedAndroidProperty(variableName, propertyName);
     92 
     93 #if defined(ANGLE_PLATFORM_ANDROID)
     94    if (!value.empty())
     95    {
     96        // Set the environment variable with the value to improve future lookups (avoids
     97        SetEnvironmentVar(variableName, value.c_str());
     98    }
     99 #endif
    100 
    101    return value;
    102 }
    103 
    104 bool GetBoolEnvironmentVar(const char *variableName)
    105 {
    106    std::string envVarString = GetEnvironmentVar(variableName);
    107    return (!envVarString.empty() && envVarString == "1");
    108 }
    109 
    110 bool PrependPathToEnvironmentVar(const char *variableName, const char *path)
    111 {
    112    std::string oldValue = GetEnvironmentVar(variableName);
    113    const char *newValue = nullptr;
    114    std::string buf;
    115    if (oldValue.empty())
    116    {
    117        newValue = path;
    118    }
    119    else
    120    {
    121        buf = path;
    122        buf += GetPathSeparatorForEnvironmentVar();
    123        buf += oldValue;
    124        newValue = buf.c_str();
    125    }
    126    return SetEnvironmentVar(variableName, newValue);
    127 }
    128 
    129 bool IsFullPath(std::string dirName)
    130 {
    131    if (dirName.find(GetRootDirectory()) == 0)
    132    {
    133        return true;
    134    }
    135    return false;
    136 }
    137 
    138 std::string ConcatenatePath(std::string first, std::string second)
    139 {
    140    if (first.empty())
    141    {
    142        return second;
    143    }
    144    if (second.empty())
    145    {
    146        return first;
    147    }
    148    if (IsFullPath(second))
    149    {
    150        return second;
    151    }
    152    bool firstRedundantPathSeparator = first.find_last_of(GetPathSeparator()) == first.length() - 1;
    153    bool secondRedundantPathSeparator = second.find(GetPathSeparator()) == 0;
    154    if (firstRedundantPathSeparator && secondRedundantPathSeparator)
    155    {
    156        return first + second.substr(1);
    157    }
    158    else if (firstRedundantPathSeparator || secondRedundantPathSeparator)
    159    {
    160        return first + second;
    161    }
    162    return first + GetPathSeparator() + second;
    163 }
    164 
    165 Optional<std::string> CreateTemporaryFile()
    166 {
    167    const Optional<std::string> tempDir = GetTempDirectory();
    168    if (!tempDir.valid())
    169        return Optional<std::string>::Invalid();
    170 
    171    return CreateTemporaryFileInDirectory(tempDir.value());
    172 }
    173 
    174 PageFaultHandler::PageFaultHandler(PageFaultCallback callback) : mCallback(callback) {}
    175 PageFaultHandler::~PageFaultHandler() {}
    176 
    177 Library *OpenSharedLibrary(const char *libraryName, SearchType searchType)
    178 {
    179    void *libraryHandle = OpenSystemLibraryAndGetError(libraryName, searchType, nullptr);
    180    return new Library(libraryHandle);
    181 }
    182 
    183 Library *OpenSharedLibraryWithExtension(const char *libraryName, SearchType searchType)
    184 {
    185    void *libraryHandle =
    186        OpenSystemLibraryWithExtensionAndGetError(libraryName, searchType, nullptr);
    187    return new Library(libraryHandle);
    188 }
    189 
    190 Library *OpenSharedLibraryAndGetError(const char *libraryName,
    191                                      SearchType searchType,
    192                                      std::string *errorOut)
    193 {
    194    void *libraryHandle = OpenSystemLibraryAndGetError(libraryName, searchType, errorOut);
    195    return new Library(libraryHandle);
    196 }
    197 
    198 Library *OpenSharedLibraryWithExtensionAndGetError(const char *libraryName,
    199                                                   SearchType searchType,
    200                                                   std::string *errorOut)
    201 {
    202    void *libraryHandle =
    203        OpenSystemLibraryWithExtensionAndGetError(libraryName, searchType, errorOut);
    204    return new Library(libraryHandle);
    205 }
    206 
    207 void *OpenSystemLibrary(const char *libraryName, SearchType searchType)
    208 {
    209    return OpenSystemLibraryAndGetError(libraryName, searchType, nullptr);
    210 }
    211 
    212 void *OpenSystemLibraryWithExtension(const char *libraryName, SearchType searchType)
    213 {
    214    return OpenSystemLibraryWithExtensionAndGetError(libraryName, searchType, nullptr);
    215 }
    216 
    217 void *OpenSystemLibraryAndGetError(const char *libraryName,
    218                                   SearchType searchType,
    219                                   std::string *errorOut)
    220 {
    221    std::string libraryWithExtension = std::string(libraryName) + "." + GetSharedLibraryExtension();
    222 #if ANGLE_PLATFORM_IOS
    223    // On iOS, libraryWithExtension is a directory in which the library resides.
    224    // The actual library name doesn't have an extension at all.
    225    // E.g. "libEGL.framework/libEGL"
    226    libraryWithExtension = libraryWithExtension + "/" + libraryName;
    227 #endif
    228    return OpenSystemLibraryWithExtensionAndGetError(libraryWithExtension.c_str(), searchType,
    229                                                     errorOut);
    230 }
    231 
    232 std::string StripFilenameFromPath(const std::string &path)
    233 {
    234    size_t lastPathSepLoc = path.find_last_of("\\/");
    235    return (lastPathSepLoc != std::string::npos) ? path.substr(0, lastPathSepLoc) : "";
    236 }
    237 
    238 static std::atomic<uint64_t> globalThreadSerial(1);
    239 
    240 #if defined(ANGLE_PLATFORM_APPLE)
    241 // https://anglebug.com/6479, similar to egl::GetCurrentThread() in libGLESv2/global_state.cpp
    242 uint64_t GetCurrentThreadUniqueId()
    243 {
    244    static pthread_key_t tlsIndex;
    245    static dispatch_once_t once;
    246    dispatch_once(&once, ^{
    247      ASSERT(pthread_key_create(&tlsIndex, nullptr) == 0);
    248    });
    249 
    250    void *tlsValue = pthread_getspecific(tlsIndex);
    251    if (tlsValue == nullptr)
    252    {
    253        uint64_t threadId = globalThreadSerial++;
    254        ASSERT(pthread_setspecific(tlsIndex, reinterpret_cast<void *>(threadId)) == 0);
    255        return threadId;
    256    }
    257    return reinterpret_cast<uint64_t>(tlsValue);
    258 }
    259 #else
    260 uint64_t GetCurrentThreadUniqueId()
    261 {
    262    thread_local uint64_t threadId(globalThreadSerial++);
    263    return threadId;
    264 }
    265 #endif
    266 
    267 }  // namespace angle