Browse Source

Remove platform files, and use uv platform api

v0.7.4-release
Igor Zinkovsky 13 years ago
parent
commit
500c8f45f5
  1. 8
      node.gyp
  2. 59
      src/node.cc
  3. 4
      src/node_buffer.cc
  4. 4
      src/node_constants.cc
  5. 1
      src/node_file.cc
  6. 90
      src/node_os.cc
  7. 10
      src/node_vars.h
  8. 49
      src/platform.h
  9. 227
      src/platform_darwin.cc
  10. 146
      src/platform_darwin_proctitle.cc
  11. 178
      src/platform_freebsd.cc
  12. 394
      src/platform_linux.cc
  13. 52
      src/platform_none.cc
  14. 178
      src/platform_openbsd.cc
  15. 305
      src/platform_sunos.cc
  16. 292
      src/platform_win32.cc
  17. 79
      src/platform_win32.h
  18. 6
      test/simple/test-os.js

8
node.gyp

@ -109,7 +109,6 @@
'src/node_string.h', 'src/node_string.h',
'src/node_version.h', 'src/node_version.h',
'src/pipe_wrap.h', 'src/pipe_wrap.h',
'src/platform.h',
'src/req_wrap.h', 'src/req_wrap.h',
'src/stream_wrap.h', 'src/stream_wrap.h',
'src/v8_typed_array.h', 'src/v8_typed_array.h',
@ -152,9 +151,6 @@
[ 'OS=="win"', { [ 'OS=="win"', {
'sources': [ 'sources': [
'src/platform_win32.cc',
# headers to make for a more pleasant IDE experience
'src/platform_win32.h',
'tools/msvs/res/node.rc', 'tools/msvs/res/node.rc',
], ],
'defines': [ 'defines': [
@ -172,25 +168,21 @@
] ]
}], }],
[ 'OS=="mac"', { [ 'OS=="mac"', {
'sources': [ 'src/platform_darwin.cc' ],
'libraries': [ '-framework Carbon' ], 'libraries': [ '-framework Carbon' ],
}], }],
[ 'OS=="linux"', { [ 'OS=="linux"', {
'sources': [ 'src/platform_linux.cc' ],
'libraries': [ 'libraries': [
'-ldl', '-ldl',
'-lutil' # needed for openpty '-lutil' # needed for openpty
], ],
}], }],
[ 'OS=="freebsd"', { [ 'OS=="freebsd"', {
'sources': [ 'src/platform_freebsd.cc' ],
'libraries': [ 'libraries': [
'-lutil', '-lutil',
'-lkvm', '-lkvm',
], ],
}], }],
[ 'OS=="solaris"', { [ 'OS=="solaris"', {
'sources': [ 'src/platform_sunos.cc' ],
'libraries': [ 'libraries': [
'-lkstat', '-lkstat',
], ],

59
src/node.cc

@ -56,16 +56,11 @@ typedef int mode_t;
#include <errno.h> #include <errno.h>
#include <sys/types.h> #include <sys/types.h>
#if defined(__MINGW32__) || defined(_MSC_VER)
# include <platform_win32.h> /* winapi_perror() */
#endif
#ifdef __POSIX__ #ifdef __POSIX__
# include <pwd.h> /* getpwnam() */ # include <pwd.h> /* getpwnam() */
# include <grp.h> /* getgrnam() */ # include <grp.h> /* getgrnam() */
#endif #endif
#include "platform.h"
#include <node_buffer.h> #include <node_buffer.h>
#ifdef __POSIX__ #ifdef __POSIX__
# include <node_io_watcher.h> # include <node_io_watcher.h>
@ -137,7 +132,7 @@ extern char **environ;
#define module_load_list NODE_VAR(module_load_list) #define module_load_list NODE_VAR(module_load_list)
#define node_isolate NODE_VAR(node_isolate) #define node_isolate NODE_VAR(node_isolate)
#define debugger_running NODE_VAR(debugger_running) #define debugger_running NODE_VAR(debugger_running)
#define prog_start_time NODE_VAR(prog_start_time)
namespace node { namespace node {
@ -854,6 +849,30 @@ Local<Value> UVException(int errorno,
#ifdef _WIN32 #ifdef _WIN32
// Does about the same as strerror(),
// but supports all windows error messages
static const char *winapi_strerror(const int errorno) {
char *errmsg = NULL;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, NULL);
if (errmsg) {
// Remove trailing newlines
for (int i = strlen(errmsg) - 1;
i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) {
errmsg[i] = '\0';
}
return errmsg;
} else {
// FormatMessage failed
return "Unknown error";
}
}
Local<Value> WinapiErrnoException(int errorno, Local<Value> WinapiErrnoException(int errorno,
const char* syscall, const char* syscall,
const char* msg, const char* msg,
@ -1485,17 +1504,19 @@ static void CheckStatus(uv_timer_t* watcher, int status) {
} }
} }
static Handle<Value> Uptime(const Arguments& args) { static Handle<Value> Uptime(const Arguments& args) {
HandleScope scope; HandleScope scope;
assert(args.Length() == 0); assert(args.Length() == 0);
double uptime;
double uptime = Platform::GetUptime(true); uv_err_t err = uv_uptime(&uptime);
if (uptime < 0) { if (err.code != UV_OK) {
return Undefined(); return Undefined();
} }
return scope.Close(Number::New(uptime)); return scope.Close(Number::New(uptime - prog_start_time));
} }
@ -1537,10 +1558,10 @@ v8::Handle<v8::Value> MemoryUsage(const v8::Arguments& args) {
size_t rss; size_t rss;
int r = Platform::GetMemory(&rss); uv_err_t err = uv_resident_set_memory(&rss);
if (r != 0) { if (err.code != UV_OK) {
return ThrowException(Exception::Error(String::New(strerror(errno)))); return ThrowException(UVException(err.code, "uv_resident_set_memory"));
} }
Local<Object> info = Object::New(); Local<Object> info = Object::New();
@ -1829,9 +1850,9 @@ static Handle<Value> Binding(const Arguments& args) {
static Handle<Value> ProcessTitleGetter(Local<String> property, static Handle<Value> ProcessTitleGetter(Local<String> property,
const AccessorInfo& info) { const AccessorInfo& info) {
HandleScope scope; HandleScope scope;
int len; char buffer[512];
const char *s = Platform::GetProcessTitle(&len); uv_get_process_title(buffer, sizeof(buffer));
return scope.Close(s ? String::New(s, len) : String::Empty()); return scope.Close(String::New(buffer));
} }
@ -1840,7 +1861,8 @@ static void ProcessTitleSetter(Local<String> property,
const AccessorInfo& info) { const AccessorInfo& info) {
HandleScope scope; HandleScope scope;
String::Utf8Value title(value->ToString()); String::Utf8Value title(value->ToString());
Platform::SetProcessTitle(*title); // TODO: protect with a lock
uv_set_process_title(*title);
} }
@ -2490,8 +2512,11 @@ static Handle<Value> DebugProcess(const Arguments& args) {
char** Init(int argc, char *argv[]) { char** Init(int argc, char *argv[]) {
// Initialize prog_start_time to get relative uptime.
uv_uptime(&prog_start_time);
// Hack aroung with the argv pointer. Used for process.title = "blah". // Hack aroung with the argv pointer. Used for process.title = "blah".
argv = node::Platform::SetupArgs(argc, argv); argv = uv_setup_args(argc, argv);
// Parse a few arguments which are specific to Node. // Parse a few arguments which are specific to Node.
node::ParseArgs(argc, argv); node::ParseArgs(argc, argv);

4
src/node_buffer.cc

@ -29,10 +29,6 @@
#include <stdlib.h> // malloc, free #include <stdlib.h> // malloc, free
#include <string.h> // memcpy #include <string.h> // memcpy
#ifdef __MINGW32__
# include "platform.h"
#endif
#ifdef __POSIX__ #ifdef __POSIX__
# include <arpa/inet.h> // htons, htonl # include <arpa/inet.h> // htons, htonl
#endif #endif

4
src/node_constants.cc

@ -32,10 +32,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#if defined(__MINGW32__) || defined(_MSC_VER)
# include <platform_win32.h>
#endif
#if HAVE_OPENSSL #if HAVE_OPENSSL
# include <openssl/ssl.h> # include <openssl/ssl.h>
#endif #endif

1
src/node_file.cc

@ -37,7 +37,6 @@
#if defined(__MINGW32__) || defined(_MSC_VER) #if defined(__MINGW32__) || defined(_MSC_VER)
# include <io.h> # include <io.h>
# include <platform_win32.h>
#endif #endif

90
src/node_os.cc

@ -22,7 +22,6 @@
#include <node.h> #include <node.h>
#include <node_os.h> #include <node_os.h>
#include "platform.h"
#include <v8.h> #include <v8.h>
@ -31,8 +30,6 @@
#ifdef __MINGW32__ #ifdef __MINGW32__
# include <io.h> # include <io.h>
# include <platform_win32.h>
#endif #endif
#ifdef __POSIX__ #ifdef __POSIX__
@ -105,13 +102,39 @@ static Handle<Value> GetOSRelease(const Arguments& args) {
static Handle<Value> GetCPUInfo(const Arguments& args) { static Handle<Value> GetCPUInfo(const Arguments& args) {
HandleScope scope; HandleScope scope;
Local<Array> cpus; uv_cpu_info_t* cpu_infos;
int r = Platform::GetCPUInfo(&cpus); int count, i;
if (r < 0) { uv_err_t err = uv_cpu_info(&cpu_infos, &count);
if (err.code != UV_OK) {
return Undefined(); return Undefined();
} }
Local<Array> cpus = Array::New();
for (i = 0; i < count; i++) {
Local<Object> times_info = Object::New();
times_info->Set(String::New("user"),
Integer::New(cpu_infos[i].cpu_times.user));
times_info->Set(String::New("nice"),
Integer::New(cpu_infos[i].cpu_times.nice));
times_info->Set(String::New("sys"),
Integer::New(cpu_infos[i].cpu_times.sys));
times_info->Set(String::New("idle"),
Integer::New(cpu_infos[i].cpu_times.idle));
times_info->Set(String::New("irq"),
Integer::New(cpu_infos[i].cpu_times.irq));
Local<Object> cpu_info = Object::New();
cpu_info->Set(String::New("model"), String::New(cpu_infos[i].model));
cpu_info->Set(String::New("speed"), Integer::New(cpu_infos[i].speed));
cpu_info->Set(String::New("times"), times_info);
(*cpus)->Set(i,cpu_info);
}
uv_free_cpu_info(cpu_infos, count);
return scope.Close(cpus); return scope.Close(cpus);
} }
@ -139,9 +162,11 @@ static Handle<Value> GetTotalMemory(const Arguments& args) {
static Handle<Value> GetUptime(const Arguments& args) { static Handle<Value> GetUptime(const Arguments& args) {
HandleScope scope; HandleScope scope;
double uptime = Platform::GetUptime(); double uptime;
if (uptime < 0) { uv_err_t err = uv_uptime(&uptime);
if (err.code != UV_OK) {
return Undefined(); return Undefined();
} }
@ -163,7 +188,54 @@ static Handle<Value> GetLoadAvg(const Arguments& args) {
static Handle<Value> GetInterfaceAddresses(const Arguments& args) { static Handle<Value> GetInterfaceAddresses(const Arguments& args) {
return Platform::GetInterfaceAddresses(); HandleScope scope;
uv_interface_address_t* interfaces;
int count, i;
char ip[INET6_ADDRSTRLEN];
Local<Object> ret, o;
Local<String> name, family;
Local<Array> ifarr;
uv_err_t err = uv_interface_addresses(&interfaces, &count);
if (err.code != UV_OK) {
return Undefined();
}
ret = Object::New();
for (i = 0; i < count; i++) {
name = String::New(interfaces[i].name);
if (ret->Has(name)) {
ifarr = Local<Array>::Cast(ret->Get(name));
} else {
ifarr = Array::New();
ret->Set(name, ifarr);
}
if (interfaces[i].address.address4.sin_family == AF_INET) {
uv_ip4_name(&interfaces[i].address.address4,ip, sizeof(ip));
family = String::New("IPv4");
} else if (interfaces[i].address.address4.sin_family == AF_INET6) {
uv_ip6_name(&interfaces[i].address.address6, ip, sizeof(ip));
family = String::New("IPv6");
} else {
strncpy(ip, "<unknown sa family>", INET6_ADDRSTRLEN);
family = String::New("<unknown>");
}
o = Object::New();
o->Set(String::New("address"), String::New(ip));
o->Set(String::New("family"), family);
o->Set(String::New("internal"), interfaces[i].is_internal ?
True() : False());
ifarr->Set(ifarr->Length(), o);
}
uv_free_interface_addresses(interfaces, count);
return scope.Close(ret);
} }

10
src/node_vars.h

@ -70,8 +70,7 @@ struct globals {
v8::Persistent<v8::Array> module_load_list; v8::Persistent<v8::Array> module_load_list;
v8::Isolate* node_isolate; v8::Isolate* node_isolate;
volatile bool debugger_running; volatile bool debugger_running;
double prog_start_time;
// stream_wrap.cc // stream_wrap.cc
size_t slab_used; size_t slab_used;
@ -176,13 +175,6 @@ struct globals {
v8::Persistent<v8::String> write_sym; v8::Persistent<v8::String> write_sym;
v8::Persistent<v8::FunctionTemplate> buffer_constructor_template; v8::Persistent<v8::FunctionTemplate> buffer_constructor_template;
// platform*.cc
char* process_title;
struct {
char *str;
size_t len;
} linux_process_title;
// node_signal_watcher.cc // node_signal_watcher.cc
v8::Persistent<v8::String> callback_symbol; v8::Persistent<v8::String> callback_symbol;
v8::Persistent<v8::FunctionTemplate> signal_watcher_constructor_template; v8::Persistent<v8::FunctionTemplate> signal_watcher_constructor_template;

49
src/platform.h

@ -1,49 +0,0 @@
// 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.
#ifndef NODE_PLATFORM_H_
#define NODE_PLATFORM_H_
#include <v8.h>
namespace node {
class Platform {
public:
static char** SetupArgs(int argc, char *argv[]);
static void SetProcessTitle(char *title);
static const char* GetProcessTitle(int *len);
static int GetMemory(size_t *rss);
static int GetCPUInfo(v8::Local<v8::Array> *cpus);
static double GetUptime(bool adjusted = false)
{
return adjusted ? GetUptimeImpl() - prog_start_time : GetUptimeImpl();
}
static v8::Handle<v8::Value> GetInterfaceAddresses();
private:
static double GetUptimeImpl();
static double prog_start_time;
};
} // namespace node
#endif // NODE_PLATFORM_H_

227
src/platform_darwin.cc

@ -1,227 +0,0 @@
// 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 "platform.h"
#include <v8.h>
#include <mach/task.h>
#include <mach/mach.h>
#include <mach/mach_host.h>
#include <limits.h> /* PATH_MAX */
#include <unistd.h> // sysconf
#include <sys/param.h>
#include <sys/sysctl.h>
#include <time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <node_vars.h>
#define process_title NODE_VAR(process_title)
namespace node {
using namespace v8;
double Platform::prog_start_time = Platform::GetUptime();
char** Platform::SetupArgs(int argc, char *argv[]) {
process_title = argc ? strdup(argv[0]) : NULL;
return argv;
}
// Platform::SetProcessTitle implemented in platform_darwin_proctitle.cc
} // namespace node
#include "platform_darwin_proctitle.cc"
namespace node {
const char* Platform::GetProcessTitle(int *len) {
if (process_title) {
*len = strlen(process_title);
return process_title;
}
*len = 0;
return NULL;
}
// Researched by Tim Becker and Michael Knight
// http://blog.kuriositaet.de/?p=257
int Platform::GetMemory(size_t *rss) {
struct task_basic_info t_info;
mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
int r = task_info(mach_task_self(),
TASK_BASIC_INFO,
(task_info_t)&t_info,
&t_info_count);
if (r != KERN_SUCCESS) return -1;
*rss = t_info.resident_size;
return 0;
}
int Platform::GetCPUInfo(Local<Array> *cpus) {
Local<Object> cpuinfo;
Local<Object> cputimes;
unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK),
multiplier = ((uint64_t)1000L / ticks);
char model[512];
uint64_t cpuspeed;
size_t size;
size = sizeof(model);
if (sysctlbyname("hw.model", &model, &size, NULL, 0) < 0) {
return -1;
}
size = sizeof(cpuspeed);
if (sysctlbyname("hw.cpufrequency", &cpuspeed, &size, NULL, 0) < 0) {
return -1;
}
natural_t numcpus;
mach_msg_type_number_t count;
processor_cpu_load_info_data_t *info;
if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numcpus,
reinterpret_cast<processor_info_array_t*>(&info),
&count) != KERN_SUCCESS) {
return -1;
}
*cpus = Array::New(numcpus);
for (unsigned int i = 0; i < numcpus; i++) {
cpuinfo = Object::New();
cputimes = Object::New();
cputimes->Set(String::New("user"),
Number::New((uint64_t)(info[i].cpu_ticks[0]) * multiplier));
cputimes->Set(String::New("nice"),
Number::New((uint64_t)(info[i].cpu_ticks[3]) * multiplier));
cputimes->Set(String::New("sys"),
Number::New((uint64_t)(info[i].cpu_ticks[1]) * multiplier));
cputimes->Set(String::New("idle"),
Number::New((uint64_t)(info[i].cpu_ticks[2]) * multiplier));
cputimes->Set(String::New("irq"), Number::New(0));
cpuinfo->Set(String::New("model"), String::New(model));
cpuinfo->Set(String::New("speed"), Number::New(cpuspeed/1000000));
cpuinfo->Set(String::New("times"), cputimes);
(*cpus)->Set(i, cpuinfo);
}
vm_deallocate(mach_task_self(), (vm_address_t)info, count);
return 0;
}
double Platform::GetUptimeImpl() {
time_t now;
struct timeval info;
size_t size = sizeof(info);
static int which[] = {CTL_KERN, KERN_BOOTTIME};
if (sysctl(which, 2, &info, &size, NULL, 0) < 0) {
return -1;
}
now = time(NULL);
return static_cast<double>(now - info.tv_sec);
}
v8::Handle<v8::Value> Platform::GetInterfaceAddresses() {
HandleScope scope;
struct ::ifaddrs *addrs, *ent;
struct ::sockaddr_in *in4;
struct ::sockaddr_in6 *in6;
char ip[INET6_ADDRSTRLEN];
Local<Object> ret, o;
Local<String> name, ipaddr, family;
Local<Array> ifarr;
if (getifaddrs(&addrs) != 0) {
return ThrowException(ErrnoException(errno, "getifaddrs"));
}
ret = Object::New();
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
bzero(&ip, sizeof (ip));
if (!(ent->ifa_flags & IFF_UP && ent->ifa_flags & IFF_RUNNING)) {
continue;
}
if (ent->ifa_addr == NULL) {
continue;
}
/*
* On Mac OS X getifaddrs returns information related to Mac Addresses for
* various devices, such as firewire, etc. These are not relevant here.
*/
if (ent->ifa_addr->sa_family == AF_LINK)
continue;
name = String::New(ent->ifa_name);
if (ret->Has(name)) {
ifarr = Local<Array>::Cast(ret->Get(name));
} else {
ifarr = Array::New();
ret->Set(name, ifarr);
}
if (ent->ifa_addr->sa_family == AF_INET6) {
in6 = (struct sockaddr_in6 *)ent->ifa_addr;
inet_ntop(AF_INET6, &(in6->sin6_addr), ip, INET6_ADDRSTRLEN);
family = String::New("IPv6");
} else if (ent->ifa_addr->sa_family == AF_INET) {
in4 = (struct sockaddr_in *)ent->ifa_addr;
inet_ntop(AF_INET, &(in4->sin_addr), ip, INET6_ADDRSTRLEN);
family = String::New("IPv4");
} else {
(void) strlcpy(ip, "<unknown sa family>", INET6_ADDRSTRLEN);
family = String::New("<unknown>");
}
o = Object::New();
o->Set(String::New("address"), String::New(ip));
o->Set(String::New("family"), family);
o->Set(String::New("internal"), ent->ifa_flags & IFF_LOOPBACK ?
True() : False());
ifarr->Set(ifarr->Length(), o);
}
freeifaddrs(addrs);
return scope.Close(ret);
}
} // namespace node

146
src/platform_darwin_proctitle.cc

@ -1,146 +0,0 @@
// Copyright 2010, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// This code emanates from the Chromium project:
// http://src.chromium.org/viewvc/chrome/trunk/src/base/mac_util.mm
#include <CoreFoundation/CoreFoundation.h>
#include <Carbon/Carbon.h> // Oh noes! See discussion blow at GetCurrentProcess
#ifndef NDEBUG
#include <err.h>
#endif
namespace node {
void Platform::SetProcessTitle(char *title) {
static int symbol_lookup_status = 0; // 1=ok, 2=unavailable
if (symbol_lookup_status == 2) {
// feature is unavailable
return;
}
if (process_title) free(process_title);
process_title = strdup(title);
// Warning: here be dragons! This is SPI reverse-engineered from WebKit's
// plugin host, and could break at any time (although realistically it's only
// likely to break in a new major release).
// When 10.7 is available, check that this still works, and update this
// comment for 10.8.
// Private CFType used in these LaunchServices calls.
typedef CFTypeRef PrivateLSASN;
typedef PrivateLSASN (*LSGetCurrentApplicationASNType)();
typedef OSStatus (*LSSetApplicationInformationItemType)(int, PrivateLSASN,
CFStringRef,
CFStringRef,
CFDictionaryRef*);
static LSGetCurrentApplicationASNType ls_get_current_application_asn_func =
NULL;
static LSSetApplicationInformationItemType
ls_set_application_information_item_func = NULL;
static CFStringRef ls_display_name_key = NULL;
if (!symbol_lookup_status) {
CFBundleRef launch_services_bundle =
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices"));
if (!launch_services_bundle) {
#ifndef NDEBUG
warnx("failed to look up LaunchServices bundle");
#endif
symbol_lookup_status = 2;
return;
}
ls_get_current_application_asn_func =
reinterpret_cast<LSGetCurrentApplicationASNType>(
CFBundleGetFunctionPointerForName(
launch_services_bundle, CFSTR("_LSGetCurrentApplicationASN")));
if (!ls_get_current_application_asn_func) {
#ifndef NDEBUG
warnx("could not find _LSGetCurrentApplicationASN");
#endif
symbol_lookup_status = 2;
return;
}
ls_set_application_information_item_func =
reinterpret_cast<LSSetApplicationInformationItemType>(
CFBundleGetFunctionPointerForName(
launch_services_bundle,
CFSTR("_LSSetApplicationInformationItem")));
if (!ls_set_application_information_item_func) {
#ifndef NDEBUG
warnx("Could not find _LSSetApplicationInformationItem");
#endif
symbol_lookup_status = 2;
return;
}
const CFStringRef* key_pointer = reinterpret_cast<const CFStringRef*>(
CFBundleGetDataPointerForName(launch_services_bundle,
CFSTR("_kLSDisplayNameKey")));
ls_display_name_key = key_pointer ? *key_pointer : NULL;
if (!ls_display_name_key) {
#ifndef NDEBUG
warnx("Could not find _kLSDisplayNameKey");
#endif
symbol_lookup_status = 2;
return;
}
// Internally, this call relies on the Mach ports that are started up by the
// Carbon Process Manager. In debug builds this usually happens due to how
// the logging layers are started up; but in release, it isn't started in as
// much of a defined order. So if the symbols had to be loaded, go ahead
// and force a call to make sure the manager has been initialized and hence
// the ports are opened.
ProcessSerialNumber psn;
GetCurrentProcess(&psn);
symbol_lookup_status = 1; // 1=ok
}
PrivateLSASN asn = ls_get_current_application_asn_func();
// Constant used by WebKit; what exactly it means is unknown.
const int magic_session_constant = -2;
CFStringRef process_name =
CFStringCreateWithCString(NULL, title, kCFStringEncodingUTF8);
OSErr err =
ls_set_application_information_item_func(magic_session_constant, asn,
ls_display_name_key,
process_name,
NULL /* optional out param */);
#ifndef NDEBUG
if (err) {
warnx("Call LSSetApplicationInformationItem failed");
}
#endif
}
} // namespace node

178
src/platform_freebsd.cc

@ -1,178 +0,0 @@
// 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 "platform.h"
#include <v8.h>
#include <stdlib.h>
#include <kvm.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/user.h>
#include <sys/dkstat.h>
#include <vm/vm_param.h>
#include <string.h>
#include <paths.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <node_vars.h>
#define process_title NODE_VAR(process_title)
namespace node {
using namespace v8;
double Platform::prog_start_time = Platform::GetUptime();
char** Platform::SetupArgs(int argc, char *argv[]) {
process_title = argc ? strdup(argv[0]) : NULL;
return argv;
}
void Platform::SetProcessTitle(char *title) {
if (process_title) free(process_title);
process_title = strdup(title);
setproctitle(title);
}
const char* Platform::GetProcessTitle(int *len) {
if (process_title) {
*len = strlen(process_title);
return process_title;
}
*len = 0;
return NULL;
}
int Platform::GetMemory(size_t *rss) {
kvm_t *kd = NULL;
struct kinfo_proc *kinfo = NULL;
pid_t pid;
int nprocs;
size_t page_size = getpagesize();
pid = getpid();
kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open");
if (kd == NULL) goto error;
kinfo = kvm_getprocs(kd, KERN_PROC_PID, pid, &nprocs);
if (kinfo == NULL) goto error;
*rss = kinfo->ki_rssize * page_size;
kvm_close(kd);
return 0;
error:
if (kd) kvm_close(kd);
return -1;
}
int Platform::GetCPUInfo(Local<Array> *cpus) {
Local<Object> cpuinfo;
Local<Object> cputimes;
unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK),
multiplier = ((uint64_t)1000L / ticks), cpuspeed, maxcpus,
cur = 0;
char model[512];
int numcpus;
size_t size;
size = sizeof(model);
if (sysctlbyname("hw.model", &model, &size, NULL, 0) < 0) {
return -1;
}
size = sizeof(numcpus);
if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0) < 0) {
return -1;
}
*cpus = Array::New(numcpus);
size = sizeof(cpuspeed);
if (sysctlbyname("hw.clockrate", &cpuspeed, &size, NULL, 0) < 0) {
return -1;
}
// kern.cp_times on FreeBSD i386 gives an array up to maxcpus instead of ncpu
size = sizeof(maxcpus);
if (sysctlbyname("kern.smp.maxcpus", &maxcpus, &size, NULL, 0) < 0) {
return -1;
}
size = maxcpus * CPUSTATES * sizeof(long);
long cp_times[size];
if (sysctlbyname("kern.cp_times", &cp_times, &size, NULL, 0) < 0) {
return -1;
}
for (int i = 0; i < numcpus; i++) {
cpuinfo = Object::New();
cputimes = Object::New();
cputimes->Set(String::New("user"),
Number::New((uint64_t)(cp_times[CP_USER+cur]) * multiplier));
cputimes->Set(String::New("nice"),
Number::New((uint64_t)(cp_times[CP_NICE+cur]) * multiplier));
cputimes->Set(String::New("sys"),
Number::New((uint64_t)(cp_times[CP_SYS+cur]) * multiplier));
cputimes->Set(String::New("idle"),
Number::New((uint64_t)(cp_times[CP_IDLE+cur]) * multiplier));
cputimes->Set(String::New("irq"),
Number::New((uint64_t)(cp_times[CP_INTR+cur]) * multiplier));
cpuinfo->Set(String::New("model"), String::New(model));
cpuinfo->Set(String::New("speed"), Number::New(cpuspeed));
cpuinfo->Set(String::New("times"), cputimes);
(*cpus)->Set(i, cpuinfo);
cur+=CPUSTATES;
}
return 0;
}
double Platform::GetUptimeImpl() {
time_t now;
struct timeval info;
size_t size = sizeof(info);
static int which[] = {CTL_KERN, KERN_BOOTTIME};
if (sysctl(which, 2, &info, &size, NULL, 0) < 0) {
return -1;
}
now = time(NULL);
return static_cast<double>(now - info.tv_sec);
}
Handle<Value> Platform::GetInterfaceAddresses() {
HandleScope scope;
return scope.Close(Object::New());
}
} // namespace node

394
src/platform_linux.cc

@ -1,394 +0,0 @@
// 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 "platform.h"
#include <v8.h>
#include <sys/param.h> // for MAXPATHLEN
#include <unistd.h> // getpagesize, sysconf
#include <stdio.h> // sscanf, snprintf
/* SetProcessTitle */
#include <sys/prctl.h>
#include <linux/prctl.h>
#include <stdlib.h> // free
#include <string.h> // strdup
/* GetInterfaceAddresses */
#include <arpa/inet.h>
#include <sys/types.h>
#include <ifaddrs.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <time.h>
#ifndef CLOCK_MONOTONIC
# include <sys/sysinfo.h>
#endif
#include <node_vars.h>
#define linux_process_title NODE_VAR(linux_process_title)
#define getbuf NODE_VAR(getbuf)
extern char **environ;
namespace node {
using namespace v8;
double Platform::prog_start_time = Platform::GetUptime();
char** Platform::SetupArgs(int argc, char *argv[]) {
char **new_argv;
char **new_env;
size_t size;
int envc;
char *s;
int i;
for (envc = 0; environ[envc]; envc++);
s = envc ? environ[envc - 1] : argv[argc - 1];
linux_process_title.str = argv[0];
linux_process_title.len = s + strlen(s) + 1 - argv[0];
size = linux_process_title.len;
size += (argc + 1) * sizeof(char **);
size += (envc + 1) * sizeof(char **);
if ((s = (char *) malloc(size)) == NULL) {
linux_process_title.str = NULL;
linux_process_title.len = 0;
return argv;
}
new_argv = (char **) s;
new_env = new_argv + argc + 1;
s = (char *) (new_env + envc + 1);
memcpy(s, linux_process_title.str, linux_process_title.len);
for (i = 0; i < argc; i++)
new_argv[i] = s + (argv[i] - argv[0]);
new_argv[argc] = NULL;
s += environ[0] - argv[0];
for (i = 0; i < envc; i++)
new_env[i] = s + (environ[i] - environ[0]);
new_env[envc] = NULL;
environ = new_env;
return new_argv;
}
void Platform::SetProcessTitle(char *title) {
/* No need to terminate, last char is always '\0'. */
if (linux_process_title.len)
strncpy(linux_process_title.str, title, linux_process_title.len - 1);
}
const char* Platform::GetProcessTitle(int *len) {
if (linux_process_title.str) {
*len = strlen(linux_process_title.str);
return linux_process_title.str;
}
else {
*len = 0;
return NULL;
}
}
int Platform::GetMemory(size_t *rss) {
FILE *f = fopen("/proc/self/stat", "r");
if (!f) return -1;
int itmp;
char ctmp;
size_t page_size = getpagesize();
char *cbuf;
bool foundExeEnd;
/* PID */
if (fscanf(f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* Exec file */
cbuf = getbuf;
foundExeEnd = false;
if (fscanf (f, "%c", cbuf++) == 0) goto error; // (
while (1) {
if (fscanf(f, "%c", cbuf) == 0) goto error;
if (*cbuf == ')') {
foundExeEnd = true;
} else if (foundExeEnd && *cbuf == ' ') {
*cbuf = 0;
break;
}
cbuf++;
}
/* State */
if (fscanf (f, "%c ", &ctmp) == 0) goto error; /* coverity[secure_coding] */
/* Parent process */
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* Process group */
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* Session id */
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* TTY */
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* TTY owner process group */
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* Flags */
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* Minor faults (no memory page) */
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* Minor faults, children */
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* Major faults (memory page faults) */
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* Major faults, children */
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* utime */
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* stime */
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* utime, children */
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* stime, children */
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* jiffies remaining in current time slice */
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* 'nice' value */
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* jiffies until next timeout */
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* jiffies until next SIGALRM */
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* start time (jiffies since system boot) */
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* Virtual memory size */
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* Resident set size */
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
*rss = (size_t) itmp * page_size;
/* rlim */
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* Start of text */
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* End of text */
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
/* Start of stack */
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
fclose (f);
return 0;
error:
fclose (f);
return -1;
}
int Platform::GetCPUInfo(Local<Array> *cpus) {
HandleScope scope;
Local<Object> cpuinfo;
Local<Object> cputimes;
unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK),
multiplier = ((uint64_t)1000L / ticks), cpuspeed;
int numcpus = 0, i = 0;
unsigned long long ticks_user, ticks_sys, ticks_idle, ticks_nice, ticks_intr;
char line[512], speedPath[256], model[512];
FILE *fpStat = fopen("/proc/stat", "r");
FILE *fpModel = fopen("/proc/cpuinfo", "r");
FILE *fpSpeed;
if (fpModel) {
while (fgets(line, 511, fpModel) != NULL) {
if (strncmp(line, "model name", 10) == 0) {
numcpus++;
if (numcpus == 1) {
char *p = strchr(line, ':') + 2;
strcpy(model, p);
model[strlen(model)-1] = 0;
}
} else if (strncmp(line, "cpu MHz", 7) == 0) {
if (numcpus == 1) {
sscanf(line, "%*s %*s : %u", &cpuspeed);
}
}
}
fclose(fpModel);
}
*cpus = Array::New(numcpus);
if (fpStat) {
while (fgets(line, 511, fpStat) != NULL) {
if (strncmp(line, "cpu ", 4) == 0) {
continue;
} else if (strncmp(line, "cpu", 3) != 0) {
break;
}
sscanf(line, "%*s %llu %llu %llu %llu %*llu %llu",
&ticks_user, &ticks_nice, &ticks_sys, &ticks_idle, &ticks_intr);
snprintf(speedPath, sizeof(speedPath),
"/sys/devices/system/cpu/cpu%u/cpufreq/cpuinfo_max_freq", i);
fpSpeed = fopen(speedPath, "r");
if (fpSpeed) {
if (fgets(line, 511, fpSpeed) != NULL) {
sscanf(line, "%u", &cpuspeed);
cpuspeed /= 1000;
}
fclose(fpSpeed);
}
cpuinfo = Object::New();
cputimes = Object::New();
cputimes->Set(String::New("user"), Number::New(ticks_user * multiplier));
cputimes->Set(String::New("nice"), Number::New(ticks_nice * multiplier));
cputimes->Set(String::New("sys"), Number::New(ticks_sys * multiplier));
cputimes->Set(String::New("idle"), Number::New(ticks_idle * multiplier));
cputimes->Set(String::New("irq"), Number::New(ticks_intr * multiplier));
cpuinfo->Set(String::New("model"), String::New(model));
cpuinfo->Set(String::New("speed"), Number::New(cpuspeed));
cpuinfo->Set(String::New("times"), cputimes);
(*cpus)->Set(i++, cpuinfo);
}
fclose(fpStat);
}
return 0;
}
double Platform::GetUptimeImpl() {
#ifdef CLOCK_MONOTONIC
struct timespec now;
if (0 == clock_gettime(CLOCK_MONOTONIC, &now)) {
double uptime = now.tv_sec;
uptime += (double)now.tv_nsec / 1000000000.0;
return uptime;
}
return -1;
#else
struct sysinfo info;
if (sysinfo(&info) < 0) {
return -1;
}
return static_cast<double>(info.uptime);
#endif
}
bool IsInternal(struct ifaddrs* addr) {
return addr->ifa_flags & IFF_UP &&
addr->ifa_flags & IFF_RUNNING &&
addr->ifa_flags & IFF_LOOPBACK;
}
Handle<Value> Platform::GetInterfaceAddresses() {
HandleScope scope;
struct ::ifaddrs *addrs, *ent;
struct ::sockaddr_in *in4;
struct ::sockaddr_in6 *in6;
char ip[INET6_ADDRSTRLEN];
Local<Object> ret, o;
Local<String> name, ipaddr, family;
Local<Array> ifarr;
if (getifaddrs(&addrs) != 0) {
return ThrowException(ErrnoException(errno, "getifaddrs"));
}
ret = Object::New();
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
bzero(&ip, sizeof (ip));
if (!(ent->ifa_flags & IFF_UP && ent->ifa_flags & IFF_RUNNING)) {
continue;
}
if (ent->ifa_addr == NULL) {
continue;
}
/*
* On Linux getifaddrs returns information related to the raw underlying
* devices. We're not interested in this information.
*/
if (ent->ifa_addr->sa_family == PF_PACKET)
continue;
name = String::New(ent->ifa_name);
if (ret->Has(name)) {
ifarr = Local<Array>::Cast(ret->Get(name));
} else {
ifarr = Array::New();
ret->Set(name, ifarr);
}
if (ent->ifa_addr->sa_family == AF_INET6) {
in6 = (struct sockaddr_in6 *)ent->ifa_addr;
inet_ntop(AF_INET6, &(in6->sin6_addr), ip, INET6_ADDRSTRLEN);
family = String::New("IPv6");
} else if (ent->ifa_addr->sa_family == AF_INET) {
in4 = (struct sockaddr_in *)ent->ifa_addr;
inet_ntop(AF_INET, &(in4->sin_addr), ip, INET6_ADDRSTRLEN);
family = String::New("IPv4");
} else {
(void) strncpy(ip, "<unknown sa family>", INET6_ADDRSTRLEN);
family = String::New("<unknown>");
}
o = Object::New();
o->Set(String::New("address"), String::New(ip));
o->Set(String::New("family"), family);
o->Set(String::New("internal"), ent->ifa_flags & IFF_LOOPBACK ?
True() : False());
ifarr->Set(ifarr->Length(), o);
}
freeifaddrs(addrs);
return scope.Close(ret);
}
} // namespace node

52
src/platform_none.cc

@ -1,52 +0,0 @@
// 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 "platform.h"
namespace node {
char** OS::SetupArgs(int argc, char *argv[]) {
return argv;
}
void OS::SetProcessTitle(char *title) {
;
}
const char* OS::GetProcessTitle(int *len) {
*len = 0;
return NULL;
}
int OS::GetMemory(size_t *rss) {
// Not implemented
*rss = 0;
return 0;
}
} // namespace node

178
src/platform_openbsd.cc

@ -1,178 +0,0 @@
// 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 "platform.h"
#include <v8.h>
#include <stdlib.h>
#include <kvm.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/user.h>
#include <sys/dkstat.h>
#include <uvm/uvm_param.h>
#include <string.h>
#include <paths.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <stdio.h>
#include <node_vars.h>
#define process_title NODE_VAR(process_title)
namespace node {
using namespace v8;
double Platform::prog_start_time = Platform::GetUptime();
char** Platform::SetupArgs(int argc, char *argv[]) {
process_title = argc ? strdup(argv[0]) : NULL;
return argv;
}
void Platform::SetProcessTitle(char *title) {
if (process_title) free(process_title);
process_title = strdup(title);
setproctitle(title);
}
const char* Platform::GetProcessTitle(int *len) {
if (process_title) {
*len = strlen(process_title);
return process_title;
}
*len = 0;
return NULL;
}
int Platform::GetMemory(size_t *rss) {
kvm_t *kd = NULL;
struct kinfo_proc2 *kinfo = NULL;
pid_t pid;
int nprocs, max_size = sizeof(struct kinfo_proc2);
size_t page_size = getpagesize();
pid = getpid();
kd = kvm_open(NULL, _PATH_MEM, NULL, O_RDONLY, "kvm_open");
if (kd == NULL) goto error;
kinfo = kvm_getproc2(kd, KERN_PROC_PID, pid, max_size, &nprocs);
if (kinfo == NULL) goto error;
*rss = kinfo->p_vm_rssize * page_size;
kvm_close(kd);
return 0;
error:
if (kd) kvm_close(kd);
return -1;
}
int Platform::GetCPUInfo(Local<Array> *cpus) {
Local<Object> cpuinfo;
Local<Object> cputimes;
unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK),
multiplier = ((uint64_t)1000L / ticks), cpuspeed;
uint64_t info[CPUSTATES];
char model[512];
int numcpus = 1;
static int which[] = {CTL_HW, HW_MODEL, NULL};
size_t size;
size = sizeof(model);
if (sysctl(which, 2, &model, &size, NULL, 0) < 0) {
return -1;
}
which[1] = HW_NCPU;
size = sizeof(numcpus);
if (sysctl(which, 2, &numcpus, &size, NULL, 0) < 0) {
return -1;
}
*cpus = Array::New(numcpus);
which[1] = HW_CPUSPEED;
size = sizeof(cpuspeed);
if (sysctl(which, 2, &cpuspeed, &size, NULL, 0) < 0) {
return -1;
}
size = sizeof(info);
which[0] = CTL_KERN;
which[1] = KERN_CPTIME2;
for (int i = 0; i < numcpus; i++) {
which[2] = i;
size = sizeof(info);
if (sysctl(which, 3, &info, &size, NULL, 0) < 0) {
return -1;
}
cpuinfo = Object::New();
cputimes = Object::New();
cputimes->Set(String::New("user"),
Number::New((uint64_t)(info[CP_USER]) * multiplier));
cputimes->Set(String::New("nice"),
Number::New((uint64_t)(info[CP_NICE]) * multiplier));
cputimes->Set(String::New("sys"),
Number::New((uint64_t)(info[CP_SYS]) * multiplier));
cputimes->Set(String::New("idle"),
Number::New((uint64_t)(info[CP_IDLE]) * multiplier));
cputimes->Set(String::New("irq"),
Number::New((uint64_t)(info[CP_INTR]) * multiplier));
cpuinfo->Set(String::New("model"), String::New(model));
cpuinfo->Set(String::New("speed"), Number::New(cpuspeed));
cpuinfo->Set(String::New("times"), cputimes);
(*cpus)->Set(i, cpuinfo);
}
return 0;
}
double Platform::GetUptimeImpl() {
time_t now;
struct timeval info;
size_t size = sizeof(info);
static int which[] = {CTL_KERN, KERN_BOOTTIME};
if (sysctl(which, 2, &info, &size, NULL, 0) < 0) {
return -1;
}
now = time(NULL);
return static_cast<double>(now - info.tv_sec);
}
Handle<Value> Platform::GetInterfaceAddresses() {
HandleScope scope;
return scope.Close(Object::New());
}
} // namespace node

305
src/platform_sunos.cc

@ -1,305 +0,0 @@
// 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 "platform.h"
#include <unistd.h> /* getpagesize() */
#include <stdlib.h> /* getexecname() */
#include <strings.h> /* strncpy() */
#include <kstat.h>
#include <errno.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/loadavg.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifdef SUNOS_HAVE_IFADDRS
# include <ifaddrs.h>
#endif
#if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64)
#define PROCFS_FILE_OFFSET_BITS_HACK 1
#undef _FILE_OFFSET_BITS
#else
#define PROCFS_FILE_OFFSET_BITS_HACK 0
#endif
#include <procfs.h>
#if (PROCFS_FILE_OFFSET_BITS_HACK - 0 == 1)
#define _FILE_OFFSET_BITS 64
#endif
namespace node {
using namespace v8;
double Platform::prog_start_time = Platform::GetUptime();
char** Platform::SetupArgs(int argc, char *argv[]) {
return argv;
}
void Platform::SetProcessTitle(char *title) {
;
}
const char* Platform::GetProcessTitle(int *len) {
*len = 0;
return NULL;
}
int Platform::GetMemory(size_t *rss) {
pid_t pid = getpid();
char pidpath[1024];
sprintf(pidpath, "/proc/%d/psinfo", pid);
psinfo_t psinfo;
FILE *f = fopen(pidpath, "r");
if (!f) return -1;
if (fread(&psinfo, sizeof(psinfo_t), 1, f) != 1) {
fclose (f);
return -1;
}
/* XXX correct? */
*rss = (size_t) psinfo.pr_rssize * 1024;
fclose (f);
return 0;
}
static Handle<Value> data_named(kstat_named_t *knp) {
Handle<Value> val;
switch (knp->data_type) {
case KSTAT_DATA_CHAR:
val = Number::New(knp->value.c[0]);
break;
case KSTAT_DATA_INT32:
val = Number::New(knp->value.i32);
break;
case KSTAT_DATA_UINT32:
val = Number::New(knp->value.ui32);
break;
case KSTAT_DATA_INT64:
val = Number::New(knp->value.i64);
break;
case KSTAT_DATA_UINT64:
val = Number::New(knp->value.ui64);
break;
case KSTAT_DATA_STRING:
val = String::New(KSTAT_NAMED_STR_PTR(knp));
break;
default:
val = String::New("unrecognized data type");
}
return (val);
}
int Platform::GetCPUInfo(Local<Array> *cpus) {
HandleScope scope;
Local<Object> cpuinfo;
Local<Object> cputimes;
int lookup_instance;
kstat_ctl_t *kc;
kstat_t *ksp;
kstat_named_t *knp;
if ((kc = kstat_open()) == NULL)
return -1;
*cpus = Array::New();
lookup_instance = 0;
while (ksp = kstat_lookup(kc, (char *)"cpu_info", lookup_instance, NULL)){
cpuinfo = Object::New();
if (kstat_read(kc, ksp, NULL) == -1) {
/*
* It is deeply annoying, but some kstats can return errors
* under otherwise routine conditions. (ACPI is one
* offender; there are surely others.) To prevent these
* fouled kstats from completely ruining our day, we assign
* an "error" member to the return value that consists of
* the strerror().
*/
cpuinfo->Set(String::New("error"), String::New(strerror(errno)));
(*cpus)->Set(lookup_instance, cpuinfo);
} else {
knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"clock_MHz");
cpuinfo->Set(String::New("speed"), data_named(knp));
knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"brand");
cpuinfo->Set(String::New("model"), data_named(knp));
(*cpus)->Set(lookup_instance, cpuinfo);
}
lookup_instance++;
}
lookup_instance = 0;
while (ksp = kstat_lookup(kc, (char *)"cpu", lookup_instance, (char *)"sys")){
cpuinfo = (*cpus)->Get(lookup_instance)->ToObject();
cputimes = Object::New();
if (kstat_read(kc, ksp, NULL) == -1) {
cputimes->Set(String::New("error"), String::New(strerror(errno)));
cpuinfo->Set(String::New("times"), cpuinfo);
} else {
knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"cpu_ticks_kernel");
cputimes->Set(String::New("system"), data_named(knp));
knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"cpu_ticks_user");
cputimes->Set(String::New("user"), data_named(knp));
knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"cpu_ticks_idle");
cputimes->Set(String::New("idle"), data_named(knp));
knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"intr");
cputimes->Set(String::New("irq"), data_named(knp));
cpuinfo->Set(String::New("times"), cputimes);
}
lookup_instance++;
}
kstat_close(kc);
return 0;
}
double Platform::GetUptimeImpl() {
kstat_ctl_t *kc;
kstat_t *ksp;
kstat_named_t *knp;
long hz = sysconf(_SC_CLK_TCK);
double clk_intr;
if ((kc = kstat_open()) == NULL)
return -1;
ksp = kstat_lookup(kc, (char *)"unix", 0, (char *)"system_misc");
if (kstat_read(kc, ksp, NULL) == -1) {
clk_intr = -1;
} else {
knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"clk_intr");
clk_intr = knp->value.ul / hz;
}
kstat_close(kc);
return clk_intr;
}
Handle<Value> Platform::GetInterfaceAddresses() {
HandleScope scope;
#ifndef SUNOS_HAVE_IFADDRS
return ThrowException(Exception::Error(String::New(
"This version of sunos doesn't support getifaddrs")));
#else
struct ::ifaddrs *addrs, *ent;
struct ::sockaddr_in *in4;
struct ::sockaddr_in6 *in6;
char ip[INET6_ADDRSTRLEN];
Local<Object> ret, o;
Local<String> name, ipaddr, family;
Local<Array> ifarr;
if (getifaddrs(&addrs) != 0) {
return ThrowException(ErrnoException(errno, "getifaddrs"));
}
ret = Object::New();
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
bzero(&ip, sizeof (ip));
if (!(ent->ifa_flags & IFF_UP && ent->ifa_flags & IFF_RUNNING)) {
continue;
}
if (ent->ifa_addr == NULL) {
continue;
}
name = String::New(ent->ifa_name);
if (ret->Has(name)) {
ifarr = Local<Array>::Cast(ret->Get(name));
} else {
ifarr = Array::New();
ret->Set(name, ifarr);
}
if (ent->ifa_addr->sa_family == AF_INET6) {
in6 = (struct sockaddr_in6 *)ent->ifa_addr;
inet_ntop(AF_INET6, &(in6->sin6_addr), ip, INET6_ADDRSTRLEN);
family = String::New("IPv6");
} else if (ent->ifa_addr->sa_family == AF_INET) {
in4 = (struct sockaddr_in *)ent->ifa_addr;
inet_ntop(AF_INET, &(in4->sin_addr), ip, INET6_ADDRSTRLEN);
family = String::New("IPv4");
} else {
(void) strlcpy(ip, "<unknown sa family>", INET6_ADDRSTRLEN);
family = String::New("<unknown>");
}
o = Object::New();
o->Set(String::New("address"), String::New(ip));
o->Set(String::New("family"), family);
o->Set(String::New("internal"), ent->ifa_flags & IFF_PRIVATE || ent->ifa_flags &
IFF_LOOPBACK ? True() : False());
ifarr->Set(ifarr->Length(), o);
}
freeifaddrs(addrs);
return scope.Close(ret);
#endif // SUNOS_HAVE_IFADDRS
}
} // namespace node

