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