• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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'use strict';
23
24const {
25  ObjectDefineProperties,
26  SymbolToPrimitive,
27} = primordials;
28
29const { safeGetenv } = internalBinding('credentials');
30const constants = internalBinding('constants').os;
31const { deprecate } = require('internal/util');
32const isWindows = process.platform === 'win32';
33
34const {
35  codes: {
36    ERR_SYSTEM_ERROR
37  },
38  hideStackFrames
39} = require('internal/errors');
40const { validateInt32 } = require('internal/validators');
41
42const {
43  getCPUs,
44  getFreeMem,
45  getHomeDirectory: _getHomeDirectory,
46  getHostname: _getHostname,
47  getInterfaceAddresses: _getInterfaceAddresses,
48  getLoadAvg,
49  getOSInformation: _getOSInformation,
50  getPriority: _getPriority,
51  getTotalMem,
52  getUserInfo,
53  getUptime,
54  isBigEndian,
55  setPriority: _setPriority
56} = internalBinding('os');
57
58function getCheckedFunction(fn) {
59  return hideStackFrames(function checkError(...args) {
60    const ctx = {};
61    const ret = fn(...args, ctx);
62    if (ret === undefined) {
63      throw new ERR_SYSTEM_ERROR(ctx);
64    }
65    return ret;
66  });
67}
68
69const [
70  type,
71  version,
72  release
73] = _getOSInformation();
74
75const getHomeDirectory = getCheckedFunction(_getHomeDirectory);
76const getHostname = getCheckedFunction(_getHostname);
77const getInterfaceAddresses = getCheckedFunction(_getInterfaceAddresses);
78const getOSRelease = () => release;
79const getOSType = () => type;
80const getOSVersion = () => version;
81
82getFreeMem[SymbolToPrimitive] = () => getFreeMem();
83getHostname[SymbolToPrimitive] = () => getHostname();
84getHomeDirectory[SymbolToPrimitive] = () => getHomeDirectory();
85getOSRelease[SymbolToPrimitive] = () => getOSRelease();
86getOSType[SymbolToPrimitive] = () => getOSType();
87getOSVersion[SymbolToPrimitive] = () => getOSVersion();
88getTotalMem[SymbolToPrimitive] = () => getTotalMem();
89getUptime[SymbolToPrimitive] = () => getUptime();
90
91const kEndianness = isBigEndian ? 'BE' : 'LE';
92
93const tmpDirDeprecationMsg =
94  'os.tmpDir() is deprecated. Use os.tmpdir() instead.';
95
96const avgValues = new Float64Array(3);
97
98function loadavg() {
99  getLoadAvg(avgValues);
100  return [avgValues[0], avgValues[1], avgValues[2]];
101}
102
103function cpus() {
104  // [] is a bugfix for a regression introduced in 51cea61
105  const data = getCPUs() || [];
106  const result = [];
107  let i = 0;
108  while (i < data.length) {
109    result.push({
110      model: data[i++],
111      speed: data[i++],
112      times: {
113        user: data[i++],
114        nice: data[i++],
115        sys: data[i++],
116        idle: data[i++],
117        irq: data[i++]
118      }
119    });
120  }
121  return result;
122}
123
124function arch() {
125  return process.arch;
126}
127arch[SymbolToPrimitive] = () => process.arch;
128
129function platform() {
130  return process.platform;
131}
132platform[SymbolToPrimitive] = () => process.platform;
133
134function tmpdir() {
135  var path;
136  if (isWindows) {
137    path = process.env.TEMP ||
138           process.env.TMP ||
139           (process.env.SystemRoot || process.env.windir) + '\\temp';
140    if (path.length > 1 && path.endsWith('\\') && !path.endsWith(':\\'))
141      path = path.slice(0, -1);
142  } else {
143    path = safeGetenv('TMPDIR') ||
144           safeGetenv('TMP') ||
145           safeGetenv('TEMP') ||
146           '/tmp';
147    if (path.length > 1 && path.endsWith('/'))
148      path = path.slice(0, -1);
149  }
150
151  return path;
152}
153tmpdir[SymbolToPrimitive] = () => tmpdir();
154
155function endianness() {
156  return kEndianness;
157}
158endianness[SymbolToPrimitive] = () => kEndianness;
159
160// Returns the number of ones in the binary representation of the decimal
161// number.
162function countBinaryOnes(n) {
163  // Count the number of bits set in parallel, which is faster than looping
164  n = n - ((n >>> 1) & 0x55555555);
165  n = (n & 0x33333333) + ((n >>> 2) & 0x33333333);
166  return ((n + (n >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24;
167}
168
169function getCIDR(address, netmask, family) {
170  let ones = 0;
171  let split = '.';
172  let range = 10;
173  let groupLength = 8;
174  let hasZeros = false;
175
176  if (family === 'IPv6') {
177    split = ':';
178    range = 16;
179    groupLength = 16;
180  }
181
182  const parts = netmask.split(split);
183  for (var i = 0; i < parts.length; i++) {
184    if (parts[i] !== '') {
185      const binary = parseInt(parts[i], range);
186      const tmp = countBinaryOnes(binary);
187      ones += tmp;
188      if (hasZeros) {
189        if (tmp !== 0) {
190          return null;
191        }
192      } else if (tmp !== groupLength) {
193        if ((binary & 1) !== 0) {
194          return null;
195        }
196        hasZeros = true;
197      }
198    }
199  }
200
201  return `${address}/${ones}`;
202}
203
204function networkInterfaces() {
205  const data = getInterfaceAddresses();
206  const result = {};
207
208  if (data === undefined)
209    return result;
210  for (var i = 0; i < data.length; i += 7) {
211    const name = data[i];
212    const entry = {
213      address: data[i + 1],
214      netmask: data[i + 2],
215      family: data[i + 3],
216      mac: data[i + 4],
217      internal: data[i + 5],
218      cidr: getCIDR(data[i + 1], data[i + 2], data[i + 3])
219    };
220    const scopeid = data[i + 6];
221    if (scopeid !== -1)
222      entry.scopeid = scopeid;
223
224    const existing = result[name];
225    if (existing !== undefined)
226      existing.push(entry);
227    else
228      result[name] = [entry];
229  }
230
231  return result;
232}
233
234function setPriority(pid, priority) {
235  if (priority === undefined) {
236    priority = pid;
237    pid = 0;
238  }
239
240  validateInt32(pid, 'pid');
241  validateInt32(priority, 'priority', -20, 19);
242
243  const ctx = {};
244
245  if (_setPriority(pid, priority, ctx) !== 0)
246    throw new ERR_SYSTEM_ERROR(ctx);
247}
248
249function getPriority(pid) {
250  if (pid === undefined)
251    pid = 0;
252  else
253    validateInt32(pid, 'pid');
254
255  const ctx = {};
256  const priority = _getPriority(pid, ctx);
257
258  if (priority === undefined)
259    throw new ERR_SYSTEM_ERROR(ctx);
260
261  return priority;
262}
263
264function userInfo(options) {
265  if (typeof options !== 'object')
266    options = null;
267
268  const ctx = {};
269  const user = getUserInfo(options, ctx);
270
271  if (user === undefined)
272    throw new ERR_SYSTEM_ERROR(ctx);
273
274  return user;
275}
276
277module.exports = {
278  arch,
279  cpus,
280  endianness,
281  freemem: getFreeMem,
282  getPriority,
283  homedir: getHomeDirectory,
284  hostname: getHostname,
285  loadavg,
286  networkInterfaces,
287  platform,
288  release: getOSRelease,
289  setPriority,
290  tmpdir,
291  totalmem: getTotalMem,
292  type: getOSType,
293  version: getOSVersion,
294  userInfo,
295  uptime: getUptime,
296
297  // Deprecated APIs
298  tmpDir: deprecate(tmpdir, tmpDirDeprecationMsg, 'DEP0022')
299};
300
301ObjectDefineProperties(module.exports, {
302  constants: {
303    configurable: false,
304    enumerable: true,
305    value: constants
306  },
307
308  EOL: {
309    configurable: true,
310    enumerable: true,
311    writable: false,
312    value: isWindows ? '\r\n' : '\n'
313  }
314});
315