8000 node/src/node.cc at master · MoonBall/node · GitHub
[go: up one dir, main page]

Skip to content 7FFF

Latest commit

 

History

History
4661 lines (3802 loc) · 134 KB

File metadata and controls

4661 lines (3802 loc) · 134 KB
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "node.h"
#include "node_buffer.h"
#include "node_constants.h"
#include "node_javascript.h"
#include "node_version.h"
#include "node_internals.h"
#include "node_revert.h"
#include "node_debug_options.h"
#if defined HAVE_PERFCTR
#include "node_counters.h"
#endif
#if HAVE_OPENSSL
#include "node_crypto.h"
#endif
#if defined(NODE_HAVE_I18N_SUPPORT)
#include "node_i18n.h"
#endif
#if HAVE_INSPECTOR
#include "inspector_io.h"
#endif
#if defined HAVE_DTRACE || defined HAVE_ETW
#include "node_dtrace.h"
#endif
#if defined HAVE_LTTNG
#include "node_lttng.h"
#endif
#include "ares.h"
#include "async-wrap.h"
#include "async-wrap-inl.h"
#include "env.h"
#include "env-inl.h"
#include "handle_wrap.h"
#include "http_parser.h"
#include "req-wrap.h"
#include "req-wrap-inl.h"
#include "string_bytes.h"
#include "tracing/agent.h"
#include "util.h"
#include "uv.h"
#if NODE_USE_V8_PLATFORM
#include "libplatform/libplatform.h"
#endif // NODE_USE_V8_PLATFORM
#include "v8-debug.h"
#include "v8-profiler.h"
#include "zlib.h"
#ifdef NODE_ENABLE_VTUNE_PROFILING
#include "../deps/v8/src/third_party/vtune/v8-vtune.h"
#endif
#include <errno.h>
#include <fcntl.h> // _O_RDWR
#include <limits.h> // PATH_MAX
#include <locale.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <string>
#include <vector>
#if defined(NODE_HAVE_I18N_SUPPORT)
#include <unicode/uvernum.h>
#endif
#if defined(LEAK_SANITIZER)
#include <sanitizer/lsan_interface.h>
#endif
#if defined(_MSC_VER)
#include <direct.h>
#include <io.h>
#define getpid GetCurrentProcessId
#define umask _umask
typedef int mode_t;
#else
#include <pthread.h>
#include <sys/resource.h> // getrlimit, setrlimit
#include <unistd.h> // setuid, getuid
#endif
#if defined(__POSIX__) && !defined(__ANDROID__)
#include <pwd.h> // getpwnam()
#include <grp.h> // getgrnam()
#endif
#ifdef __APPLE__
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#elif !defined(_MSC_VER)
extern char **environ;
#endif
namespace node {
using v8::Array;
using v8::ArrayBuffer;
using v8::Boolean;
using v8::Context;
using v8::EscapableHandleScope;
using v8::Exception;
using v8::Float64Array;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::HandleScope;
using v8::HeapStatistics;
using v8::Integer;
using v8::Isolate;
using v8::Local;
using v8::Locker;
using v8::MaybeLocal;
using v8::Message;
using v8::Name;
using v8::NamedPropertyHandlerConfiguration;
using v8::Null;
using v8::Number;
using v8::Object;
using v8::ObjectTemplate;
using v8::Promise;
using v8::PromiseHookType;
using v8::PromiseRejectMessage;
using v8::PropertyCallbackInfo;
using v8::ScriptOrigin;
using v8::SealHandleScope;
using v8::String;
using v8::TryCatch;
using v8::Uint32Array;
using v8::V8;
using v8::Value;
using AsyncHooks = node::Environment::AsyncHooks;
static bool print_eval = false;
static bool force_repl = false;
static bool syntax_check_only = false;
static bool trace_deprecation = false;
static bool throw_deprecation = false;
static bool trace_sync_io = false;
static bool track_heap_objects = false;
static const char* eval_string = nullptr;
static std::vector<std::string> preload_modules;
static const int v8_default_thread_pool_size = 4;
static int v8_thread_pool_size = v8_default_thread_pool_size;
static bool prof_process = false;
static bool v8_is_profiling = false;
static bool node_is_initialized = false;
static node_module* modpending;
static node_module* modlist_builtin;
static node_module* modlist_linked;
static node_module* modlist_addon;
static bool trace_enabled = false;
static std::string trace_enabled_categories; // NOLINT(runtime/string)
static bool abort_on_uncaught_exception = false;
#if defined(NODE_HAVE_I18N_SUPPORT)
// Path to ICU data (for i18n / Intl)
std::string icu_data_dir; // NOLINT(runtime/string)
#endif
// N-API is in experimental state, disabled by default.
bool load_napi_modules = false;
// used by C++ modules as well
bool no_deprecation = false;
#if HAVE_OPENSSL
// use OpenSSL's cert store instead of bundled certs
bool ssl_openssl_cert_store =
#if defined(NODE_OPENSSL_CERT_STORE)
true;
#else
false;
#endif
# if NODE_FIPS_MODE
// used by crypto module
bool enable_fips_crypto = false;
bool force_fips_crypto = false;
# endif // NODE_FIPS_MODE
std::string openssl_config; // NOLINT(runtime/string)
#endif // HAVE_OPENSSL
// true if process warnings should be suppressed
bool no_process_warnings = false;
bool trace_warnings = false;
// Set in node.cc by ParseArgs when --preserve-symlinks is used.
// Used in node_config.cc to set a constant on process.binding('config')
// that is used by lib/module.js
bool config_preserve_symlinks = false;
// Set by ParseArgs when --pending-deprecation or NODE_PENDING_DEPRECATION
// is used.
bool config_pending_deprecation = false;
// Set in node.cc by ParseArgs when --redirect-warnings= is used.
std::string config_warning_file; // NOLINT(runtime/string)
// Set in node.cc by ParseArgs when --expose-internals or --expose_internals is
// used.
// Used in node_config.cc to set a constant on process.binding('config')
// that is used by lib/internal/bootstrap_node.js
bool config_expose_internals = false;
bool v8_initialized = false;
bool linux_at_secure = false;
// process-relative uptime base, initialized at start-up
static double prog_start_time;
static Mutex node_isolate_mutex;
static v8::Isolate* node_isolate;
node::DebugOptions debug_options;
static struct {
#if NODE_USE_V8_PLATFORM
void Initialize(int thread_pool_size) {
platform_ = v8::platform::CreateDefaultPlatform(thread_pool_size);
V8::InitializePlatform(platform_);
tracing::TraceEventHelper::SetCurrentPlatform(platform_);
}
void PumpMessageLoop(Isolate* isolate) {
v8::platform::PumpMessageLoop(platform_, isolate);
}
void Dispose() {
delete platform_;
platform_ = nullptr;
}
#if HAVE_INSPECTOR
bool StartInspector(Environment *env, const char* script_path,
const node::DebugOptions& options) {
// Inspector agent can't fail to start, but if it was configured to listen
// right away on the websocket port and fails to bind/etc, this will return
// false.
return env->inspector_agent()->Start(platform_, script_path, options);
}
bool InspectorStarted(Environment *env) {
return env->inspector_agent()->IsStarted();
}
#endif // HAVE_INSPECTOR
void StartTracingAgent() {
CHECK(tracing_agent_ == nullptr);
tracing_agent_ = new tracing::Agent();
tracing_agent_->Start(platform_, trace_enabled_categories);
}
void StopTracingAgent() {
tracing_agent_->Stop();
}
v8::Platform* platform_;
tracing::Agent* tracing_agent_;
#else // !NODE_USE_V8_PLATFORM
void Initialize(int thread_pool_size) {}
void PumpMessageLoop(Isolate* isolate) {}
void Dispose() {}
bool StartInspector(Environment *env, const char* script_path,
const node::DebugOptions& options) {
env->ThrowError("Node compiled with NODE_USE_V8_PLATFORM=0");
return true;
}
void StartTracingAgent() {
fprintf(stderr, "Node compiled with NODE_USE_V8_PLATFORM=0, "
"so event tracing is not available.\n");
}
void StopTracingAgent() {}
#endif // !NODE_USE_V8_PLATFORM
#if !NODE_USE_V8_PLATFORM || !HAVE_INSPECTOR
bool InspectorStarted(Environment *env) {
return false;
}
#endif // !NODE_USE_V8_PLATFORM || !HAVE_INSPECTOR
} v8_platform;
#ifdef __POSIX__
static const unsigned kMaxSignal = 32;
#endif
static void PrintErrorString(const char* format, ...) {
va_list ap;
va_start(ap, format);
#ifdef _WIN32
HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
// Check if stderr is something other than a tty/console
if (stderr_handle == INVALID_HANDLE_VALUE ||
stderr_handle == nullptr ||
uv_guess_handle(_fileno(stderr)) != UV_TTY) {
vfprintf(stderr, format, ap);
va_end(ap);
return;
}
// Fill in any placeholders
int n = _vscprintf(format, ap);
std::vector<char> out(n + 1);
vsprintf(out.data(), format, ap);
// Get required wide buffer size
n = MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, nullptr, 0);
std::vector<wchar_t> wbuf(n);
MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, wbuf.data(), n);
// Don't include the null character in the output
CHECK_GT(n, 0);
WriteConsoleW(stderr_handle, wbuf.data(), n - 1, nullptr, nullptr);
#else
vfprintf(stderr, format, ap);
#endif
va_end(ap);
}
static void CheckImmediate(uv_check_t* handle) {
Environment* env = Environment::from_immediate_check_handle(handle);
HandleScope scope(env->isolate());
Context::Scope context_scope(env->context());
MakeCallback(env->isolate(),
env->process_object(),
env->immediate_callback_string(),
0,
nullptr,
0, 0).ToLocalChecked();
}
static void IdleImmediateDummy(uv_idle_t* handle) {
// Do nothing. Only for maintaining event loop.
// TODO(bnoordhuis) Maybe make libuv accept nullptr idle callbacks.
}
static inline const char *errno_string(int errorno) {
#define ERRNO_CASE(e) case e: return #e;
switch (errorno) {
#ifdef EACCES
ERRNO_CASE(EACCES);
#endif
#ifdef EADDRINUSE
ERRNO_CASE(EADDRINUSE);
#endif
#ifdef EADDRNOTAVAIL
ERRNO_CASE(EADDRNOTAVAIL);
#endif
#ifdef EAFNOSUPPORT
ERRNO_CASE(EAFNOSUPPORT);
#endif
#ifdef EAGAIN
ERRNO_CASE(EAGAIN);
#endif
#ifdef EWOULDBLOCK
# if EAGAIN != EWOULDBLOCK
ERRNO_CASE(EWOULDBLOCK);
# endif
#endif
#ifdef EALREADY
ERRNO_CASE(EALREADY);
#endif
#ifdef EBADF
ERRNO_CASE(EBADF);
#endif
#ifdef EBADMSG
ERRNO_CASE(EBADMSG);
#endif
#ifdef EBUSY
ERRNO_CASE(EBUSY);
#endif
#ifdef ECANCELED
ERRNO_CASE(ECANCELED);
#endif
#ifdef ECHILD
ERRNO_CASE(ECHILD);
#endif
#ifdef ECONNABORTED
ERRNO_CASE(ECONNABORTED);
#endif
#ifdef ECONNREFUSED
ERRNO_CASE(ECONNREFUSED);
#endif
#ifdef ECONNRESET
ERRNO_CASE(ECONNRESET);
#endif
#ifdef EDEADLK
ERRNO_CASE(EDEADLK);
#endif
#ifdef EDESTADDRREQ
ERRNO_CASE(EDESTADDRREQ);
#endif
#ifdef EDOM
ERRNO_CASE(EDOM);
#endif
#ifdef EDQUOT
ERRNO_CASE(EDQUOT);
#endif
#ifdef EEXIST
ERRNO_CASE(EEXIST);
#endif
#ifdef EFAULT
ERRNO_CASE(EFAULT);
#endif
#ifdef EFBIG
ERRNO_CASE(EFBIG);
#endif
#ifdef EHOSTUNREACH
ERRNO_CASE(EHOSTUNREACH);
#endif
#ifdef EIDRM
ERRNO_CASE(EIDRM);
#endif
#ifdef EILSEQ
ERRNO_CASE(EILSEQ);
#endif
#ifdef EINPROGRESS
ERRNO_CASE(EINPROGRESS);
#endif
#ifdef EINTR
ERRNO_CASE(EINTR);
#endif
#ifdef EINVAL
ERRNO_CASE(EINVAL);
#endif
#ifdef EIO
ERRNO_CASE(EIO);
#endif
#ifdef EISCONN
ERRNO_CASE(EISCONN);
#endif
#ifdef EISDIR
ERRNO_CASE(EISDIR);
#endif
#ifdef ELOOP
ERRNO_CASE(ELOOP);
#endif
#ifdef EMFILE
ERRNO_CASE(EMFILE);
#endif
#ifdef EMLINK
ERRNO_CASE(EMLINK);
#endif
#ifdef EMSGSIZE
ERRNO_CASE(EMSGSIZE);
#endif
#ifdef EMULTIHOP
ERRNO_CASE(EMULTIHOP);
#endif
#ifdef ENAMETOOLONG
ERRNO_CASE(ENAMETOOLONG);
#endif
#ifdef ENETDOWN
ERRNO_CASE(ENETDOWN);
#endif
#ifdef ENETRESET
ERRNO_CASE(ENETRESET);
#endif
#ifdef ENETUNREACH
ERRNO_CASE(ENETUNREACH);
#endif
#ifdef ENFILE
ERRNO_CASE(ENFILE);
#endif
#ifdef ENOBUFS
ERRNO_CASE(ENOBUFS);
#endif
#ifdef ENODATA
ERRNO_CASE(ENODATA);
#endif
#ifdef ENODEV
ERRNO_CASE(ENODEV);
#endif
#ifdef ENOENT
ERRNO_CASE(ENOENT);
#endif
#ifdef ENOEXEC
ERRNO_CASE(ENOEXEC);
#endif
#ifdef ENOLINK
ERRNO_CASE(ENOLINK);
#endif
#ifdef ENOLCK
# if ENOLINK != ENOLCK
ERRNO_CASE(ENOLCK);
# endif
#endif
#ifdef ENOMEM
ERRNO_CASE(ENOMEM);
#endif
#ifdef ENOMSG
ERRNO_CASE(ENOMSG);
#endif
#ifdef ENOPROTOOPT
57D8 ERRNO_CASE(ENOPROTOOPT);
#endif
#ifdef ENOSPC
ERRNO_CASE(ENOSPC);
#endif
#ifdef ENOSR
ERRNO_CASE(ENOSR);
#endif
#ifdef ENOSTR
ERRNO_CASE(ENOSTR);
#endif
#ifdef ENOSYS
ERRNO_CASE(ENOSYS);
#endif
#ifdef ENOTCONN
ERRNO_CASE(ENOTCONN);
#endif
#ifdef ENOTDIR
ERRNO_CASE(ENOTDIR);
#endif
#ifdef ENOTEMPTY
# if ENOTEMPTY != EEXIST
ERRNO_CASE(ENOTEMPTY);
# endif
#endif
#ifdef ENOTSOCK
ERRNO_CASE(ENOTSOCK);
#endif
#ifdef ENOTSUP
ERRNO_CASE(ENOTSUP);
#else
# ifdef EOPNOTSUPP
ERRNO_CASE(EOPNOTSUPP);
# endif
#endif
#ifdef ENOTTY
ERRNO_CASE(ENOTTY);
#endif
#ifdef ENXIO
ERRNO_CASE(ENXIO);
#endif
#ifdef EOVERFLOW
ERRNO_CASE(EOVERFLOW);
#endif
#ifdef EPERM
ERRNO_CASE(EPERM);
#endif
#ifdef EPIPE
ERRNO_CASE(EPIPE);
#endif
#ifdef EPROTO
ERRNO_CASE(EPROTO);
#endif
#ifdef EPROTONOSUPPORT
ERRNO_CASE(EPROTONOSUPPORT);
#endif
#ifdef EPROTOTYPE
ERRNO_CASE(EPROTOTYPE);
#endif
#ifdef ERANGE
ERRNO_CASE(ERANGE);
#endif
#ifdef EROFS
ERRNO_CASE(EROFS);
#endif
#ifdef ESPIPE
ERRNO_CASE(ESPIPE);
#endif
#ifdef ESRCH
ERRNO_CASE(ESRCH);
#endif
#ifdef ESTALE
ERRNO_CASE(ESTALE);
#endif
#ifdef ETIME
ERRNO_CASE(ETIME);
#endif
#ifdef ETIMEDOUT
ERRNO_CASE(ETIMEDOUT);
#endif
#ifdef ETXTBSY
ERRNO_CASE(ETXTBSY);
#endif
#ifdef EXDEV
ERRNO_CASE(EXDEV);
#endif
default: return "";
}
}
const char *signo_string(int signo) {
#define SIGNO_CASE(e) case e: return #e;
switch (signo) {
#ifdef SIGHUP
SIGNO_CASE(SIGHUP);
#endif
#ifdef SIGINT
SIGNO_CASE(SIGINT);
#endif
#ifdef SIGQUIT
SIGNO_CASE(SIGQUIT);
#endif
#ifdef SIGILL
SIGNO_CASE(SIGILL);
#endif
#ifdef SIGTRAP
SIGNO_CASE(SIGTRAP);
#endif
#ifdef SIGABRT
SIGNO_CASE(SIGABRT);
#endif
#ifdef SIGIOT
# if SIGABRT != SIGIOT
SIGNO_CASE(SIGIOT);
# endif
#endif
#ifdef SIGBUS
SIGNO_CASE(SIGBUS);
#endif
#ifdef SIGFPE
SIGNO_CASE(SIGFPE);
#endif
#ifdef SIGKILL
SIGNO_CASE(SIGKILL);
#endif
#ifdef SIGUSR1
SIGNO_CASE(SIGUSR1);
#endif
#ifdef SIGSEGV
SIGNO_CASE(SIGSEGV);
#endif
#ifdef SIGUSR2
SIGNO_CASE(SIGUSR2);
#endif
#ifdef SIGPIPE
SIGNO_CASE(SIGPIPE);
#endif
#ifdef SIGALRM
SIGNO_CASE(SIGALRM);
#endif
SIGNO_CASE(SIGTERM);
#ifdef SIGCHLD
SIGNO_CASE(SIGCHLD);
#endif
#ifdef SIGSTKFLT
SIGNO_CASE(SIGSTKFLT);
#endif
#ifdef SIGCONT
SIGNO_CASE(SIGCONT);
#endif
#ifdef SIGSTOP
SIGNO_CASE(SIGSTOP);
#endif
#ifdef SIGTSTP
SIGNO_CASE(SIGTSTP);
#endif
#ifdef SIGBREAK
SIGNO_CASE(SIGBREAK);
#endif
#ifdef SIGTTIN
SIGNO_CASE(SIGTTIN);
#endif
#ifdef SIGTTOU
SIGNO_CASE(SIGTTOU);
#endif
#ifdef SIGURG
SIGNO_CASE(SIGURG);
#endif
#ifdef SIGXCPU
SIGNO_CASE(SIGXCPU);
#endif
#ifdef SIGXFSZ
SIGNO_CASE(SIGXFSZ);
#endif
#ifdef SIGVTALRM
SIGNO_CASE(SIGVTALRM);
#endif
#ifdef SIGPROF
SIGNO_CASE(SIGPROF);
#endif
#ifdef SIGWINCH
SIGNO_CASE(SIGWINCH);
#endif
#ifdef SIGIO
SIGNO_CASE(SIGIO);
#endif
#ifdef SIGPOLL
# if SIGPOLL != SIGIO
SIGNO_CASE(SIGPOLL);
# endif
#endif
#ifdef SIGLOST
# if SIGLOST != SIGABRT
SIGNO_CASE(SIGLOST);
# endif
#endif
#ifdef SIGPWR
# if SIGPWR != SIGLOST
SIGNO_CASE(SIGPWR);
# endif
#endif
#ifdef SIGINFO
# if !defined(SIGPWR) || SIGINFO != SIGPWR
SIGNO_CASE(SIGINFO);
# endif
#endif
#ifdef SIGSYS
SIGNO_CASE(SIGSYS);
#endif
default: return "";
}
}
Local<Value> ErrnoException(Isolate* isolate,
int errorno,
const char *syscall,
const char *msg,
const char *path) {
Environment* env = Environment::GetCurrent(isolate);
Local<Value> e;
Local<String> estring = OneByteString(env->isolate(), errno_string(errorno));
if (msg == nullptr || msg[0] == '\0') {
msg = strerror(errorno);
}
Local<String> message = OneByteString(env->isolate(), msg);
Local<String> cons =
String::Concat(estring, FIXED_ONE_BYTE_STRING(env->isolate(), ", "));
cons = String::Concat(cons, message);
Local<String> path_string;
if (path != nullptr) {
// FIXME(bnoordhuis) It's questionable to interpret the file path as UTF-8.
path_string = String::NewFromUtf8(env->isolate(), path);
}
if (path_string.IsEmpty() == false) {
cons = String::Concat(cons, FIXED_ONE_BYTE_STRING(env->isolate(), " '"));
cons = String::Concat(cons, path_string);
cons = String::Concat(cons, FIXED_ONE_BYTE_STRING(env->isolate(), "'"));
}
e = Exception::Error(cons);
Local<Object> obj = e->ToObject(env->isolate());
obj->Set(env->errno_string(), Integer::New(env->isolate(), errorno));
obj->Set(env->code_string(), estring);
if (path_string.IsEmpty() == false) {
obj->Set(env->path_string(), path_string);
}
if (syscall != nullptr) {
obj->Set(env->syscall_string(), OneByteString(env->isolate(), syscall));
}
return e;
}
static Local<String> StringFromPath(Isolate* isolate, const char* path) {
#ifdef _WIN32
if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
return String::Concat(FIXED_ONE_BYTE_STRING(isolate, "\\\\"),
String::NewFromUtf8(isolate, path + 8));
} else if (strncmp(path, "\\\\?\\", 4) == 0) {
return String::NewFromUtf8(isolate, path + 4);
}
#endif
return String::NewFromUtf8(isolate, path);
}
Local<Value> UVException(Isolate* isolate,
int errorno,
const char* syscall,
const char* msg,
const char* path) {
return UVException(isolate, errorno, syscall, msg, path, nullptr);
}
Local<Value> UVException(Isolate* isolate,
int errorno,
const char* syscall,
const char* msg,
const char* path,
const char* dest) {
Environment* env = Environment::GetCurrent(isolate);
if (!msg || !msg[0])
msg = uv_strerror(errorno);
Local<String> js_code = OneByteString(isolate, uv_err_name(errorno));
Local<String> js_syscall = OneByteString(isolate, syscall);
Local<String> js_path;
Local<String> js_dest;
Local<String> js_msg = js_code;
js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, ": "));
js_msg = String::Concat(js_msg, OneByteString(isolate, msg));
js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, ", "));
js_msg = String::Concat(js_msg, js_syscall);
if (path != nullptr) {
js_path = StringFromPath(isolate, path);
js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, " '"));
js_msg = String::Concat(js_msg, js_path);
js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
}
if (dest != nullptr) {
js_dest = StringFromPath(isolate, dest);
js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, " -> '"));
js_msg = String::Concat(js_msg, js_dest);
js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
}
Local<Object> e = Exception::Error(js_msg)->ToObject(isolate);
e->Set(env->errno_string(), Integer::New(isolate, errorno));
e->Set(env->code_string(), js_code);
e->Set(env->syscall_string(), js_syscall);
if (!js_path.IsEmpty())
e->Set(env->path_string(), js_path);
if (!js_dest.IsEmpty())
e->Set(env->dest_string(), js_dest);
return e;
}
// Look up environment variable unless running as setuid root.
bool SafeGetenv(const char* key, std::string* text) {
#ifndef _WIN32
if (linux_at_secure || getuid() != geteuid() || getgid() != getegid())
goto fail;
#endif
if (const char* value = getenv(key)) {
*text = value;
return true;
}
fail:
text->clear();
return false;
}
#ifdef _WIN32
0