GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage/nodes/benchmark/out/../src/node_os.cc Lines: 162 189 85.7 %
Date: 2017-11-19 Branches: 43 82 52.4 %

Line Branch Exec Source
1
// Copyright Joyent, Inc. and other Node contributors.
2
//
3
// Permission is hereby granted, free of charge, to any person obtaining a
4
// copy of this software and associated documentation files (the
5
// "Software"), to deal in the Software without restriction, including
6
// without limitation the rights to use, copy, modify, merge, publish,
7
// distribute, sublicense, and/or sell copies of the Software, and to permit
8
// persons to whom the Software is furnished to do so, subject to the
9
// following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included
12
// in all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22
#include "node_internals.h"
23
#include "string_bytes.h"
24
25
#include <errno.h>
26
#include <string.h>
27
28
#ifdef __MINGW32__
29
# include <io.h>
30
#endif  // __MINGW32__
31
32
#ifdef __POSIX__
33
# include <limits.h>        // PATH_MAX on Solaris.
34
# include <netdb.h>         // MAXHOSTNAMELEN on Solaris.
35
# include <unistd.h>        // gethostname, sysconf
36
# include <sys/param.h>     // MAXHOSTNAMELEN on Linux and the BSDs.
37
# include <sys/utsname.h>
38
#endif  // __POSIX__
39
40
// Add Windows fallback.
41
#ifndef MAXHOSTNAMELEN
42
# define MAXHOSTNAMELEN 256
43
#endif  // MAXHOSTNAMELEN
44
45
namespace node {
46
namespace os {
47
48
using v8::Array;
49
using v8::ArrayBuffer;
50
using v8::Boolean;
51
using v8::Context;
52
using v8::Float64Array;
53
using v8::Function;
54
using v8::FunctionCallbackInfo;
55
using v8::Integer;
56
using v8::Local;
57
using v8::MaybeLocal;
58
using v8::Null;
59
using v8::Number;
60
using v8::Object;
61
using v8::String;
62
using v8::Value;
63
64
65
3
static void GetHostname(const FunctionCallbackInfo<Value>& args) {
66
3
  Environment* env = Environment::GetCurrent(args);
67
  char buf[MAXHOSTNAMELEN + 1];
68
69
3
  if (gethostname(buf, sizeof(buf))) {
70
#ifdef __POSIX__
71
    int errorno = errno;
72
#else  // __MINGW32__
73
    int errorno = WSAGetLastError();
74
#endif  // __POSIX__
75
    CHECK_GE(args.Length(), 1);
76
    env->CollectExceptionInfo(args[args.Length() - 1], errorno, "gethostname");
77
3
    return args.GetReturnValue().SetUndefined();
78
  }
79
3
  buf[sizeof(buf) - 1] = '\0';
80
81
9
  args.GetReturnValue().Set(OneByteString(env->isolate(), buf));
82
}
83
84
85
9
static void GetOSType(const FunctionCallbackInfo<Value>& args) {
86
9
  Environment* env = Environment::GetCurrent(args);
87
  const char* rval;
88
89
#ifdef __POSIX__
90
  struct utsname info;
91
9
  if (uname(&info) < 0) {
92
    CHECK_GE(args.Length(), 1);
93
    env->CollectExceptionInfo(args[args.Length() - 1], errno, "uname");
94
9
    return args.GetReturnValue().SetUndefined();
95
  }
96
9
  rval = info.sysname;
97
#else  // __MINGW32__
98
  rval = "Windows_NT";
99
#endif  // __POSIX__
100
101
27
  args.GetReturnValue().Set(OneByteString(env->isolate(), rval));
102
}
103
104
105
3
static void GetOSRelease(const FunctionCallbackInfo<Value>& args) {
106
3
  Environment* env = Environment::GetCurrent(args);
107
  const char* rval;
108
109
#ifdef __POSIX__
110
  struct utsname info;
111
3
  if (uname(&info) < 0) {
112
    CHECK_GE(args.Length(), 1);
113
    env->CollectExceptionInfo(args[args.Length() - 1], errno, "uname");
114
3
    return args.GetReturnValue().SetUndefined();
115
  }
116
# ifdef _AIX
117
  char release[256];
118
  snprintf(release, sizeof(release),
119
           "%s.%s", info.version, info.release);
120
  rval = release;
121
# else
122
3
  rval = info.release;
123
# endif
124
#else  // Windows
125
  char release[256];
126
  OSVERSIONINFOW info;
127
128
  info.dwOSVersionInfoSize = sizeof(info);
129
130
  // Don't complain that GetVersionEx is deprecated; there is no alternative.
131
  #pragma warning(suppress : 4996)
132
  if (GetVersionExW(&info) == 0)
133
    return;
134
135
  snprintf(release,
136
           sizeof(release),
137
           "%d.%d.%d",
138
           static_cast<int>(info.dwMajorVersion),
139
           static_cast<int>(info.dwMinorVersion),
140
           static_cast<int>(info.dwBuildNumber));
141
  rval = release;
142
#endif  // __POSIX__
143
144
9
  args.GetReturnValue().Set(OneByteString(env->isolate(), rval));
145
}
146
147
148
2449
static void GetCPUInfo(const FunctionCallbackInfo<Value>& args) {
149
2449
  Environment* env = Environment::GetCurrent(args);
150
  uv_cpu_info_t* cpu_infos;
151
  int count, i, field_idx;
152
153
2449
  int err = uv_cpu_info(&cpu_infos, &count);
154
2449
  if (err)
155
2449
    return;
156
157
4898
  CHECK(args[0]->IsFunction());
158
4898
  Local<Function> addfn = args[0].As<Function>();
159
160
4898
  CHECK(args[1]->IsFloat64Array());
161
4898
  Local<Float64Array> array = args[1].As<Float64Array>();
162
2449
  CHECK_EQ(array->Length(), 6 * NODE_PUSH_VAL_TO_ARRAY_MAX);
163
2449
  Local<ArrayBuffer> ab = array->Buffer();
164
2449
  double* fields = static_cast<double*>(ab->GetContents().Data());
165
166
4898
  CHECK(args[2]->IsArray());
167
4898
  Local<Array> cpus = args[2].As<Array>();
168
169
22041
  Local<Value> model_argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
170
2449
  int model_idx = 0;
171
172
22041
  for (i = 0, field_idx = 0; i < count; i++) {
173
19592
    uv_cpu_info_t* ci = cpu_infos + i;
174
175
19592
    fields[field_idx++] = ci->speed;
176
19592
    fields[field_idx++] = ci->cpu_times.user;
177
19592
    fields[field_idx++] = ci->cpu_times.nice;
178
19592
    fields[field_idx++] = ci->cpu_times.sys;
179
19592
    fields[field_idx++] = ci->cpu_times.idle;
180
19592
    fields[field_idx++] = ci->cpu_times.irq;
181
39184
    model_argv[model_idx++] = OneByteString(env->isolate(), ci->model);
182
183
19592
    if (model_idx >= NODE_PUSH_VAL_TO_ARRAY_MAX) {
184
7347
      addfn->Call(env->context(), cpus, model_idx, model_argv).ToLocalChecked();
185
2449
      model_idx = 0;
186
2449
      field_idx = 0;
187
    }
188
  }
189
190
2449
  if (model_idx > 0) {
191
    addfn->Call(env->context(), cpus, model_idx, model_argv).ToLocalChecked();
192
  }
193
194
2449
  uv_free_cpu_info(cpu_infos, count);
195
4898
  args.GetReturnValue().Set(cpus);
196
}
197
198
199
3
static void GetFreeMemory(const FunctionCallbackInfo<Value>& args) {
200
3
  double amount = uv_get_free_memory();
201
3
  if (amount < 0)
202
3
    return;
203
6
  args.GetReturnValue().Set(amount);
204
}
205
206
207
2447
static void GetTotalMemory(const FunctionCallbackInfo<Value>& args) {
208
2447
  double amount = uv_get_total_memory();
209
2447
  if (amount < 0)
210
2447
    return;
211
4894
  args.GetReturnValue().Set(amount);
212
}
213
214
215
3
static void GetUptime(const FunctionCallbackInfo<Value>& args) {
216
  double uptime;
217
3
  int err = uv_uptime(&uptime);
218
3
  if (err == 0)
219
9
    args.GetReturnValue().Set(uptime);
220
3
}
221
222
223
2
static void GetLoadAvg(const FunctionCallbackInfo<Value>& args) {
224
4
  CHECK(args[0]->IsFloat64Array());
225
4
  Local<Float64Array> array = args[0].As<Float64Array>();
226
2
  CHECK_EQ(array->Length(), 3);
227
2
  Local<ArrayBuffer> ab = array->Buffer();
228
2
  double* loadavg = static_cast<double*>(ab->GetContents().Data());
229
2
  uv_loadavg(loadavg);
230
2
}
231
232
233
2449
static void GetInterfaceAddresses(const FunctionCallbackInfo<Value>& args) {
234
2449
  Environment* env = Environment::GetCurrent(args);
235
  uv_interface_address_t* interfaces;
236
  int count, i;
237
  char ip[INET6_ADDRSTRLEN];
238
  char netmask[INET6_ADDRSTRLEN];
239
  char mac[18];
240
  Local<Object> ret, o;
241
  Local<String> name, family;
242
  Local<Array> ifarr;
243
244
2449
  int err = uv_interface_addresses(&interfaces, &count);
245
246
2449
  ret = Object::New(env->isolate());
247
248
2449
  if (err == UV_ENOSYS) {
249
    return args.GetReturnValue().Set(ret);
250
2449
  } else if (err) {
251
    CHECK_GE(args.Length(), 1);
252
    env->CollectUVExceptionInfo(args[args.Length() - 1], errno,
253
                                "uv_interface_addresses");
254
    return args.GetReturnValue().SetUndefined();
255
  }
256
257
17143
  for (i = 0; i < count; i++) {
258
14694
    const char* const raw_name = interfaces[i].name;
259
260
    // On Windows, the interface name is the UTF8-encoded friendly name and may
261
    // contain non-ASCII characters.  On UNIX, it's just a binary string with
262
    // no particular encoding but we treat it as a one-byte Latin-1 string.
263
#ifdef _WIN32
264
    name = String::NewFromUtf8(env->isolate(), raw_name);
265
#else
266
14694
    name = OneByteString(env->isolate(), raw_name);
267
#endif
268
269
44082
    if (ret->Has(env->context(), name).FromJust()) {
270
14694
      ifarr = Local<Array>::Cast(ret->Get(name));
271
    } else {
272
7347
      ifarr = Array::New(env->isolate());
273
7347
      ret->Set(name, ifarr);
274
    }
275
276
    snprintf(mac,
277
             18,
278
             "%02x:%02x:%02x:%02x:%02x:%02x",
279
14694
             static_cast<unsigned char>(interfaces[i].phys_addr[0]),
280
14694
             static_cast<unsigned char>(interfaces[i].phys_addr[1]),
281
14694
             static_cast<unsigned char>(interfaces[i].phys_addr[2]),
282
14694
             static_cast<unsigned char>(interfaces[i].phys_addr[3]),
283
14694
             static_cast<unsigned char>(interfaces[i].phys_addr[4]),
284
88164
             static_cast<unsigned char>(interfaces[i].phys_addr[5]));
285
286
14694
    if (interfaces[i].address.address4.sin_family == AF_INET) {
287
7347
      uv_ip4_name(&interfaces[i].address.address4, ip, sizeof(ip));
288
7347
      uv_ip4_name(&interfaces[i].netmask.netmask4, netmask, sizeof(netmask));
289
7347
      family = env->ipv4_string();
290
7347
    } else if (interfaces[i].address.address4.sin_family == AF_INET6) {
291
7347
      uv_ip6_name(&interfaces[i].address.address6, ip, sizeof(ip));
292
7347
      uv_ip6_name(&interfaces[i].netmask.netmask6, netmask, sizeof(netmask));
293
7347
      family = env->ipv6_string();
294
    } else {
295
      strncpy(ip, "<unknown sa family>", INET6_ADDRSTRLEN);
296
      family = env->unknown_string();
297
    }
298
299
14694
    o = Object::New(env->isolate());
300
44082
    o->Set(env->address_string(), OneByteString(env->isolate(), ip));
301
44082
    o->Set(env->netmask_string(), OneByteString(env->isolate(), netmask));
302
29388
    o->Set(env->family_string(), family);
303
44082
    o->Set(env->mac_string(), FIXED_ONE_BYTE_STRING(env->isolate(), mac));
304
305
14694
    if (interfaces[i].address.address4.sin_family == AF_INET6) {
306
7347
      uint32_t scopeid = interfaces[i].address.address6.sin6_scope_id;
307
      o->Set(env->scopeid_string(),
308
22041
             Integer::NewFromUnsigned(env->isolate(), scopeid));
309
    }
310
311
14694
    const bool internal = interfaces[i].is_internal;
312
    o->Set(env->internal_string(),
313
53878
           internal ? True(env->isolate()) : False(env->isolate()));
314
315
29388
    ifarr->Set(ifarr->Length(), o);
316
  }
317
318
2449
  uv_free_interface_addresses(interfaces, count);
319
4898
  args.GetReturnValue().Set(ret);
320
}
321
322
323
94
static void GetHomeDirectory(const FunctionCallbackInfo<Value>& args) {
324
94
  Environment* env = Environment::GetCurrent(args);
325
  char buf[PATH_MAX];
326
327
94
  size_t len = sizeof(buf);
328
94
  const int err = uv_os_homedir(buf, &len);
329
330
94
  if (err) {
331
    CHECK_GE(args.Length(), 1);
332
    env->CollectUVExceptionInfo(args[args.Length() - 1], err, "uv_os_homedir");
333
94
    return args.GetReturnValue().SetUndefined();
334
  }
335
336
  Local<String> home = String::NewFromUtf8(env->isolate(),
337
                                           buf,
338
                                           String::kNormalString,
339
94
                                           len);
340
188
  args.GetReturnValue().Set(home);
341
}
342
343
344
3
static void GetUserInfo(const FunctionCallbackInfo<Value>& args) {
345
3
  Environment* env = Environment::GetCurrent(args);
346
  uv_passwd_t pwd;
347
  enum encoding encoding;
348
349
6
  if (args[0]->IsObject()) {
350
6
    Local<Object> options = args[0].As<Object>();
351
    MaybeLocal<Value> maybe_encoding = options->Get(env->context(),
352
9
                                                    env->encoding_string());
353
3
    if (maybe_encoding.IsEmpty())
354
1
      return;
355
356
2
    Local<Value> encoding_opt = maybe_encoding.ToLocalChecked();
357
2
    encoding = ParseEncoding(env->isolate(), encoding_opt, UTF8);
358
  } else {
359
    encoding = UTF8;
360
  }
361
362
2
  const int err = uv_os_get_passwd(&pwd);
363
364
2
  if (err) {
365
    CHECK_GE(args.Length(), 2);
366
    env->CollectUVExceptionInfo(args[args.Length() - 1], err,
367
                                "uv_os_get_passwd");
368
    return args.GetReturnValue().SetUndefined();
369
  }
370
371
  Local<Value> error;
372
373
2
  Local<Value> uid = Number::New(env->isolate(), pwd.uid);
374
2
  Local<Value> gid = Number::New(env->isolate(), pwd.gid);
375
  MaybeLocal<Value> username = StringBytes::Encode(env->isolate(),
376
                                                   pwd.username,
377
                                                   encoding,
378
2
                                                   &error);
379
  MaybeLocal<Value> homedir = StringBytes::Encode(env->isolate(),
380
                                                  pwd.homedir,
381
                                                  encoding,
382
2
                                                  &error);
383
  MaybeLocal<Value> shell;
384
385
2
  if (pwd.shell == NULL)
386
    shell = Null(env->isolate());
387
  else
388
2
    shell = StringBytes::Encode(env->isolate(), pwd.shell, encoding, &error);
389
390


6
  if (username.IsEmpty() || homedir.IsEmpty() || shell.IsEmpty()) {
391
    CHECK(!error.IsEmpty());
392
    uv_os_free_passwd(&pwd);
393
    env->isolate()->ThrowException(error);
394
    return;
395
  }
396
397
2
  Local<Object> entry = Object::New(env->isolate());
398
399
4
  entry->Set(env->uid_string(), uid);
400
4
  entry->Set(env->gid_string(), gid);
401
4
  entry->Set(env->username_string(), username.ToLocalChecked());
402
4
  entry->Set(env->homedir_string(), homedir.ToLocalChecked());
403
4
  entry->Set(env->shell_string(), shell.ToLocalChecked());
404
405
4
  args.GetReturnValue().Set(entry);
406
}
407
408
409
2533
void Initialize(Local<Object> target,
410
                Local<Value> unused,
411
                Local<Context> context) {
412
2533
  Environment* env = Environment::GetCurrent(context);
413
2533
  env->SetMethod(target, "getHostname", GetHostname);
414
2533
  env->SetMethod(target, "getLoadAvg", GetLoadAvg);
415
2533
  env->SetMethod(target, "getUptime", GetUptime);
416
2533
  env->SetMethod(target, "getTotalMem", GetTotalMemory);
417
2533
  env->SetMethod(target, "getFreeMem", GetFreeMemory);
418
2533
  env->SetMethod(target, "getCPUs", GetCPUInfo);
419
2533
  env->SetMethod(target, "getOSType", GetOSType);
420
2533
  env->SetMethod(target, "getOSRelease", GetOSRelease);
421
2533
  env->SetMethod(target, "getInterfaceAddresses", GetInterfaceAddresses);
422
2533
  env->SetMethod(target, "getHomeDirectory", GetHomeDirectory);
423
2533
  env->SetMethod(target, "getUserInfo", GetUserInfo);
424
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "isBigEndian"),
425
7599
              Boolean::New(env->isolate(), IsBigEndian()));
426
2533
}
427
428
}  // namespace os
429
}  // namespace node
430
431
3332
NODE_BUILTIN_MODULE_CONTEXT_AWARE(os, node::os::Initialize)