292
src/platform_win32.cc

@ -1,292 +0,0 @@
// 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 "platform.h"
#include <v8.h>
#include <errno.h>
#include <stdlib.h>
#if defined(__MINGW32__)
#include <sys/param.h> // for MAXPATHLEN
#include <unistd.h> // getpagesize
#endif
#include <platform_win32.h>
#include <psapi.h>
#include <node_vars.h>
#define process_title NODE_VAR(process_title)
namespace node {
using namespace v8;
double Platform::prog_start_time = Platform::GetUptime();
// Does the about the same as strerror(),
// but supports all windows errror messages
const char *winapi_strerror(const int errorno) {
char *errmsg = NULL;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, NULL);
if (errmsg) {
// Remove trailing newlines
for (int i = strlen(errmsg) - 1;
i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) {
errmsg[i] = '\0';
}
return errmsg;
} else {
// FormatMessage failed
return "Unknown error";
}
}
// Does the about the same as perror(), but for windows api functions
void winapi_perror(const char* prefix = NULL) {
DWORD errorno = GetLastError();
const char *errmsg = NULL;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, NULL);
if (!errmsg) {
errmsg = "Unknown error\n";
}
// FormatMessage messages include a newline character
if (prefix) {
fprintf(stderr, "%s: %s", prefix, errmsg);
} else {
fputs(errmsg, stderr);
}
}
char** Platform::SetupArgs(int argc, char *argv[]) {
return argv;
}
// Max title length; the only thing MSDN tells us about the maximum length
// of the console title is that it is smaller than 64K. However in practice
// it is much smaller, and there is no way to figure out what the exact length
// of the title is or can be, at least not on XP. To make it even more
// annoying, GetConsoleTitle failes when the buffer to be read into is bigger
// than the actual maximum length. So we make a conservative guess here;
// just don't put the novel you're writing in the title, unless the plot
// survives truncation.
#define MAX_TITLE_LENGTH 8192
void Platform::SetProcessTitle(char *title) {
// We need to convert _title_ to UTF-16 first, because that's what windows uses internally.
// It would be more efficient to use the UTF-16 value that we can obtain from v8,
// but it's not accessible from here.
int length;
WCHAR *title_w;
// Find out how big the buffer for the wide-char title must be
length = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0);
if (!length) {
winapi_perror("MultiByteToWideChar");
return;
}
// Convert to wide-char string
title_w = new WCHAR[length];
length = MultiByteToWideChar(CP_UTF8, 0, title, -1, title_w, length);
if (!length) {
winapi_perror("MultiByteToWideChar");
delete title_w;
return;
};
// If the title must be truncated insert a \0 terminator there
if (length > MAX_TITLE_LENGTH) {
title_w[MAX_TITLE_LENGTH - 1] = *L"\0";
}
if (!SetConsoleTitleW(title_w)) {
winapi_perror("SetConsoleTitleW");
}
free(process_title);
process_title = strdup(title);
delete title_w;
}
static inline char* _getProcessTitle() {
WCHAR title_w[MAX_TITLE_LENGTH];
char *title;
int result, length;
result = GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR));
if (result == 0) {
winapi_perror("GetConsoleTitleW");
return NULL;
}
// Find out what the size of the buffer is that we need
length = WideCharToMultiByte(CP_UTF8, 0, title_w, -1, NULL, 0, NULL, NULL);
if (!length) {
winapi_perror("WideCharToMultiByte");
return NULL;
}
title = (char *) malloc(length);
if (!title) {
perror("malloc");
return NULL;
}
// Do utf16 -> utf8 conversion here
if (!WideCharToMultiByte(CP_UTF8, 0, title_w, -1, title, length, NULL, NULL)) {
winapi_perror("WideCharToMultiByte");
free(title);
return NULL;
}
return title;
}
const char* Platform::GetProcessTitle(int *len) {
// If the process_title was never read before nor explicitly set,
// we must query it with getConsoleTitleW
if (!process_title) {
process_title = _getProcessTitle();
}
if (process_title) {
*len = strlen(process_title);
return process_title;
} else {
*len = 0;
return NULL;
}
}
int Platform::GetMemory(size_t *rss) {
HANDLE current_process = GetCurrentProcess();
PROCESS_MEMORY_COUNTERS pmc;
if ( !GetProcessMemoryInfo( current_process, &pmc, sizeof(pmc)) )
{
winapi_perror("GetProcessMemoryInfo");
}
*rss = pmc.WorkingSetSize;
return 0;
}
int Platform::GetCPUInfo(Local<Array> *cpus) {
HandleScope scope;
*cpus = Array::New();
for (int i = 0; i < 32; i++) {
char key[128] = "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\";
char processor_number[32];
itoa(i, processor_number, 10);
strncat(key, processor_number, 2);
HKEY processor_key = NULL;
DWORD cpu_speed = 0;
DWORD cpu_speed_length = sizeof(cpu_speed);
char cpu_brand[256];
DWORD cpu_brand_length = sizeof(cpu_brand);
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_QUERY_VALUE,
&processor_key) != ERROR_SUCCESS) {
if (i == 0) {
winapi_perror("RegOpenKeyEx");
return -1;
}
continue;
}
if (RegQueryValueEx(processor_key, "~MHz", NULL, NULL,
(LPBYTE)&cpu_speed, &cpu_speed_length)
!= ERROR_SUCCESS) {
winapi_perror("RegQueryValueEx");
return -1;
}
if (RegQueryValueEx(processor_key, "ProcessorNameString", NULL, NULL,
(LPBYTE)&cpu_brand, &cpu_brand_length)
!= ERROR_SUCCESS) {
winapi_perror("RegQueryValueEx");
return -1;
}
RegCloseKey(processor_key);
Local<Object> times_info = Object::New(); // FIXME - find times on windows
times_info->Set(String::New("user"), Integer::New(0));
times_info->Set(String::New("nice"), Integer::New(0));
times_info->Set(String::New("sys"), Integer::New(0));
times_info->Set(String::New("idle"), Integer::New(0));
times_info->Set(String::New("irq"), Integer::New(0));
Local<Object> cpu_info = Object::New();
cpu_info->Set(String::New("model"), String::New(cpu_brand));
cpu_info->Set(String::New("speed"), Integer::New(cpu_speed));
cpu_info->Set(String::New("times"), times_info);
(*cpus)->Set(i,cpu_info);
}
return 0;
}
double Platform::GetUptimeImpl() {
return (double)GetTickCount()/1000.0;
}
Handle<Value> Platform::GetInterfaceAddresses() {
HandleScope scope;
return scope.Close(Object::New());
}
} // namespace node

