Bug 1403366 - Stop requiring argv[0] for XRE_GetBinaryPath and the underlying BinaryPath::Get. r?froydnj
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -227,19 +227,19 @@ static int do_main(int argc, char* argv[
if (getenv("LIBFUZZER"))
gBootstrap->XRE_LibFuzzerSetDriver(fuzzer::FuzzerDriver);
#endif
return gBootstrap->XRE_main(argc, argv, config);
}
static nsresult
-InitXPCOMGlue(const char *argv0)
+InitXPCOMGlue()
{
- UniqueFreePtr<char> exePath = BinaryPath::Get(argv0);
+ UniqueFreePtr<char> exePath = BinaryPath::Get();
if (!exePath) {
Output("Couldn't find the application directory.\n");
return NS_ERROR_FAILURE;
}
gBootstrap = mozilla::GetBootstrap(exePath.get());
if (!gBootstrap) {
Output("Couldn't load XPCOM.\n");
@@ -267,17 +267,17 @@ int main(int argc, char* argv[], char* e
// We need to initialize the sandbox TargetServices before InitXPCOMGlue
// because we might need the sandbox broker to give access to some files.
if (IsSandboxedProcess() && !sandboxing::GetInitializedTargetServices()) {
Output("Failed to initialize the sandbox target services.");
return 255;
}
#endif
- nsresult rv = InitXPCOMGlue(argv[0]);
+ nsresult rv = InitXPCOMGlue();
if (NS_FAILED(rv)) {
return 255;
}
int result = content_process_main(gBootstrap.get(), argc, argv);
// InitXPCOMGlue calls NS_LogInit, so we need to balance it here.
gBootstrap->NS_LogTerm();
@@ -285,17 +285,17 @@ int main(int argc, char* argv[], char* e
return result;
}
#endif
#ifdef HAS_DLL_BLOCKLIST
DllBlocklist_Initialize();
#endif
- nsresult rv = InitXPCOMGlue(argv[0]);
+ nsresult rv = InitXPCOMGlue();
if (NS_FAILED(rv)) {
return 255;
}
gBootstrap->XRE_StartupTimelineRecord(mozilla::StartupTimeline::START, start);
#ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC
gBootstrap->XRE_EnableSameExecutableForContentProc();
--- a/ipc/glue/ScopedXREEmbed.cpp
+++ b/ipc/glue/ScopedXREEmbed.cpp
@@ -41,27 +41,18 @@ ScopedXREEmbed::SetAppDir(const nsACStri
NS_WARNING("Invalid application directory passed to content process.");
mAppDir = nullptr;
}
}
void
ScopedXREEmbed::Start()
{
- std::string path;
-#if defined(OS_WIN)
- path = WideToUTF8(CommandLine::ForCurrentProcess()->program());
-#elif defined(OS_POSIX)
- path = CommandLine::ForCurrentProcess()->argv()[0];
-#else
-# error Sorry
-#endif
-
nsCOMPtr<nsIFile> localFile;
- nsresult rv = XRE_GetBinaryPath(path.c_str(), getter_AddRefs(localFile));
+ nsresult rv = XRE_GetBinaryPath(getter_AddRefs(localFile));
if (NS_FAILED(rv))
return;
nsCOMPtr<nsIFile> parent;
rv = localFile->GetParent(getter_AddRefs(parent));
if (NS_FAILED(rv))
return;
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -1110,17 +1110,17 @@ XRE_XPCShellMain(int argc, char** argv,
printf_stderr("*** You are running in chaos test mode. See ChaosMode.h. ***\n");
}
// The provider needs to outlive the call to shutting down XPCOM.
XPCShellDirProvider dirprovider;
{ // Start scoping nsCOMPtrs
nsCOMPtr<nsIFile> appFile;
- rv = XRE_GetBinaryPath(argv[0], getter_AddRefs(appFile));
+ rv = XRE_GetBinaryPath(getter_AddRefs(appFile));
if (NS_FAILED(rv)) {
printf("Couldn't find application file.\n");
return 1;
}
nsCOMPtr<nsIFile> appDir;
rv = appFile->GetParent(getter_AddRefs(appDir));
if (NS_FAILED(rv)) {
printf("Couldn't get application directory.\n");
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -1870,19 +1870,19 @@ StartRemoteClient(const char* aDesktopSt
void
XRE_InitOmnijar(nsIFile* greOmni, nsIFile* appOmni)
{
mozilla::Omnijar::Init(greOmni, appOmni);
}
nsresult
-XRE_GetBinaryPath(const char* argv0, nsIFile* *aResult)
+XRE_GetBinaryPath(nsIFile* *aResult)
{
- return mozilla::BinaryPath::GetFile(argv0, aResult);
+ return mozilla::BinaryPath::GetFile(aResult);
}
#ifdef XP_WIN
#include "nsWindowsRestart.cpp"
#include <shellapi.h>
typedef BOOL (WINAPI* SetProcessDEPPolicyFunc)(DWORD dwFlags);
#endif
@@ -1911,17 +1911,17 @@ static nsresult LaunchChild(nsINativeApp
SaveToEnv("MOZ_LAUNCHED_CHILD=1");
#if !defined(MOZ_WIDGET_ANDROID) // Android has separate restart code.
#if defined(XP_MACOSX)
CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
LaunchChildMac(gRestartArgc, gRestartArgv);
#else
nsCOMPtr<nsIFile> lf;
- nsresult rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
+ nsresult rv = XRE_GetBinaryPath(getter_AddRefs(lf));
if (NS_FAILED(rv))
return rv;
#if defined(XP_WIN)
nsAutoString exePath;
rv = lf->GetPath(exePath);
if (NS_FAILED(rv))
return rv;
@@ -4780,25 +4780,25 @@ XREMain::XRE_main(int argc, char* argv[]
if (!mAppData->remotingName) {
mAppData->remotingName = mAppData->name;
}
// used throughout this file
gAppData = mAppData.get();
nsCOMPtr<nsIFile> binFile;
- rv = XRE_GetBinaryPath(argv[0], getter_AddRefs(binFile));
+ rv = XRE_GetBinaryPath(getter_AddRefs(binFile));
NS_ENSURE_SUCCESS(rv, 1);
rv = binFile->GetPath(gAbsoluteArgv0Path);
NS_ENSURE_SUCCESS(rv, 1);
if (!mAppData->xreDirectory) {
nsCOMPtr<nsIFile> lf;
- rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
+ rv = XRE_GetBinaryPath(getter_AddRefs(lf));
if (NS_FAILED(rv))
return 2;
nsCOMPtr<nsIFile> greDir;
rv = lf->GetParent(getter_AddRefs(greDir));
if (NS_FAILED(rv))
return 2;
@@ -4971,17 +4971,17 @@ XRE_InitCommandLine(int aArgc, char* aAr
CommandLine::Init(aArgc, aArgv);
#else
// these leak on error, but that's OK: we'll just exit()
char** canonArgs = new char*[aArgc];
// get the canonical version of the binary's path
nsCOMPtr<nsIFile> binFile;
- rv = XRE_GetBinaryPath(aArgv[0], getter_AddRefs(binFile));
+ rv = XRE_GetBinaryPath(getter_AddRefs(binFile));
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
nsAutoCString canonBinPath;
rv = binFile->GetNativePath(canonBinPath);
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
--- a/toolkit/xre/nsUpdateDriver.cpp
+++ b/toolkit/xre/nsUpdateDriver.cpp
@@ -503,17 +503,17 @@ ApplyUpdate(nsIFile *greDir, nsIFile *up
rv = GetCurrentWorkingDir(workingDirPath, sizeof(workingDirPath));
if (NS_FAILED(rv)) {
return;
}
// Get the application file path used by the updater to restart the
// application after the update has finished.
nsCOMPtr<nsIFile> appFile;
- XRE_GetBinaryPath(appArgv[0], getter_AddRefs(appFile));
+ XRE_GetBinaryPath(getter_AddRefs(appFile));
if (!appFile) {
return;
}
#if defined(XP_WIN)
nsAutoString appFilePathW;
rv = appFile->GetPath(appFilePathW);
if (NS_FAILED(rv)) {
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -421,19 +421,19 @@ nsXREDirProvider::GetFile(const char* aP
rv = file->AppendNative(NS_LITERAL_CSTRING(APP_REGISTRY_NAME));
}
else if (!strcmp(aProperty, NS_APP_USER_PROFILES_ROOT_DIR)) {
rv = GetUserProfilesRootDir(getter_AddRefs(file), nullptr, nullptr, nullptr);
}
else if (!strcmp(aProperty, NS_APP_USER_PROFILES_LOCAL_ROOT_DIR)) {
rv = GetUserProfilesLocalDir(getter_AddRefs(file), nullptr, nullptr, nullptr);
}
- else if (!strcmp(aProperty, XRE_EXECUTABLE_FILE) && gArgv[0]) {
+ else if (!strcmp(aProperty, XRE_EXECUTABLE_FILE)) {
nsCOMPtr<nsIFile> lf;
- rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
+ rv = XRE_GetBinaryPath(getter_AddRefs(lf));
if (NS_SUCCEEDED(rv))
file = lf;
}
else if (!strcmp(aProperty, NS_APP_PROFILE_DIR_STARTUP) && mProfileDir) {
return mProfileDir->Clone(aFile);
}
else if (!strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
@@ -923,17 +923,17 @@ nsXREDirProvider::GetFilesInternal(const
rv = NS_NewArrayEnumerator(aResult, directories);
}
else if (!strcmp(aProperty, NS_APP_PLUGINS_DIR_LIST)) {
nsCOMArray<nsIFile> directories;
if (mozilla::Preferences::GetBool("plugins.load_appdir_plugins", false)) {
nsCOMPtr<nsIFile> appdir;
- rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(appdir));
+ rv = XRE_GetBinaryPath(getter_AddRefs(appdir));
if (NS_SUCCEEDED(rv)) {
appdir->SetNativeLeafName(NS_LITERAL_CSTRING("plugins"));
directories.AppendObject(appdir);
}
}
static const char *const kAppendPlugins[] = { "plugins", nullptr };
--- a/xpcom/build/BinaryPath.h
+++ b/xpcom/build/BinaryPath.h
@@ -8,53 +8,62 @@
#define mozilla_BinaryPath_h
#include "nsXPCOMPrivate.h" // for MAXPATHLEN
#ifdef XP_WIN
#include <windows.h>
#elif defined(XP_MACOSX)
#include <CoreFoundation/CoreFoundation.h>
#elif defined(XP_UNIX)
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+#if defined(__FreeBSD__) || defined(__DragonFly__) || \
+ defined(__FreeBSD_kernel__) || defined(__NetBSD__) || \
+ defined(__OpenBSD__)
+#include <sys/sysctl.h>
+#endif
+#if defined(__OpenBSD__)
#include <sys/stat.h>
-#include <string.h>
#endif
#include "mozilla/UniquePtr.h"
#include "mozilla/UniquePtrExtensions.h"
#ifdef MOZILLA_INTERNAL_API
#include "nsCOMPtr.h"
#include "nsIFile.h"
#include "nsString.h"
#endif
namespace mozilla {
class BinaryPath
{
public:
#ifdef XP_WIN
- static nsresult Get(const char* argv0, char aResult[MAXPATHLEN])
+ static nsresult Get(char aResult[MAXPATHLEN])
{
wchar_t wide_path[MAXPATHLEN];
- nsresult rv = GetW(argv0, wide_path);
+ nsresult rv = GetW(wide_path);
if (NS_FAILED(rv)) {
return rv;
}
WideCharToMultiByte(CP_UTF8, 0, wide_path, -1,
aResult, MAXPATHLEN, nullptr, nullptr);
return NS_OK;
}
static nsresult GetLong(wchar_t aResult[MAXPATHLEN])
{
static bool cached = false;
static wchar_t exeLongPath[MAXPATHLEN] = L"";
if (!cached) {
- nsresult rv = GetW(nullptr, exeLongPath);
+ nsresult rv = GetW(exeLongPath);
if (NS_FAILED(rv)) {
return rv;
}
if (!::GetLongPathNameW(exeLongPath, exeLongPath, MAXPATHLEN)) {
return NS_ERROR_FAILURE;
}
@@ -65,17 +74,17 @@ public:
if (wcscpy_s(aResult, MAXPATHLEN, exeLongPath)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
private:
- static nsresult GetW(const char* argv0, wchar_t aResult[MAXPATHLEN])
+ static nsresult GetW(wchar_t aResult[MAXPATHLEN])
{
static bool cached = false;
static wchar_t moduleFileName[MAXPATHLEN] = L"";
if (!cached) {
if (!::GetModuleFileNameW(0, moduleFileName, MAXPATHLEN)) {
return NS_ERROR_FAILURE;
}
@@ -86,17 +95,17 @@ private:
if (wcscpy_s(aResult, MAXPATHLEN, moduleFileName)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
#elif defined(XP_MACOSX)
- static nsresult Get(const char* argv0, char aResult[MAXPATHLEN])
+ static nsresult Get(char aResult[MAXPATHLEN])
{
// Works even if we're not bundled.
CFBundleRef appBundle = CFBundleGetMainBundle();
if (!appBundle) {
return NS_ERROR_FAILURE;
}
CFURLRef executableURL = CFBundleCopyExecutableURL(appBundle);
@@ -126,38 +135,96 @@ private:
rv = NS_ERROR_FAILURE;
}
CFRelease(executableURL);
return rv;
}
#elif defined(ANDROID)
- static nsresult Get(const char* argv0, char aResult[MAXPATHLEN])
+ static nsresult Get(char aResult[MAXPATHLEN])
{
// On Android, we use the GRE_HOME variable that is set by the Java
// bootstrap code.
const char* greHome = getenv("GRE_HOME");
if (!greHome) {
return NS_ERROR_FAILURE;
}
snprintf(aResult, MAXPATHLEN, "%s/%s", greHome, "dummy");
aResult[MAXPATHLEN - 1] = '\0';
return NS_OK;
}
-#elif defined(XP_UNIX)
- static nsresult Get(const char* aArgv0, char aResult[MAXPATHLEN])
+#elif defined(XP_LINUX) || defined(XP_SOLARIS)
+ static nsresult Get(char aResult[MAXPATHLEN])
+ {
+# if defined(XP_SOLARIS)
+ const char path[] = "/proc/self/path/a.out";
+# else
+ const char path[] = "/proc/self/exe";
+# endif
+
+ ssize_t len = readlink(path, aResult, MAXPATHLEN - 1);
+ if (len < 0) {
+ return NS_ERROR_FAILURE;
+ }
+ aResult[len] = '\0';
+ return NS_OK;
+ }
+
+#elif defined(__FreeBSD__) || defined(__DragonFly__) || \
+ defined(__FreeBSD_kernel__) || defined(__NetBSD__)
+ static nsresult Get(char aResult[MAXPATHLEN])
+ {
+ int mib[4];
+ mib[0] = CTL_KERN;
+#ifdef __NetBSD__
+ mib[1] = KERN_PROC_ARGS;
+ mib[2] = -1;
+ mib[3] = KERN_PROC_PATHNAME;
+#else
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PATHNAME;
+ mib[3] = -1;
+#endif
+
+ size_t len = MAXPATHLEN;
+ if (sysctl(mib, 4, aResult, &len, nullptr, 0) < 0) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+ }
+
+#elif defined(__OpenBSD__)
+ static nsresult Get(char aResult[MAXPATHLEN])
+ {
+ int mib[4];
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC_ARGS;
+ mib[2] = getpid();
+ mib[3] = KERN_PROC_ARGV;
+
+ size_t len = 0;
+ if (sysctl(mib, 4, nullptr, &len, nullptr, 0) < 0) {
+ return NS_ERROR_FAILURE;
+ }
+
+ auto argv = MakeUnique<const char*[]>(len / sizeof(const char*));
+ if (sysctl(mib, 4, argv.get(), &len, nullptr, 0) < 0) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return GetFromArgv0(argv[0], aResult);
+ }
+
+ static nsresult GetFromArgv0(const char* aArgv0, char aResult[MAXPATHLEN])
{
struct stat fileStat;
- // on unix, there is no official way to get the path of the current binary.
- // instead of using the MOZILLA_FIVE_HOME hack, which doesn't scale to
- // multiple applications, we will try a series of techniques:
- //
// 1) use realpath() on argv[0], which works unless we're loaded from the
// PATH. Only do so if argv[0] looks like a path (contains a /).
// 2) manually walk through the PATH and look for ourself
// 3) give up
if (strchr(aArgv0, '/') && realpath(aArgv0, aResult) &&
stat(aResult, &fileStat) == 0) {
return NS_OK;
}
@@ -190,37 +257,37 @@ private:
return NS_ERROR_FAILURE;
}
#else
#error Oops, you need platform-specific code here
#endif
public:
- static UniqueFreePtr<char> Get(const char *aArgv0)
+ static UniqueFreePtr<char> Get()
{
char path[MAXPATHLEN];
- if (NS_FAILED(Get(aArgv0, path))) {
+ if (NS_FAILED(Get(path))) {
return nullptr;
}
UniqueFreePtr<char> result;
result.reset(strdup(path));
return result;
}
#ifdef MOZILLA_INTERNAL_API
- static nsresult GetFile(const char* aArgv0, nsIFile** aResult)
+ static nsresult GetFile(nsIFile** aResult)
{
nsCOMPtr<nsIFile> lf;
#ifdef XP_WIN
wchar_t exePath[MAXPATHLEN];
- nsresult rv = GetW(aArgv0, exePath);
+ nsresult rv = GetW(exePath);
#else
char exePath[MAXPATHLEN];
- nsresult rv = Get(aArgv0, exePath);
+ nsresult rv = Get(exePath);
#endif
if (NS_FAILED(rv)) {
return rv;
}
#ifdef XP_WIN
rv = NS_NewLocalFile(nsDependentString(exePath), true,
getter_AddRefs(lf));
#else
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -200,22 +200,19 @@ XRE_API(int,
*
* @note Pass UTF8 strings on Windows... native charset on other platforms.
*/
XRE_API(nsresult,
XRE_GetFileFromPath, (const char* aPath, nsIFile** aResult))
/**
* Get the path of the running application binary and store it in aResult.
- * @param aArgv0 The value passed as argv[0] of main(). This value is only
- * used on *nix, and only when other methods of determining
- * the binary path have failed.
*/
XRE_API(nsresult,
- XRE_GetBinaryPath, (const char* aArgv0, nsIFile** aResult))
+ XRE_GetBinaryPath, (nsIFile** aResult))
/**
* Get the static module built in to libxul.
*/
XRE_API(const mozilla::Module*,
XRE_GetStaticModule, ())
/**