LCOV - code coverage report
Current view: top level - xpcom/build - BinaryPath.h (source / functions) Hit Total Coverage
Test: output.info Lines: 18 39 46.2 %
Date: 2017-07-14 16:53:18 Functions: 3 3 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef mozilla_BinaryPath_h
       8             : #define mozilla_BinaryPath_h
       9             : 
      10             : #include "nsXPCOMPrivate.h" // for MAXPATHLEN
      11             : #ifdef XP_WIN
      12             : #include <windows.h>
      13             : #elif defined(XP_MACOSX)
      14             : #include <CoreFoundation/CoreFoundation.h>
      15             : #elif defined(XP_UNIX)
      16             : #include <sys/stat.h>
      17             : #include <string.h>
      18             : #endif
      19             : #include "mozilla/UniquePtr.h"
      20             : #include "mozilla/UniquePtrExtensions.h"
      21             : 
      22             : #ifdef MOZILLA_INTERNAL_API
      23             : #include "nsCOMPtr.h"
      24             : #include "nsIFile.h"
      25             : #include "nsString.h"
      26             : #endif
      27             : 
      28             : namespace mozilla {
      29             : 
      30             : class BinaryPath
      31             : {
      32             : public:
      33             : #ifdef XP_WIN
      34             :   static nsresult Get(const char* argv0, char aResult[MAXPATHLEN])
      35             :   {
      36             :     wchar_t wide_path[MAXPATHLEN];
      37             :     nsresult rv = GetW(argv0, wide_path);
      38             :     if (NS_FAILED(rv)) {
      39             :       return rv;
      40             :     }
      41             :     WideCharToMultiByte(CP_UTF8, 0, wide_path, -1,
      42             :                         aResult, MAXPATHLEN, nullptr, nullptr);
      43             :     return NS_OK;
      44             :   }
      45             : 
      46             :   static nsresult GetLong(wchar_t aResult[MAXPATHLEN])
      47             :   {
      48             :     static bool cached = false;
      49             :     static wchar_t exeLongPath[MAXPATHLEN] = L"";
      50             : 
      51             :     if (!cached) {
      52             :       nsresult rv = GetW(nullptr, exeLongPath);
      53             : 
      54             :       if (NS_FAILED(rv)) {
      55             :         return rv;
      56             :       }
      57             : 
      58             :       if (!::GetLongPathNameW(exeLongPath, exeLongPath, MAXPATHLEN)) {
      59             :         return NS_ERROR_FAILURE;
      60             :       }
      61             : 
      62             :       cached = true;
      63             :     }
      64             : 
      65             :     if (wcscpy_s(aResult, MAXPATHLEN, exeLongPath)) {
      66             :       return NS_ERROR_FAILURE;
      67             :     }
      68             : 
      69             :     return NS_OK;
      70             :   }
      71             : 
      72             : private:
      73             :   static nsresult GetW(const char* argv0, wchar_t aResult[MAXPATHLEN])
      74             :   {
      75             :     static bool cached = false;
      76             :     static wchar_t moduleFileName[MAXPATHLEN] = L"";
      77             : 
      78             :     if (!cached) {
      79             :       if (!::GetModuleFileNameW(0, moduleFileName, MAXPATHLEN)) {
      80             :         return NS_ERROR_FAILURE;
      81             :       }
      82             : 
      83             :       cached = true;
      84             :     }
      85             : 
      86             :     if (wcscpy_s(aResult, MAXPATHLEN, moduleFileName)) {
      87             :       return NS_ERROR_FAILURE;
      88             :     }
      89             : 
      90             :     return NS_OK;
      91             :   }
      92             : 
      93             : #elif defined(XP_MACOSX)
      94             :   static nsresult Get(const char* argv0, char aResult[MAXPATHLEN])
      95             :   {
      96             :     // Works even if we're not bundled.
      97             :     CFBundleRef appBundle = CFBundleGetMainBundle();
      98             :     if (!appBundle) {
      99             :       return NS_ERROR_FAILURE;
     100             :     }
     101             : 
     102             :     CFURLRef executableURL = CFBundleCopyExecutableURL(appBundle);
     103             :     if (!executableURL) {
     104             :       return NS_ERROR_FAILURE;
     105             :     }
     106             : 
     107             :     nsresult rv;
     108             :     if (CFURLGetFileSystemRepresentation(executableURL, false, (UInt8*)aResult,
     109             :                                          MAXPATHLEN)) {
     110             :       // Sanitize path in case the app was launched from Terminal via
     111             :       // './firefox' for example.
     112             :       size_t readPos = 0;
     113             :       size_t writePos = 0;
     114             :       while (aResult[readPos] != '\0') {
     115             :         if (aResult[readPos] == '.' && aResult[readPos + 1] == '/') {
     116             :           readPos += 2;
     117             :         } else {
     118             :           aResult[writePos] = aResult[readPos];
     119             :           readPos++;
     120             :           writePos++;
     121             :         }
     122             :       }
     123             :       aResult[writePos] = '\0';
     124             :       rv = NS_OK;
     125             :     } else {
     126             :       rv = NS_ERROR_FAILURE;
     127             :     }
     128             : 
     129             :     CFRelease(executableURL);
     130             :     return rv;
     131             :   }
     132             : 
     133             : #elif defined(ANDROID)
     134             :   static nsresult Get(const char* argv0, char aResult[MAXPATHLEN])
     135             :   {
     136             :     // On Android, we use the GRE_HOME variable that is set by the Java
     137             :     // bootstrap code.
     138             :     const char* greHome = getenv("GRE_HOME");
     139             : #if defined(MOZ_WIDGET_GONK)
     140             :     if (!greHome) {
     141             :       greHome = "/system/b2g";
     142             :     }
     143             : #endif
     144             : 
     145             :     if (!greHome) {
     146             :       return NS_ERROR_FAILURE;
     147             :     }
     148             : 
     149             :     snprintf(aResult, MAXPATHLEN, "%s/%s", greHome, "dummy");
     150             :     aResult[MAXPATHLEN - 1] = '\0';
     151             :     return NS_OK;
     152             :   }
     153             : 
     154             : #elif defined(XP_UNIX)
     155          13 :   static nsresult Get(const char* aArgv0, char aResult[MAXPATHLEN])
     156             :   {
     157             :     struct stat fileStat;
     158             :     // on unix, there is no official way to get the path of the current binary.
     159             :     // instead of using the MOZILLA_FIVE_HOME hack, which doesn't scale to
     160             :     // multiple applications, we will try a series of techniques:
     161             :     //
     162             :     // 1) use realpath() on argv[0], which works unless we're loaded from the
     163             :     //    PATH. Only do so if argv[0] looks like a path (contains a /).
     164             :     // 2) manually walk through the PATH and look for ourself
     165             :     // 3) give up
     166          26 :     if (strchr(aArgv0, '/') && realpath(aArgv0, aResult) &&
     167          13 :         stat(aResult, &fileStat) == 0) {
     168          13 :       return NS_OK;
     169             :     }
     170             : 
     171           0 :     const char* path = getenv("PATH");
     172           0 :     if (!path) {
     173           0 :       return NS_ERROR_FAILURE;
     174             :     }
     175             : 
     176           0 :     char* pathdup = strdup(path);
     177           0 :     if (!pathdup) {
     178           0 :       return NS_ERROR_OUT_OF_MEMORY;
     179             :     }
     180             : 
     181           0 :     bool found = false;
     182           0 :     char* token = strtok(pathdup, ":");
     183           0 :     while (token) {
     184             :       char tmpPath[MAXPATHLEN];
     185           0 :       sprintf(tmpPath, "%s/%s", token, aArgv0);
     186           0 :       if (realpath(tmpPath, aResult) && stat(aResult, &fileStat) == 0) {
     187           0 :         found = true;
     188           0 :         break;
     189             :       }
     190           0 :       token = strtok(nullptr, ":");
     191             :     }
     192           0 :     free(pathdup);
     193           0 :     if (found) {
     194           0 :       return NS_OK;
     195             :     }
     196           0 :     return NS_ERROR_FAILURE;
     197             :   }
     198             : 
     199             : #else
     200             : #error Oops, you need platform-specific code here
     201             : #endif
     202             : 
     203             : public:
     204           3 :   static UniqueFreePtr<char> Get(const char *aArgv0)
     205             :   {
     206             :     char path[MAXPATHLEN];
     207           3 :     if (NS_FAILED(Get(aArgv0, path))) {
     208           0 :       return nullptr;
     209             :     }
     210           6 :     UniqueFreePtr<char> result;
     211           3 :     result.reset(strdup(path));
     212           3 :     return result;
     213             :   }
     214             : 
     215             : #ifdef MOZILLA_INTERNAL_API
     216          10 :   static nsresult GetFile(const char* aArgv0, nsIFile** aResult)
     217             :   {
     218          20 :     nsCOMPtr<nsIFile> lf;
     219             : #ifdef XP_WIN
     220             :     wchar_t exePath[MAXPATHLEN];
     221             :     nsresult rv = GetW(aArgv0, exePath);
     222             : #else
     223             :     char exePath[MAXPATHLEN];
     224          10 :     nsresult rv = Get(aArgv0, exePath);
     225             : #endif
     226          10 :     if (NS_FAILED(rv)) {
     227           0 :       return rv;
     228             :     }
     229             : #ifdef XP_WIN
     230             :     rv = NS_NewLocalFile(nsDependentString(exePath), true,
     231             :                          getter_AddRefs(lf));
     232             : #else
     233          20 :     rv = NS_NewNativeLocalFile(nsDependentCString(exePath), true,
     234          30 :                                getter_AddRefs(lf));
     235             : #endif
     236          10 :     if (NS_FAILED(rv)) {
     237           0 :       return rv;
     238             :     }
     239          10 :     NS_ADDREF(*aResult = lf);
     240          10 :     return NS_OK;
     241             :   }
     242             : #endif
     243             : };
     244             : 
     245             : } // namespace mozilla
     246             : 
     247             : #endif /* mozilla_BinaryPath_h */

Generated by: LCOV version 1.13