GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/node-core-coverage/node-core-coverage/workdir/node/src/node_os.cc Lines: 160 175 91.4 %
Date: 2016-07-18 Branches: 28 42 66.7 %

Line Exec Source
1
#include "node.h"
2
#include "v8.h"
3
#include "env.h"
4
#include "env-inl.h"
5
#include "string_bytes.h"
6
7
#include <errno.h>
8
#include <string.h>
9
10
#ifdef __MINGW32__
11
# include <io.h>
12
#endif  // __MINGW32__
13
14
#ifdef __POSIX__
15
# include <limits.h>        // PATH_MAX on Solaris.
16
# include <netdb.h>         // MAXHOSTNAMELEN on Solaris.
17
# include <unistd.h>        // gethostname, sysconf
18
# include <sys/param.h>     // MAXHOSTNAMELEN on Linux and the BSDs.
19
# include <sys/utsname.h>
20
#endif  // __MINGW32__
21
22
// Add Windows fallback.
23
#ifndef MAXHOSTNAMELEN
24
# define MAXHOSTNAMELEN 256
25
#endif  // MAXHOSTNAMELEN
26
27
namespace node {
28
namespace os {
29
30
using v8::Array;
31
using v8::Boolean;
32
using v8::Context;
33
using v8::FunctionCallbackInfo;
34
using v8::Integer;
35
using v8::Local;
36
using v8::Null;
37
using v8::Number;
38
using v8::Object;
39
using v8::String;
40
using v8::Value;
41
42
43
1
static void GetHostname(const FunctionCallbackInfo<Value>& args) {
44
1
  Environment* env = Environment::GetCurrent(args);
45
  char buf[MAXHOSTNAMELEN + 1];
46
47
1
  if (gethostname(buf, sizeof(buf))) {
48
#ifdef __POSIX__
49
    int errorno = errno;
50
#else  // __MINGW32__
51
    int errorno = WSAGetLastError();
52
#endif  // __POSIX__
53
    return env->ThrowErrnoException(errorno, "gethostname");
54
  }
55
1
  buf[sizeof(buf) - 1] = '\0';
56
57
3
  args.GetReturnValue().Set(OneByteString(env->isolate(), buf));
58
}
59
60
61
2
static void GetOSType(const FunctionCallbackInfo<Value>& args) {
62
2
  Environment* env = Environment::GetCurrent(args);
63
  const char* rval;
64
65
#ifdef __POSIX__
66
  struct utsname info;
67
2
  if (uname(&info) < 0) {
68
    return env->ThrowErrnoException(errno, "uname");
69
  }
70
2
  rval = info.sysname;
71
#else  // __MINGW32__
72
  rval ="Windows_NT";
73
#endif  // __POSIX__
74
75
6
  args.GetReturnValue().Set(OneByteString(env->isolate(), rval));
76
}
77
78
79
1
static void GetOSRelease(const FunctionCallbackInfo<Value>& args) {
80
1
  Environment* env = Environment::GetCurrent(args);
81
  const char* rval;
82
83
#ifdef __POSIX__
84
  struct utsname info;
85
1
  if (uname(&info) < 0) {
86
    return env->ThrowErrnoException(errno, "uname");
87
  }
88
1
  rval = info.release;
89
#else  // Windows
90
  char release[256];
91
  OSVERSIONINFOW info;
92
93
  info.dwOSVersionInfoSize = sizeof(info);
94
95
  // Don't complain that GetVersionEx is deprecated; there is no alternative.
96
  #pragma warning(suppress : 4996)
97
  if (GetVersionExW(&info) == 0)
98
    return;
99
100
  snprintf(release,
101
           sizeof(release),
102
           "%d.%d.%d",
103
           static_cast<int>(info.dwMajorVersion),
104
           static_cast<int>(info.dwMinorVersion),
105
           static_cast<int>(info.dwBuildNumber));
106
  rval = release;
107
#endif  // __POSIX__
108
109
3
  args.GetReturnValue().Set(OneByteString(env->isolate(), rval));
110
}
111
112
113
1
static void GetCPUInfo(const FunctionCallbackInfo<Value>& args) {
114
1
  Environment* env = Environment::GetCurrent(args);
115
  uv_cpu_info_t* cpu_infos;
116
  int count, i;
117
118
1
  int err = uv_cpu_info(&cpu_infos, &count);
119
1
  if (err)
120
    return;
121
122
1
  Local<Array> cpus = Array::New(env->isolate());
123
9
  for (i = 0; i < count; i++) {
124
8
    uv_cpu_info_t* ci = cpu_infos + i;
125
126
8
    Local<Object> times_info = Object::New(env->isolate());
127
40
    times_info->Set(env->user_string(),
128
16
                    Number::New(env->isolate(), ci->cpu_times.user));
129
40
    times_info->Set(env->nice_string(),
130
16
                    Number::New(env->isolate(), ci->cpu_times.nice));
131
40
    times_info->Set(env->sys_string(),
132
16
                    Number::New(env->isolate(), ci->cpu_times.sys));
133
40
    times_info->Set(env->idle_string(),
134
16
                    Number::New(env->isolate(), ci->cpu_times.idle));
135
40
    times_info->Set(env->irq_string(),
136
16
                    Number::New(env->isolate(), ci->cpu_times.irq));
137
138
8
    Local<Object> cpu_info = Object::New(env->isolate());
139
40
    cpu_info->Set(env->model_string(),
140
16
                  OneByteString(env->isolate(), ci->model));
141
40
    cpu_info->Set(env->speed_string(),
142
16
                  Number::New(env->isolate(), ci->speed));
143
24
    cpu_info->Set(env->times_string(), times_info);
144
145
16
    (*cpus)->Set(i, cpu_info);
146
  }
147
148
1
  uv_free_cpu_info(cpu_infos, count);
149
2
  args.GetReturnValue().Set(cpus);
150
}
151
152
153
1
static void GetFreeMemory(const FunctionCallbackInfo<Value>& args) {
154
1
  double amount = uv_get_free_memory();
155
  if (amount < 0)
156
    return;
157
2
  args.GetReturnValue().Set(amount);
158
}
159
160
161
1389
static void GetTotalMemory(const FunctionCallbackInfo<Value>& args) {
162
1389
  double amount = uv_get_total_memory();
163
  if (amount < 0)
164
    return;
165
2778
  args.GetReturnValue().Set(amount);
166
}
167
168
169
1
static void GetUptime(const FunctionCallbackInfo<Value>& args) {
170
  double uptime;
171
1
  int err = uv_uptime(&uptime);
172
1
  if (err == 0)
173
2
    args.GetReturnValue().Set(uptime);
174
1
}
175
176
177
1
static void GetLoadAvg(const FunctionCallbackInfo<Value>& args) {
178
1
  Environment* env = Environment::GetCurrent(args);
179
  double loadavg[3];
180
1
  uv_loadavg(loadavg);
181
1
  Local<Array> loads = Array::New(env->isolate(), 3);
182
2
  loads->Set(0, Number::New(env->isolate(), loadavg[0]));
183
2
  loads->Set(1, Number::New(env->isolate(), loadavg[1]));
184
2
  loads->Set(2, Number::New(env->isolate(), loadavg[2]));
185
2
  args.GetReturnValue().Set(loads);
186
1
}
187
188
189
1390
static void GetInterfaceAddresses(const FunctionCallbackInfo<Value>& args) {
190
1390
  Environment* env = Environment::GetCurrent(args);
191
  uv_interface_address_t* interfaces;
192
  int count, i;
193
  char ip[INET6_ADDRSTRLEN];
194
  char netmask[INET6_ADDRSTRLEN];
195
  char mac[18];
196
2780
  Local<Object> ret, o;
197
2780
  Local<String> name, family;
198
1390
  Local<Array> ifarr;
199
200
1390
  int err = uv_interface_addresses(&interfaces, &count);
201
202
1390
  ret = Object::New(env->isolate());
203
204
1390
  if (err == UV_ENOSYS) {
205
    return args.GetReturnValue().Set(ret);
206
1390
  } else if (err) {
207
    return env->ThrowUVException(err, "uv_interface_addresses");
208
  }
209
210
20850
  for (i = 0; i < count; i++) {
211
9730
    const char* const raw_name = interfaces[i].name;
212
213
    // On Windows, the interface name is the UTF8-encoded friendly name and may
214
    // contain non-ASCII characters.  On UNIX, it's just a binary string with
215
    // no particular encoding but we treat it as a one-byte Latin-1 string.
216
#ifdef _WIN32
217
    name = String::NewFromUtf8(env->isolate(), raw_name);
218
#else
219
9730
    name = OneByteString(env->isolate(), raw_name);
220
#endif
221
222
29190
    if (ret->Has(env->context(), name).FromJust()) {
223
5560
      ifarr = Local<Array>::Cast(ret->Get(name));
224
    } else {
225
4170
      ifarr = Array::New(env->isolate());
226
8340
      ret->Set(name, ifarr);
227
    }
228
229
58380
    snprintf(mac,
230
             18,
231
             "%02x:%02x:%02x:%02x:%02x:%02x",
232
9730
             static_cast<unsigned char>(interfaces[i].phys_addr[0]),
233
9730
             static_cast<unsigned char>(interfaces[i].phys_addr[1]),
234
9730
             static_cast<unsigned char>(interfaces[i].phys_addr[2]),
235
9730
             static_cast<unsigned char>(interfaces[i].phys_addr[3]),
236
9730
             static_cast<unsigned char>(interfaces[i].phys_addr[4]),
237
19460
             static_cast<unsigned char>(interfaces[i].phys_addr[5]));
238
239
9730
    if (interfaces[i].address.address4.sin_family == AF_INET) {
240
4170
      uv_ip4_name(&interfaces[i].address.address4, ip, sizeof(ip));
241
4170
      uv_ip4_name(&interfaces[i].netmask.netmask4, netmask, sizeof(netmask));
242
4170
      family = env->ipv4_string();
243
5560
    } else if (interfaces[i].address.address4.sin_family == AF_INET6) {
244
5560
      uv_ip6_name(&interfaces[i].address.address6, ip, sizeof(ip));
245
5560
      uv_ip6_name(&interfaces[i].netmask.netmask6, netmask, sizeof(netmask));
246
5560
      family = env->ipv6_string();
247
    } else {
248
      strncpy(ip, "<unknown sa family>", INET6_ADDRSTRLEN);
249
      family = env->unknown_string();
250
    }
251
252
9730
    o = Object::New(env->isolate());
253
38920
    o->Set(env->address_string(), OneByteString(env->isolate(), ip));
254
38920
    o->Set(env->netmask_string(), OneByteString(env->isolate(), netmask));
255
29190
    o->Set(env->family_string(), family);
256
38920
    o->Set(env->mac_string(), FIXED_ONE_BYTE_STRING(env->isolate(), mac));
257
258
9730
    if (interfaces[i].address.address4.sin_family == AF_INET6) {
259
5560
      uint32_t scopeid = interfaces[i].address.address6.sin6_scope_id;
260
27800
      o->Set(env->scopeid_string(),
261
5560
             Integer::NewFromUnsigned(env->isolate(), scopeid));
262
    }
263
264
9730
    const bool internal = interfaces[i].is_internal;
265
48650
    o->Set(env->internal_string(),
266
19460
           internal ? True(env->isolate()) : False(env->isolate()));
267
268
9730
    ifarr->Set(ifarr->Length(), o);
269
  }
270
271
1390
  uv_free_interface_addresses(interfaces, count);
272
2780
  args.GetReturnValue().Set(ret);
273
}
274
275
276
8
static void GetHomeDirectory(const FunctionCallbackInfo<Value>& args) {
277
8
  Environment* env = Environment::GetCurrent(args);
278
  char buf[PATH_MAX];
279
280
8
  size_t len = sizeof(buf);
281
8
  const int err = uv_os_homedir(buf, &len);
282
283
8
  if (err) {
284
    return env->ThrowUVException(err, "uv_os_homedir");
285
  }
286
287
  Local<String> home = String::NewFromUtf8(env->isolate(),
288
                                           buf,
289
                                           String::kNormalString,
290
8
                                           len);
291
16
  args.GetReturnValue().Set(home);
292
}
293
294
295
2
static void GetUserInfo(const FunctionCallbackInfo<Value>& args) {
296
2
  Environment* env = Environment::GetCurrent(args);
297
  uv_passwd_t pwd;
298
  enum encoding encoding;
299
300
2
  if (args[0]->IsObject()) {
301
2
    Local<Object> options = args[0].As<Object>();
302
2
    Local<Value> encoding_opt = options->Get(env->encoding_string());
303
1
    encoding = ParseEncoding(env->isolate(), encoding_opt, UTF8);
304
  } else {
305
    encoding = UTF8;
306
  }
307
308
2
  const int err = uv_os_get_passwd(&pwd);
309
310
2
  if (err) {
311
    return env->ThrowUVException(err, "uv_os_get_passwd");
312
  }
313
314
4
  Local<Value> uid = Number::New(env->isolate(), pwd.uid);
315
4
  Local<Value> gid = Number::New(env->isolate(), pwd.gid);
316
  Local<Value> username = StringBytes::Encode(env->isolate(),
317
2
                                              pwd.username,
318
2
                                              encoding);
319
  Local<Value> homedir = StringBytes::Encode(env->isolate(),
320
2
                                             pwd.homedir,
321
2
                                             encoding);
322
2
  Local<Value> shell;
323
324
2
  if (pwd.shell == NULL)
325
    shell = Null(env->isolate());
326
  else
327
2
    shell = StringBytes::Encode(env->isolate(), pwd.shell, encoding);
328
329
2
  uv_os_free_passwd(&pwd);
330
331
2
  if (username.IsEmpty()) {
332
    return env->ThrowUVException(UV_EINVAL,
333
                                 "uv_os_get_passwd",
334
                                 "Invalid character encoding for username");
335
  }
336
337
2
  if (homedir.IsEmpty()) {
338
    return env->ThrowUVException(UV_EINVAL,
339
                                 "uv_os_get_passwd",
340
                                 "Invalid character encoding for homedir");
341
  }
342
343
2
  if (shell.IsEmpty()) {
344
    return env->ThrowUVException(UV_EINVAL,
345
                                 "uv_os_get_passwd",
346
                                 "Invalid character encoding for shell");
347
  }
348
349
2
  Local<Object> entry = Object::New(env->isolate());
350
351
4
  entry->Set(env->uid_string(), uid);
352
4
  entry->Set(env->gid_string(), gid);
353
4
  entry->Set(env->username_string(), username);
354
4
  entry->Set(env->homedir_string(), homedir);
355
4
  entry->Set(env->shell_string(), shell);
356
357
4
  args.GetReturnValue().Set(entry);
358
}
359
360
361
1401
void Initialize(Local<Object> target,
362
                Local<Value> unused,
363
                Local<Context> context) {
364
1401
  Environment* env = Environment::GetCurrent(context);
365
1401
  env->SetMethod(target, "getHostname", GetHostname);
366
1401
  env->SetMethod(target, "getLoadAvg", GetLoadAvg);
367
1401
  env->SetMethod(target, "getUptime", GetUptime);
368
1401
  env->SetMethod(target, "getTotalMem", GetTotalMemory);
369
1401
  env->SetMethod(target, "getFreeMem", GetFreeMemory);
370
1401
  env->SetMethod(target, "getCPUs", GetCPUInfo);
371
1401
  env->SetMethod(target, "getOSType", GetOSType);
372
1401
  env->SetMethod(target, "getOSRelease", GetOSRelease);
373
1401
  env->SetMethod(target, "getInterfaceAddresses", GetInterfaceAddresses);
374
1401
  env->SetMethod(target, "getHomeDirectory", GetHomeDirectory);
375
1401
  env->SetMethod(target, "getUserInfo", GetUserInfo);
376
8406
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "isBigEndian"),
377
1401
              Boolean::New(env->isolate(), IsBigEndian()));
378
1401
}
379
380
}  // namespace os
381
}  // namespace node
382
383
1564
NODE_MODULE_CONTEXT_AWARE_BUILTIN(os, node::os::Initialize)