Skip to content

Commit

Permalink
Make Platform.executable return the fully qualified path of the execu…
Browse files Browse the repository at this point in the history
…table

BUG=http://dartbug.com/16994
R=kustermann@google.com, lrn@google.com

Review URL: https://codereview.chromium.org//1145053002
  • Loading branch information
sgjesse committed May 20, 2015
1 parent 03917ff commit e03ab17
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 4 deletions.
1 change: 1 addition & 0 deletions runtime/bin/platform.cc
Expand Up @@ -13,6 +13,7 @@ namespace dart {
namespace bin {

const char* Platform::executable_name_ = NULL;
bool Platform::executable_name_resolved_ = false;
const char* Platform::package_root_ = NULL;
int Platform::script_index_ = 1;
char** Platform::argv_ = NULL;
Expand Down
16 changes: 15 additions & 1 deletion runtime/bin/platform.h
Expand Up @@ -39,11 +39,21 @@ class Platform {
static char** Environment(intptr_t* count);
static void FreeEnvironment(char** env, intptr_t count);

// Stores and gets the executable name.
static char* ResolveExecutablePath();

// Stores the executable name.
static void SetExecutableName(const char* executable_name) {
executable_name_ = executable_name;
}
static const char* GetExecutableName() {
if (!executable_name_resolved_) {
// Try to resolve the executable path using platform specific APIs.
char* path = Platform::ResolveExecutablePath();
if (path != NULL) {
executable_name_ = path;
}
executable_name_resolved_ = true;
}
return executable_name_;
}

Expand All @@ -68,7 +78,11 @@ class Platform {
}

private:
// The path to the executable.
static const char* executable_name_;
// State to indicate whether the executable name has been resolved.
static bool executable_name_resolved_;

static const char* package_root_;
static int script_index_;
static char** argv_; // VM flags are argv_[1 ... script_index_ - 1]
Expand Down
5 changes: 5 additions & 0 deletions runtime/bin/platform_android.cc
Expand Up @@ -71,6 +71,11 @@ void Platform::FreeEnvironment(char** env, intptr_t count) {
delete[] env;
}


char* Platform::ResolveExecutablePath() {
return File::LinkTarget("/proc/self/exe");
}

} // namespace bin
} // namespace dart

Expand Down
6 changes: 6 additions & 0 deletions runtime/bin/platform_linux.cc
Expand Up @@ -5,6 +5,7 @@
#include "platform/globals.h"
#if defined(TARGET_OS_LINUX)

#include "bin/file.h"
#include "bin/platform.h"

#include <signal.h> // NOLINT
Expand Down Expand Up @@ -71,6 +72,11 @@ void Platform::FreeEnvironment(char** env, intptr_t count) {
delete[] env;
}


char* Platform::ResolveExecutablePath() {
return File::LinkTarget("/proc/self/exe");
}

} // namespace bin
} // namespace dart

Expand Down
19 changes: 19 additions & 0 deletions runtime/bin/platform_macos.cc
Expand Up @@ -5,6 +5,8 @@
#include "platform/globals.h"
#if defined(TARGET_OS_MACOS)

#include <mach-o/dyld.h>

#include "bin/platform.h"

#include <crt_externs.h> // NOLINT
Expand Down Expand Up @@ -75,6 +77,23 @@ void Platform::FreeEnvironment(char** env, intptr_t count) {
delete[] env;
}


char* Platform::ResolveExecutablePath() {
// Get the required length of the buffer.
uint32_t path_size = 0;
char* path = NULL;
if (_NSGetExecutablePath(path, &path_size) == 0) {
return NULL;
}
// Allocate buffer and get executable path.
path = reinterpret_cast<char*>(malloc(path_size));
if (_NSGetExecutablePath(path, &path_size) != 0) {
free(path);
return NULL;
}
return path;
}

} // namespace bin
} // namespace dart

Expand Down
20 changes: 20 additions & 0 deletions runtime/bin/platform_win.cc
Expand Up @@ -80,6 +80,26 @@ void Platform::FreeEnvironment(char** env, intptr_t count) {
delete[] env;
}


char* Platform::ResolveExecutablePath() {
// GetModuleFileNameW cannot directly provide information on the
// required buffer size, so start out with a buffer large enough to
// hold any Windows path.
const int kTmpBufferSize = 32768;
wchar_t* tmp_buffer = reinterpret_cast<wchar_t*>(malloc(kTmpBufferSize));
// Ensure no last error before calling GetModuleFileNameW.
SetLastError(ERROR_SUCCESS);
// Get the required length of the buffer.
int path_length = GetModuleFileNameW(NULL, tmp_buffer, kTmpBufferSize);
if (GetLastError() != ERROR_SUCCESS) {
free(tmp_buffer);
return NULL;
}
char* path = StringUtils::WideToUtf8(tmp_buffer);
free(tmp_buffer);
return path;
}

} // namespace bin
} // namespace dart

Expand Down
8 changes: 5 additions & 3 deletions sdk/lib/io/platform.dart
Expand Up @@ -39,7 +39,7 @@ part of dart.io;
* Map<String, String> envVars = Platform.environment;
* print(envVars['PATH']);
* }
*
*
* ## Determine the OS
*
* You can get the name of the operating system as a string with the
Expand All @@ -53,7 +53,7 @@ part of dart.io;
* String os = Platform.operatingSystem;
* // Or, use a predicate getter.
* if (Platform.isMacOS) {
* Print('is a Mac');
* Print('is a Mac');
* } else {
* print('is not a Mac');
* }
Expand All @@ -62,7 +62,7 @@ part of dart.io;
* ## Other resources
*
* [Dart by Example](https://www.dartlang.org/dart-by-example/#dart-io-and-command-line-apps)
* provides additional task-oriented code samples that show how to use
* provides additional task-oriented code samples that show how to use
* various API from the [dart:io] library.
*/
class Platform {
Expand Down Expand Up @@ -131,6 +131,8 @@ class Platform {
* Returns the path of the executable used to run the script in this
* isolate.
*
* If supported by the platform the returned path will be absolute.
*
* If the execution environment does not support [executable] an empty
* string is returned.
*/
Expand Down
9 changes: 9 additions & 0 deletions tests/standalone/io/platform_test.dart
Expand Up @@ -25,6 +25,15 @@ test() {
var environment = Platform.environment;
Expect.isTrue(environment is Map<String, String>);
Expect.isTrue(Platform.executable.contains('dart'));
if (!Platform.isWindows) {
Expect.isTrue(Platform.executable.startsWith('/'));
} else {
// This assumes that tests (both locally and on the bots) are
// running off a location referred to by a drive letter. If a UNC
// location is used or long names ("\\?\" prefix) is used this
// needs to be fixed.
Expect.equals(Platform.executable.substring(1, 3), ':\\');
}
// Move directory to be sure script is correct.
var oldDir = Directory.current;
Directory.current = Directory.current.parent;
Expand Down

0 comments on commit e03ab17

Please sign in to comment.