79
src/platform_win32.h

@ -1,79 +0,0 @@
// 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.
#ifndef NODE_PLATFORM_WIN32_H_
#define NODE_PLATFORM_WIN32_H_
// Require at least Windows XP SP1
// (GetProcessId requires it)
#ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0501
#endif
#ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN // implies NOCRYPT and NOGDI.
#endif
#ifndef NOMINMAX
# define NOMINMAX
#endif
#ifndef NOKERNEL
# define NOKERNEL
#endif
#ifndef NOUSER
# define NOUSER
#endif
#ifndef NOSERVICE
# define NOSERVICE
#endif
#ifndef NOSOUND
# define NOSOUND
#endif
#ifndef NOMCX
# define NOMCX
#endif
#include <windows.h>
#include <winsock2.h>
#if defined(_MSC_VER)
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
#endif
namespace node {
#define NO_IMPL_MSG(...) \
fprintf(stderr, "Not implemented: %s\n", #__VA_ARGS__);
const char *winapi_strerror(const int errorno);
void winapi_perror(const char* prefix);
}
#endif // NODE_PLATFORM_WIN32_H_

6
test/simple/test-os.js

@ -72,4 +72,10 @@ switch (platform) {
var expected = [{ address: '127.0.0.1', family: 'IPv4', internal: true }]; var expected = [{ address: '127.0.0.1', family: 'IPv4', internal: true }];
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
break; break;
case 'win32':
var filter = function(e) { return e.address == '127.0.0.1'; };
var actual = interfaces['Loopback Pseudo-Interface 1'].filter(filter);
var expected = [{ address: '127.0.0.1', family: 'IPv4', internal: true }];
assert.deepEqual(actual, expected);
break;
} }

Loading…
Cancel
Save