Command Injection in fsSize() on Windows
Description
systeminformation is a System and OS information library for node.js. In versions prior to 5.27.14, the fsSize() function in systeminformation is vulnerable to OS command injection on Windows systems. The optional drive parameter is directly concatenated into a PowerShell command without sanitization, allowing arbitrary command execution when user-controlled input reaches this function. The actual exploitability depends on how applications use this function. If an application does not pass user-controlled input to fsSize(), it is not vulnerable. Version 5.27.14 contains a patch.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
systeminformationnpm | < 5.27.14 | 5.27.14 |
Affected products
1- Range: < 5.27.14
Patches
1c52f9fd07feffsSize() fix drive sanitation (windows)
6 files changed · +768 −513
CHANGELOG.md+1 −0 modified@@ -90,6 +90,7 @@ For major (breaking) changes - **version 4, 3 and 2** - see end of page. | Version | Date | Comment | | ------- | ---------- | --------------------------------------------------------------------------------------------------- | +| 5.27.14 | 2025-12-15 | `fsSize()` fix drive sanitation (windows) | | 5.27.13 | 2025-12-10 | `cpuCurrentSpeed()` fix hasOwnProperty | | 5.27.12 | 2025-12-09 | `networkConnections()` fix pid issue (macOS) | | 5.27.11 | 2025-10-05 | `system()` added latest mac studio versions (macOS) |
docs/history.html+5 −0 modified@@ -57,6 +57,11 @@ <h3>Full version history</h3> </tr> </thead> <tbody> + <tr> + <th scope="row">5.27.14</th> + <td>2025-12-16</td> + <td><span class="code">fsSize()</span> fix sanitation drive (windows)</td> + </tr> <tr> <th scope="row">5.27.13</th> <td>2025-12-10</td>
docs/index.html+2 −2 modified@@ -166,11 +166,11 @@ <body> <header class="bg-image-full"> <div class="top-container"> - <a href="security.html" class="recommendation">Security advisory:<br>Update to v5.23.7</a> + <a href="security.html" class="recommendation">Security advisory:<br>Update to v5.27.14</a> <img class="logo" src="assets/logo.png" alt="logo"> <div class="title">systeminformation</div> <div class="subtitle"><span id="typed"></span> </div> - <div class="version">New Version: <span id="version">5.27.13</span></div> + <div class="version">New Version: <span id="version">5.27.14</span></div> <button class="btn btn-light" onclick="location.href='https://github.com/sebhildebrandt/systeminformation'">View on Github <i class=" fab fa-github"></i></button> </div> <div class="down">
docs/security.html+15 −0 modified@@ -44,6 +44,21 @@ <div class="col-12 sectionheader"> <div class="title">Security Advisories</div> <div class="text"> + <h2>fsSize Command Injection Vulnerability</h2> + <p><span class="bold">Affected versions:</span> + < 5.23.14<br> + <span class="bold">Date:</span> 2025-12-16<br> + <span class="bold">CVE indentifier</span> CVE-??? + </p> + + <h4>Impact</h4> + <p>We had an issue that there was a possibility to perform a potential command injection possibility by manipulating Win32_logicaldisk input in <span class="code">fsSize()</span> on windows machines.</p> + + <h4>Patch</h4> + <p>Problem was fixed with parameter checking. If you are using version 5, please upgrade to version >= 5.27.14.</p> + <hr> + <br> + <h2>SSID Command Injection Vulnerability</h2> <p><span class="bold">Affected versions:</span> < 5.23.7<br>
lib/filesystem.js+495 −340 modified@@ -20,24 +20,23 @@ const exec = require('child_process').exec; const execSync = require('child_process').execSync; const execPromiseSave = util.promisifySave(require('child_process').exec); -let _platform = process.platform; +const _platform = process.platform; -const _linux = (_platform === 'linux' || _platform === 'android'); -const _darwin = (_platform === 'darwin'); -const _windows = (_platform === 'win32'); -const _freebsd = (_platform === 'freebsd'); -const _openbsd = (_platform === 'openbsd'); -const _netbsd = (_platform === 'netbsd'); -const _sunos = (_platform === 'sunos'); +const _linux = _platform === 'linux' || _platform === 'android'; +const _darwin = _platform === 'darwin'; +const _windows = _platform === 'win32'; +const _freebsd = _platform === 'freebsd'; +const _openbsd = _platform === 'openbsd'; +const _netbsd = _platform === 'netbsd'; +const _sunos = _platform === 'sunos'; -let _fs_speed = {}; -let _disk_io = {}; +const _fs_speed = {}; +const _disk_io = {}; // -------------------------- // FS - mounted file systems function fsSize(drive, callback) { - if (util.isFunction(drive)) { callback = drive; drive = ''; @@ -47,30 +46,36 @@ function fsSize(drive, callback) { let osMounts = []; function getmacOsFsType(fs) { - if (!fs.startsWith('/')) { return 'NFS'; } + if (!fs.startsWith('/')) { + return 'NFS'; + } const parts = fs.split('/'); const fsShort = parts[parts.length - 1]; - const macOsDisksSingle = macOsDisks.filter(item => item.indexOf(fsShort) >= 0); - if (macOsDisksSingle.length === 1 && macOsDisksSingle[0].indexOf('APFS') >= 0) { return 'APFS'; } + const macOsDisksSingle = macOsDisks.filter((item) => item.indexOf(fsShort) >= 0); + if (macOsDisksSingle.length === 1 && macOsDisksSingle[0].indexOf('APFS') >= 0) { + return 'APFS'; + } return 'HFS'; } function isLinuxTmpFs(fs) { const linuxTmpFileSystems = ['rootfs', 'unionfs', 'squashfs', 'cramfs', 'initrd', 'initramfs', 'devtmpfs', 'tmpfs', 'udev', 'devfs', 'specfs', 'type', 'appimaged']; let result = false; - linuxTmpFileSystems.forEach(linuxFs => { - if (fs.toLowerCase().indexOf(linuxFs) >= 0) { result = true; } + linuxTmpFileSystems.forEach((linuxFs) => { + if (fs.toLowerCase().indexOf(linuxFs) >= 0) { + result = true; + } }); return result; } function filterLines(stdout) { - let lines = stdout.toString().split('\n'); + const lines = stdout.toString().split('\n'); lines.shift(); if (stdout.toString().toLowerCase().indexOf('filesystem')) { let removeLines = 0; for (let i = 0; i < lines.length; i++) { - if (lines[i] && lines[i].toLowerCase().startsWith('filesystem')) { + if (lines[i]?.toLowerCase().startsWith('filesystem')) { removeLines = i; } } @@ -82,21 +87,21 @@ function fsSize(drive, callback) { } function parseDf(lines) { - let data = []; - lines.forEach(function (line) { + const data = []; + lines.forEach((line) => { if (line !== '') { line = line.replace(/ +/g, ' ').split(' '); - if (line && ((line[0].startsWith('/')) || (line[6] && line[6] === '/') || (line[0].indexOf('/') > 0) || (line[0].indexOf(':') === 1) || !_darwin && !isLinuxTmpFs(line[1]))) { + if (line && (line[0].startsWith('/') || (line[6] && line[6] === '/') || line[0].indexOf('/') > 0 || line[0].indexOf(':') === 1 || (!_darwin && !isLinuxTmpFs(line[1])))) { const fs = line[0]; - const fsType = ((_linux || _freebsd || _openbsd || _netbsd) ? line[1] : getmacOsFsType(line[0])); - const size = parseInt(((_linux || _freebsd || _openbsd || _netbsd) ? line[2] : line[1])) * 1024; - const used = parseInt(((_linux || _freebsd || _openbsd || _netbsd) ? line[3] : line[2])) * 1024; - const available = parseInt(((_linux || _freebsd || _openbsd || _netbsd) ? line[4] : line[3])) * 1024; + const fsType = _linux || _freebsd || _openbsd || _netbsd ? line[1] : getmacOsFsType(line[0]); + const size = parseInt(_linux || _freebsd || _openbsd || _netbsd ? line[2] : line[1], 10) * 1024; + const used = parseInt(_linux || _freebsd || _openbsd || _netbsd ? line[3] : line[2], 10) * 1024; + const available = parseInt(_linux || _freebsd || _openbsd || _netbsd ? line[4] : line[3], 10) * 1024; const use = parseFloat((100.0 * (used / (used + available))).toFixed(2)); - let rw = osMounts && Object.keys(osMounts).length > 0 ? osMounts[fs] || false : null; - line.splice(0, (_linux || _freebsd || _openbsd || _netbsd) ? 6 : 5); + const rw = osMounts && Object.keys(osMounts).length > 0 ? osMounts[fs] || false : null; + line.splice(0, _linux || _freebsd || _openbsd || _netbsd ? 6 : 5); const mount = line.join(' '); - if (!data.find(el => (el.fs === fs && el.type === fsType))) { + if (!data.find((el) => el.fs === fs && el.type === fsType)) { data.push({ fs, type: fsType, @@ -124,48 +129,62 @@ function fsSize(drive, callback) { if (_darwin) { cmd = 'df -kP'; try { - macOsDisks = execSync('diskutil list').toString().split('\n').filter(line => { - return !line.startsWith('/') && line.indexOf(':') > 0; - }); - execSync('mount').toString().split('\n').filter(line => { - return line.startsWith('/'); - }).forEach((line) => { - osMounts[line.split(' ')[0]] = line.toLowerCase().indexOf('read-only') === -1; - }); - } catch (e) { + macOsDisks = execSync('diskutil list') + .toString() + .split('\n') + .filter((line) => { + return !line.startsWith('/') && line.indexOf(':') > 0; + }); + execSync('mount') + .toString() + .split('\n') + .filter((line) => { + return line.startsWith('/'); + }) + .forEach((line) => { + osMounts[line.split(' ')[0]] = line.toLowerCase().indexOf('read-only') === -1; + }); + } catch { util.noop(); } } if (_linux) { try { cmd = 'export LC_ALL=C; df -lkPTx squashfs; unset LC_ALL'; - execSync('cat /proc/mounts 2>/dev/null', util.execOptsLinux).toString().split('\n').filter(line => { - return line.startsWith('/'); - }).forEach((line) => { - osMounts[line.split(' ')[0]] = osMounts[line.split(' ')[0]] || false; - if (line.toLowerCase().indexOf('/snap/') === -1) { - osMounts[line.split(' ')[0]] = ((line.toLowerCase().indexOf('rw,') >= 0 || line.toLowerCase().indexOf(' rw ') >= 0)); - } - }); - } catch (e) { + execSync('cat /proc/mounts 2>/dev/null', util.execOptsLinux) + .toString() + .split('\n') + .filter((line) => { + return line.startsWith('/'); + }) + .forEach((line) => { + osMounts[line.split(' ')[0]] = osMounts[line.split(' ')[0]] || false; + if (line.toLowerCase().indexOf('/snap/') === -1) { + osMounts[line.split(' ')[0]] = line.toLowerCase().indexOf('rw,') >= 0 || line.toLowerCase().indexOf(' rw ') >= 0; + } + }); + } catch { util.noop(); } } if (_freebsd || _openbsd || _netbsd) { try { cmd = 'df -lkPT'; - execSync('mount').toString().split('\n').forEach((line) => { - osMounts[line.split(' ')[0]] = line.toLowerCase().indexOf('read-only') === -1; - }); - } catch (e) { + execSync('mount') + .toString() + .split('\n') + .forEach((line) => { + osMounts[line.split(' ')[0]] = line.toLowerCase().indexOf('read-only') === -1; + }); + } catch { util.noop(); } } - exec(cmd, { maxBuffer: 1024 * 1024 }, function (error, stdout) { - let lines = filterLines(stdout); + exec(cmd, { maxBuffer: 1024 * 1024 }, (error, stdout) => { + const lines = filterLines(stdout); data = parseDf(lines); if (drive) { - data = data.filter(item => { + data = data.filter((item) => { return item.fs.toLowerCase().indexOf(drive.toLowerCase()) >= 0 || item.mount.toLowerCase().indexOf(drive.toLowerCase()) >= 0; }); } @@ -175,9 +194,9 @@ function fsSize(drive, callback) { } resolve(data); } else { - exec('df -kPT', { maxBuffer: 1024 * 1024 }, function (error, stdout) { + exec('df -kPT', { maxBuffer: 1024 * 1024 }, (error, stdout) => { if (!error) { - let lines = filterLines(stdout); + const lines = filterLines(stdout); data = parseDf(lines); } if (callback) { @@ -189,22 +208,25 @@ function fsSize(drive, callback) { }); } if (_sunos) { - if (callback) { callback(data); } + if (callback) { + callback(data); + } resolve(data); } if (_windows) { try { - const cmd = `Get-WmiObject Win32_logicaldisk | select Access,Caption,FileSystem,FreeSpace,Size ${drive ? '| where -property Caption -eq ' + drive : ''} | fl`; + const driveSanitized = drive ? util.sanitizeShellString(drive, true) : ''; + const cmd = `Get-WmiObject Win32_logicaldisk | select Access,Caption,FileSystem,FreeSpace,Size ${driveSanitized ? '| where -property Caption -eq ' + driveSanitized : ''} | fl`; util.powerShell(cmd).then((stdout, error) => { if (!error) { - let devices = stdout.toString().split(/\n\s*\n/); - devices.forEach(function (device) { - let lines = device.split('\r\n'); + const devices = stdout.toString().split(/\n\s*\n/); + devices.forEach((device) => { + const lines = device.split('\r\n'); const size = util.toInt(util.getValue(lines, 'size', ':')); const free = util.toInt(util.getValue(lines, 'freespace', ':')); const caption = util.getValue(lines, 'caption', ':'); const rwValue = util.getValue(lines, 'access', ':'); - const rw = rwValue ? (util.toInt(rwValue) !== 1) : null; + const rw = rwValue ? util.toInt(rwValue) !== 1 : null; if (size) { data.push({ fs: caption, @@ -224,8 +246,10 @@ function fsSize(drive, callback) { } resolve(data); }); - } catch (e) { - if (callback) { callback(data); } + } catch { + if (callback) { + callback(data); + } resolve(data); } } @@ -239,7 +263,6 @@ exports.fsSize = fsSize; // FS - open files count function fsOpenFiles(callback) { - return new Promise((resolve) => { process.nextTick(() => { const result = { @@ -248,10 +271,10 @@ function fsOpenFiles(callback) { available: null }; if (_freebsd || _openbsd || _netbsd || _darwin) { - let cmd = 'sysctl -i kern.maxfiles kern.num_files kern.open_files'; - exec(cmd, { maxBuffer: 1024 * 1024 }, function (error, stdout) { + const cmd = 'sysctl -i kern.maxfiles kern.num_files kern.open_files'; + exec(cmd, { maxBuffer: 1024 * 1024 }, (error, stdout) => { if (!error) { - let lines = stdout.toString().split('\n'); + const lines = stdout.toString().split('\n'); result.max = parseInt(util.getValue(lines, 'kern.maxfiles', ':'), 10); result.allocated = parseInt(util.getValue(lines, 'kern.num_files', ':'), 10) || parseInt(util.getValue(lines, 'kern.open_files', ':'), 10); result.available = result.max - result.allocated; @@ -263,26 +286,28 @@ function fsOpenFiles(callback) { }); } if (_linux) { - fs.readFile('/proc/sys/fs/file-nr', function (error, stdout) { + fs.readFile('/proc/sys/fs/file-nr', (error, stdout) => { if (!error) { - let lines = stdout.toString().split('\n'); + const lines = stdout.toString().split('\n'); if (lines[0]) { const parts = lines[0].replace(/\s+/g, ' ').split(' '); if (parts.length === 3) { result.allocated = parseInt(parts[0], 10); result.available = parseInt(parts[1], 10); result.max = parseInt(parts[2], 10); - if (!result.available) { result.available = result.max - result.allocated; } + if (!result.available) { + result.available = result.max - result.allocated; + } } } if (callback) { callback(result); } resolve(result); } else { - fs.readFile('/proc/sys/fs/file-max', function (error, stdout) { + fs.readFile('/proc/sys/fs/file-max', (error, stdout) => { if (!error) { - let lines = stdout.toString().split('\n'); + const lines = stdout.toString().split('\n'); if (lines[0]) { result.max = parseInt(lines[0], 10); } @@ -296,11 +321,15 @@ function fsOpenFiles(callback) { }); } if (_sunos) { - if (callback) { callback(null); } + if (callback) { + callback(null); + } resolve(null); } if (_windows) { - if (callback) { callback(null); } + if (callback) { + callback(null); + } resolve(null); } }); @@ -313,18 +342,18 @@ exports.fsOpenFiles = fsOpenFiles; // disks function parseBytes(s) { - return parseInt(s.substr(s.indexOf(' (') + 2, s.indexOf(' Bytes)') - 10)); + return parseInt(s.substr(s.indexOf(' (') + 2, s.indexOf(' Bytes)') - 10), 10); } function parseDevices(lines) { - let devices = []; + const devices = []; let i = 0; - lines.forEach(line => { + lines.forEach((line) => { if (line.length > 0) { if (line[0] === '*') { i++; } else { - let parts = line.split(':'); + const parts = line.split(':'); if (parts.length > 1) { if (!devices[i]) { devices[i] = { @@ -347,22 +376,50 @@ function parseDevices(lines) { } parts[0] = parts[0].trim().toUpperCase().replace(/ +/g, ''); parts[1] = parts[1].trim(); - if ('DEVICEIDENTIFIER' === parts[0]) { devices[i].identifier = parts[1]; } - if ('DEVICENODE' === parts[0]) { devices[i].name = parts[1]; } + if ('DEVICEIDENTIFIER' === parts[0]) { + devices[i].identifier = parts[1]; + } + if ('DEVICENODE' === parts[0]) { + devices[i].name = parts[1]; + } if ('VOLUMENAME' === parts[0]) { - if (parts[1].indexOf('Not applicable') === -1) { devices[i].label = parts[1]; } + if (parts[1].indexOf('Not applicable') === -1) { + devices[i].label = parts[1]; + } + } + if ('PROTOCOL' === parts[0]) { + devices[i].protocol = parts[1]; + } + if ('DISKSIZE' === parts[0]) { + devices[i].size = parseBytes(parts[1]); + } + if ('FILESYSTEMPERSONALITY' === parts[0]) { + devices[i].fsType = parts[1]; + } + if ('MOUNTPOINT' === parts[0]) { + devices[i].mount = parts[1]; + } + if ('VOLUMEUUID' === parts[0]) { + devices[i].uuid = parts[1]; + } + if ('READ-ONLYMEDIA' === parts[0] && parts[1] === 'Yes') { + devices[i].physical = 'CD/DVD'; + } + if ('SOLIDSTATE' === parts[0] && parts[1] === 'Yes') { + devices[i].physical = 'SSD'; + } + if ('VIRTUAL' === parts[0]) { + devices[i].type = 'virtual'; + } + if ('REMOVABLEMEDIA' === parts[0]) { + devices[i].removable = parts[1] === 'Removable'; + } + if ('PARTITIONTYPE' === parts[0]) { + devices[i].type = 'part'; + } + if ('DEVICE/MEDIANAME' === parts[0]) { + devices[i].model = parts[1]; } - if ('PROTOCOL' === parts[0]) { devices[i].protocol = parts[1]; } - if ('DISKSIZE' === parts[0]) { devices[i].size = parseBytes(parts[1]); } - if ('FILESYSTEMPERSONALITY' === parts[0]) { devices[i].fsType = parts[1]; } - if ('MOUNTPOINT' === parts[0]) { devices[i].mount = parts[1]; } - if ('VOLUMEUUID' === parts[0]) { devices[i].uuid = parts[1]; } - if ('READ-ONLYMEDIA' === parts[0] && parts[1] === 'Yes') { devices[i].physical = 'CD/DVD'; } - if ('SOLIDSTATE' === parts[0] && parts[1] === 'Yes') { devices[i].physical = 'SSD'; } - if ('VIRTUAL' === parts[0]) { devices[i].type = 'virtual'; } - if ('REMOVABLEMEDIA' === parts[0]) { devices[i].removable = (parts[1] === 'Removable'); } - if ('PARTITIONTYPE' === parts[0]) { devices[i].type = 'part'; } - if ('DEVICE/MEDIANAME' === parts[0]) { devices[i].model = parts[1]; } } } } @@ -373,30 +430,32 @@ function parseDevices(lines) { function parseBlk(lines) { let data = []; - lines.filter(line => line !== '').forEach((line) => { - try { - line = decodeURIComponent(line.replace(/\\x/g, '%')); - line = line.replace(/\\/g, '\\\\'); - let disk = JSON.parse(line); - data.push({ - 'name': disk.name, - 'type': disk.type, - 'fsType': disk.fsType, - 'mount': disk.mountpoint, - 'size': parseInt(disk.size), - 'physical': (disk.type === 'disk' ? (disk.rota === '0' ? 'SSD' : 'HDD') : (disk.type === 'rom' ? 'CD/DVD' : '')), - 'uuid': disk.uuid, - 'label': disk.label, - 'model': (disk.model || '').trim(), - 'serial': disk.serial, - 'removable': disk.rm === '1', - 'protocol': disk.tran, - 'group': disk.group || '', - }); - } catch (e) { - util.noop(); - } - }); + lines + .filter((line) => line !== '') + .forEach((line) => { + try { + line = decodeURIComponent(line.replace(/\\x/g, '%')); + line = line.replace(/\\/g, '\\\\'); + const disk = JSON.parse(line); + data.push({ + name: util.sanitizeShellString(disk.name), + type: disk.type, + fsType: disk.fsType, + mount: disk.mountpoint, + size: parseInt(disk.size, 10), + physical: disk.type === 'disk' ? (disk.rota === '0' ? 'SSD' : 'HDD') : disk.type === 'rom' ? 'CD/DVD' : '', + uuid: disk.uuid, + label: disk.label, + model: (disk.model || '').trim(), + serial: disk.serial, + removable: disk.rm === '1', + protocol: disk.tran, + group: disk.group || '' + }); + } catch { + util.noop(); + } + }); data = util.unique(data); data = util.sortByKey(data, ['type', 'name']); return data; @@ -407,7 +466,7 @@ function decodeMdabmData(lines) { const label = util.getValue(lines, 'md_name', '='); // <- get label info const uuid = util.getValue(lines, 'md_uuid', '='); // <- get uuid info const members = []; - lines.forEach(line => { + lines.forEach((line) => { if (line.toLowerCase().startsWith('md_device_dev') && line.toLowerCase().indexOf('/dev/') > 0) { members.push(line.split('/dev/')[1]); } @@ -424,16 +483,16 @@ function raidMatchLinux(data) { // for all block devices of type "raid%" let result = data; try { - data.forEach(element => { + data.forEach((element) => { if (element.type.startsWith('raid')) { const lines = execSync(`mdadm --export --detail /dev/${element.name}`, util.execOptsLinux).toString().split('\n'); const mdData = decodeMdabmData(lines); element.label = mdData.label; // <- assign label info element.uuid = mdData.uuid; // <- assign uuid info - if (mdData.members && mdData.members.length && mdData.raid === element.type) { - result = result.map(blockdevice => { + if (mdData.members?.length && mdData.raid === element.type) { + result = result.map((blockdevice) => { if (blockdevice.fsType === 'linux_raid_member' && mdData.members.indexOf(blockdevice.name) >= 0) { blockdevice.group = element.name; } @@ -442,15 +501,15 @@ function raidMatchLinux(data) { } } }); - } catch (e) { + } catch { util.noop(); } return result; } function getDevicesLinux(data) { const result = []; - data.forEach(element => { + data.forEach((element) => { if (element.type.startsWith('disk')) { result.push(element.name); } @@ -462,31 +521,31 @@ function matchDevicesLinux(data) { let result = data; try { const devices = getDevicesLinux(data); - result = result.map(blockdevice => { + result = result.map((blockdevice) => { if (blockdevice.type.startsWith('part') || blockdevice.type.startsWith('disk')) { - devices.forEach(element => { + devices.forEach((element) => { if (blockdevice.name.startsWith(element)) { blockdevice.device = '/dev/' + element; } }); } return blockdevice; }); - } catch (e) { + } catch { util.noop(); } return result; } function getDevicesMac(data) { const result = []; - data.forEach(element => { + data.forEach((element) => { if (element.type.startsWith('disk')) { result.push({ name: element.name, model: element.model, device: element.name }); } if (element.type.startsWith('virtual')) { let device = ''; - result.forEach(e => { + result.forEach((e) => { if (e.model === element.model) { device = e.device; } @@ -503,31 +562,31 @@ function matchDevicesMac(data) { let result = data; try { const devices = getDevicesMac(data); - result = result.map(blockdevice => { + result = result.map((blockdevice) => { if (blockdevice.type.startsWith('part') || blockdevice.type.startsWith('disk') || blockdevice.type.startsWith('virtual')) { - devices.forEach(element => { + devices.forEach((element) => { if (blockdevice.name.startsWith(element.name)) { blockdevice.device = element.device; } }); } return blockdevice; }); - } catch (e) { + } catch { util.noop(); } return result; } function getDevicesWin(diskDrives) { const result = []; - diskDrives.forEach(element => { + diskDrives.forEach((element) => { const lines = element.split('\r\n'); const device = util.getValue(lines, 'DeviceID', ':'); let partitions = element.split('@{DeviceID='); if (partitions.length > 1) { partitions = partitions.slice(1); - partitions.forEach(partition => { + partitions.forEach((partition) => { result.push({ name: partition.split(';')[0].toUpperCase(), device }); }); } @@ -537,8 +596,10 @@ function getDevicesWin(diskDrives) { function matchDevicesWin(data, diskDrives) { const devices = getDevicesWin(diskDrives); - data.map(element => { - const filteresDevices = devices.filter((e) => { return e.name === element.name.toUpperCase(); }); + data.map((element) => { + const filteresDevices = devices.filter((e) => { + return e.name === element.name.toUpperCase(); + }); if (filteresDevices.length > 0) { element.device = filteresDevices[0].device; } @@ -548,7 +609,8 @@ function matchDevicesWin(data, diskDrives) { } function blkStdoutToObject(stdout) { - return stdout.toString() + return stdout + .toString() .replace(/NAME=/g, '{"name":') .replace(/FSTYPE=/g, ',"fsType":') .replace(/TYPE=/g, ',"type":') @@ -568,16 +630,15 @@ function blkStdoutToObject(stdout) { } function blockDevices(callback) { - return new Promise((resolve) => { process.nextTick(() => { let data = []; if (_linux) { // see https://wiki.ubuntuusers.de/lsblk/ // exec("lsblk -bo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,TRAN,SERIAL,LABEL,MODEL,OWNER,GROUP,MODE,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,SCHED,RQ-SIZE,RA,WSAME", function (error, stdout) { - const procLsblk1 = exec('lsblk -bPo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,RM,TRAN,SERIAL,LABEL,MODEL,OWNER 2>/dev/null', { maxBuffer: 1024 * 1024 }, function (error, stdout) { + const procLsblk1 = exec('lsblk -bPo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,RM,TRAN,SERIAL,LABEL,MODEL,OWNER 2>/dev/null', { maxBuffer: 1024 * 1024 }, (error, stdout) => { if (!error) { - let lines = blkStdoutToObject(stdout).split('\n'); + const lines = blkStdoutToObject(stdout).split('\n'); data = parseBlk(lines); data = raidMatchLinux(data); data = matchDevicesLinux(data); @@ -586,9 +647,9 @@ function blockDevices(callback) { } resolve(data); } else { - const procLsblk2 = exec('lsblk -bPo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,RM,LABEL,MODEL,OWNER 2>/dev/null', { maxBuffer: 1024 * 1024 }, function (error, stdout) { + const procLsblk2 = exec('lsblk -bPo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,RM,LABEL,MODEL,OWNER 2>/dev/null', { maxBuffer: 1024 * 1024 }, (error, stdout) => { if (!error) { - let lines = blkStdoutToObject(stdout).split('\n'); + const lines = blkStdoutToObject(stdout).split('\n'); data = parseBlk(lines); data = raidMatchLinux(data); } @@ -597,25 +658,25 @@ function blockDevices(callback) { } resolve(data); }); - procLsblk2.on('error', function () { + procLsblk2.on('error', () => { if (callback) { callback(data); } resolve(data); }); } }); - procLsblk1.on('error', function () { + procLsblk1.on('error', () => { if (callback) { callback(data); } resolve(data); }); } if (_darwin) { - const procDskutil = exec('diskutil info -all', { maxBuffer: 1024 * 1024 }, function (error, stdout) { + const procDskutil = exec('diskutil info -all', { maxBuffer: 1024 * 1024 }, (error, stdout) => { if (!error) { - let lines = stdout.toString().split('\n'); + const lines = stdout.toString().split('\n'); // parse lines into temp array of devices data = parseDevices(lines); data = matchDevicesMac(data); @@ -625,33 +686,37 @@ function blockDevices(callback) { } resolve(data); }); - procDskutil.on('error', function () { + procDskutil.on('error', () => { if (callback) { callback(data); } resolve(data); }); } if (_sunos) { - if (callback) { callback(data); } + if (callback) { + callback(data); + } resolve(data); } if (_windows) { - let drivetypes = ['Unknown', 'NoRoot', 'Removable', 'Local', 'Network', 'CD/DVD', 'RAM']; + const drivetypes = ['Unknown', 'NoRoot', 'Removable', 'Local', 'Network', 'CD/DVD', 'RAM']; try { // util.wmic('logicaldisk get Caption,Description,DeviceID,DriveType,FileSystem,FreeSpace,Name,Size,VolumeName,VolumeSerialNumber /value').then((stdout, error) => { // util.powerShell('Get-CimInstance Win32_logicaldisk | select Caption,DriveType,Name,FileSystem,Size,VolumeSerialNumber,VolumeName | fl').then((stdout, error) => { const workload = []; workload.push(util.powerShell('Get-CimInstance -ClassName Win32_LogicalDisk | select Caption,DriveType,Name,FileSystem,Size,VolumeSerialNumber,VolumeName | fl')); - workload.push(util.powerShell('Get-WmiObject -Class Win32_diskdrive | Select-Object -Property PNPDeviceId,DeviceID, Model, Size, @{L=\'Partitions\'; E={$_.GetRelated(\'Win32_DiskPartition\').GetRelated(\'Win32_LogicalDisk\') | Select-Object -Property DeviceID, VolumeName, Size, FreeSpace}} | fl')); - util.promiseAll( - workload - ).then((res) => { - let logicalDisks = res.results[0].toString().split(/\n\s*\n/); - let diskDrives = res.results[1].toString().split(/\n\s*\n/); - logicalDisks.forEach(function (device) { - let lines = device.split('\r\n'); - let drivetype = util.getValue(lines, 'drivetype', ':'); + workload.push( + util.powerShell( + "Get-WmiObject -Class Win32_diskdrive | Select-Object -Property PNPDeviceId,DeviceID, Model, Size, @{L='Partitions'; E={$_.GetRelated('Win32_DiskPartition').GetRelated('Win32_LogicalDisk') | Select-Object -Property DeviceID, VolumeName, Size, FreeSpace}} | fl" + ) + ); + util.promiseAll(workload).then((res) => { + const logicalDisks = res.results[0].toString().split(/\n\s*\n/); + const diskDrives = res.results[1].toString().split(/\n\s*\n/); + logicalDisks.forEach((device) => { + const lines = device.split('\r\n'); + const drivetype = util.getValue(lines, 'drivetype', ':'); if (drivetype) { data.push({ name: util.getValue(lines, 'name', ':'), @@ -660,7 +725,7 @@ function blockDevices(callback) { fsType: util.getValue(lines, 'filesystem', ':').toLowerCase(), mount: util.getValue(lines, 'caption', ':'), size: util.getValue(lines, 'size', ':'), - physical: (drivetype >= 0 && drivetype <= 6) ? drivetypes[drivetype] : drivetypes[0], + physical: drivetype >= 0 && drivetype <= 6 ? drivetypes[drivetype] : drivetypes[0], uuid: util.getValue(lines, 'volumeserialnumber', ':'), label: util.getValue(lines, 'volumename', ':'), model: '', @@ -679,17 +744,20 @@ function blockDevices(callback) { } resolve(data); }); - } catch (e) { - if (callback) { callback(data); } + } catch { + if (callback) { + callback(data); + } resolve(data); } } if (_freebsd || _openbsd || _netbsd) { // will follow - if (callback) { callback(null); } + if (callback) { + callback(null); + } resolve(null); } - }); }); } @@ -700,7 +768,7 @@ exports.blockDevices = blockDevices; // FS - speed function calcFsSpeed(rx, wx) { - let result = { + const result = { rx: 0, wx: 0, tx: 0, @@ -710,7 +778,7 @@ function calcFsSpeed(rx, wx) { ms: 0 }; - if (_fs_speed && _fs_speed.ms) { + if (_fs_speed?.ms) { result.rx = rx; result.wx = wx; result.tx = result.rx + result.wx; @@ -743,7 +811,6 @@ function calcFsSpeed(rx, wx) { } function fsStats(callback) { - return new Promise((resolve) => { process.nextTick(() => { if (_windows || _freebsd || _openbsd || _netbsd || _sunos) { @@ -762,31 +829,33 @@ function fsStats(callback) { let rx = 0; let wx = 0; - if ((_fs_speed && !_fs_speed.ms) || (_fs_speed && _fs_speed.ms && Date.now() - _fs_speed.ms >= 500)) { + if ((_fs_speed && !_fs_speed.ms) || (_fs_speed?.ms && Date.now() - _fs_speed.ms >= 500)) { if (_linux) { // exec("df -k | grep /dev/", function(error, stdout) { - const procLsblk = exec('lsblk -r 2>/dev/null | grep /', { maxBuffer: 1024 * 1024 }, function (error, stdout) { + const procLsblk = exec('lsblk -r 2>/dev/null | grep /', { maxBuffer: 1024 * 1024 }, (error, stdout) => { if (!error) { - let lines = stdout.toString().split('\n'); - let fs_filter = []; - lines.forEach(function (line) { + const lines = stdout.toString().split('\n'); + const fs_filter = []; + lines.forEach((line) => { if (line !== '') { line = line.trim().split(' '); - if (fs_filter.indexOf(line[0]) === -1) { fs_filter.push(line[0]); } + if (fs_filter.indexOf(line[0]) === -1) { + fs_filter.push(line[0]); + } } }); - let output = fs_filter.join('|'); - const procCat = exec('cat /proc/diskstats | egrep "' + output + '"', { maxBuffer: 1024 * 1024 }, function (error, stdout) { + const output = fs_filter.join('|'); + const procCat = exec('cat /proc/diskstats | egrep "' + output + '"', { maxBuffer: 1024 * 1024 }, (error, stdout) => { if (!error) { - let lines = stdout.toString().split('\n'); - lines.forEach(function (line) { + const lines = stdout.toString().split('\n'); + lines.forEach((line) => { line = line.trim(); if (line !== '') { line = line.replace(/ +/g, ' ').split(' '); - rx += parseInt(line[5]) * 512; - wx += parseInt(line[9]) * 512; + rx += parseInt(line[5], 10) * 512; + wx += parseInt(line[9], 10) * 512; } }); result = calcFsSpeed(rx, wx); @@ -796,7 +865,7 @@ function fsStats(callback) { } resolve(result); }); - procCat.on('error', function () { + procCat.on('error', () => { if (callback) { callback(result); } @@ -809,35 +878,38 @@ function fsStats(callback) { resolve(result); } }); - procLsblk.on('error', function () { + procLsblk.on('error', () => { if (callback) { callback(result); } resolve(result); }); - } if (_darwin) { - const procIoreg = exec('ioreg -c IOBlockStorageDriver -k Statistics -r -w0 | sed -n "/IOBlockStorageDriver/,/Statistics/p" | grep "Statistics" | tr -cd "01234567890,\n"', { maxBuffer: 1024 * 1024 }, function (error, stdout) { - if (!error) { - let lines = stdout.toString().split('\n'); - lines.forEach(function (line) { - line = line.trim(); - if (line !== '') { - line = line.split(','); - - rx += parseInt(line[2]); - wx += parseInt(line[9]); - } - }); - result = calcFsSpeed(rx, wx); - } - if (callback) { - callback(result); + const procIoreg = exec( + 'ioreg -c IOBlockStorageDriver -k Statistics -r -w0 | sed -n "/IOBlockStorageDriver/,/Statistics/p" | grep "Statistics" | tr -cd "01234567890,\n"', + { maxBuffer: 1024 * 1024 }, + (error, stdout) => { + if (!error) { + const lines = stdout.toString().split('\n'); + lines.forEach((line) => { + line = line.trim(); + if (line !== '') { + line = line.split(','); + + rx += parseInt(line[2], 10); + wx += parseInt(line[9], 10); + } + }); + result = calcFsSpeed(rx, wx); + } + if (callback) { + callback(result); + } + resolve(result); } - resolve(result); - }); - procIoreg.on('error', function () { + ); + procIoreg.on('error', () => { if (callback) { callback(result); } @@ -864,7 +936,7 @@ function fsStats(callback) { exports.fsStats = fsStats; function calcDiskIO(rIO, wIO, rWaitTime, wWaitTime, tWaitTime) { - let result = { + const result = { rIO: 0, wIO: 0, tIO: 0, @@ -879,7 +951,7 @@ function calcDiskIO(rIO, wIO, rWaitTime, wWaitTime, tWaitTime) { tWaitPercent: null, ms: 0 }; - if (_disk_io && _disk_io.ms) { + if (_disk_io?.ms) { result.rIO = rIO; result.wIO = wIO; result.tIO = rIO + wIO; @@ -890,9 +962,9 @@ function calcDiskIO(rIO, wIO, rWaitTime, wWaitTime, tWaitTime) { result.rWaitTime = rWaitTime; result.wWaitTime = wWaitTime; result.tWaitTime = tWaitTime; - result.rWaitPercent = (result.rWaitTime - _disk_io.rWaitTime) * 100 / (result.ms); - result.wWaitPercent = (result.wWaitTime - _disk_io.wWaitTime) * 100 / (result.ms); - result.tWaitPercent = (result.tWaitTime - _disk_io.tWaitTime) * 100 / (result.ms); + result.rWaitPercent = ((result.rWaitTime - _disk_io.rWaitTime) * 100) / result.ms; + result.wWaitPercent = ((result.wWaitTime - _disk_io.wWaitTime) * 100) / result.ms; + result.tWaitPercent = ((result.tWaitTime - _disk_io.tWaitTime) * 100) / result.ms; _disk_io.rIO = rIO; _disk_io.wIO = wIO; _disk_io.rIO_sec = result.rIO_sec; @@ -931,7 +1003,6 @@ function calcDiskIO(rIO, wIO, rWaitTime, wWaitTime, tWaitTime) { } function disksIO(callback) { - return new Promise((resolve) => { process.nextTick(() => { if (_windows) { @@ -962,27 +1033,30 @@ function disksIO(callback) { let wWaitTime = 0; let tWaitTime = 0; - if ((_disk_io && !_disk_io.ms) || (_disk_io && _disk_io.ms && Date.now() - _disk_io.ms >= 500)) { + if ((_disk_io && !_disk_io.ms) || (_disk_io?.ms && Date.now() - _disk_io.ms >= 500)) { if (_linux || _freebsd || _openbsd || _netbsd) { // prints Block layer statistics for all mounted volumes // var cmd = "for mount in `lsblk | grep / | sed -r 's/│ └─//' | cut -d ' ' -f 1`; do cat /sys/block/$mount/stat | sed -r 's/ +/;/g' | sed -r 's/^;//'; done"; // var cmd = "for mount in `lsblk | grep / | sed 's/[│└─├]//g' | awk '{$1=$1};1' | cut -d ' ' -f 1 | sort -u`; do cat /sys/block/$mount/stat | sed -r 's/ +/;/g' | sed -r 's/^;//'; done"; - let cmd = 'for mount in `lsblk 2>/dev/null | grep " disk " | sed "s/[│└─├]//g" | awk \'{$1=$1};1\' | cut -d " " -f 1 | sort -u`; do cat /sys/block/$mount/stat | sed -r "s/ +/;/g" | sed -r "s/^;//"; done'; + const cmd = + 'for mount in `lsblk 2>/dev/null | grep " disk " | sed "s/[│└─├]//g" | awk \'{$1=$1};1\' | cut -d " " -f 1 | sort -u`; do cat /sys/block/$mount/stat | sed -r "s/ +/;/g" | sed -r "s/^;//"; done'; - exec(cmd, { maxBuffer: 1024 * 1024 }, function (error, stdout) { + exec(cmd, { maxBuffer: 1024 * 1024 }, (error, stdout) => { if (!error) { - let lines = stdout.split('\n'); - lines.forEach(function (line) { + const lines = stdout.split('\n'); + lines.forEach((line) => { // ignore empty lines - if (!line) { return; } + if (!line) { + return; + } // sum r/wIO of all disks to compute all disks IO - let stats = line.split(';'); - rIO += parseInt(stats[0]); - wIO += parseInt(stats[4]); - rWaitTime += parseInt(stats[3]); - wWaitTime += parseInt(stats[7]); - tWaitTime += parseInt(stats[10]); + const stats = line.split(';'); + rIO += parseInt(stats[0], 10); + wIO += parseInt(stats[4], 10); + rWaitTime += parseInt(stats[3], 10); + wWaitTime += parseInt(stats[7], 10); + tWaitTime += parseInt(stats[10], 10); }); result = calcDiskIO(rIO, wIO, rWaitTime, wWaitTime, tWaitTime); @@ -999,25 +1073,29 @@ function disksIO(callback) { }); } if (_darwin) { - exec('ioreg -c IOBlockStorageDriver -k Statistics -r -w0 | sed -n "/IOBlockStorageDriver/,/Statistics/p" | grep "Statistics" | tr -cd "01234567890,\n"', { maxBuffer: 1024 * 1024 }, function (error, stdout) { - if (!error) { - let lines = stdout.toString().split('\n'); - lines.forEach(function (line) { - line = line.trim(); - if (line !== '') { - line = line.split(','); - - rIO += parseInt(line[10]); - wIO += parseInt(line[0]); - } - }); - result = calcDiskIO(rIO, wIO, rWaitTime, wWaitTime, tWaitTime); - } - if (callback) { - callback(result); + exec( + 'ioreg -c IOBlockStorageDriver -k Statistics -r -w0 | sed -n "/IOBlockStorageDriver/,/Statistics/p" | grep "Statistics" | tr -cd "01234567890,\n"', + { maxBuffer: 1024 * 1024 }, + (error, stdout) => { + if (!error) { + const lines = stdout.toString().split('\n'); + lines.forEach((line) => { + line = line.trim(); + if (line !== '') { + line = line.split(','); + + rIO += parseInt(line[10], 10); + wIO += parseInt(line[0], 10); + } + }); + result = calcDiskIO(rIO, wIO, rWaitTime, wWaitTime, tWaitTime); + } + if (callback) { + callback(result); + } + resolve(result); } - resolve(result); - }); + ); } } else { result.rIO = _disk_io.rIO; @@ -1045,7 +1123,6 @@ function disksIO(callback) { exports.disksIO = disksIO; function diskLayout(callback) { - function getVendorFromModel(model) { const diskManufacturers = [ { pattern: 'WESTERN.*', manufacturer: 'Western Digital' }, @@ -1078,24 +1155,25 @@ function diskLayout(callback) { { pattern: 'ECM.*', manufacturer: 'ECM' }, { pattern: 'INTEL.*', manufacturer: 'INTEL' }, { pattern: 'EVO.*', manufacturer: 'Samsung' }, - { pattern: 'APPLE.*', manufacturer: 'Apple' }, + { pattern: 'APPLE.*', manufacturer: 'Apple' } ]; let result = ''; if (model) { model = model.toUpperCase(); diskManufacturers.forEach((manufacturer) => { const re = RegExp(manufacturer.pattern); - if (re.test(model)) { result = manufacturer.manufacturer; } + if (re.test(model)) { + result = manufacturer.manufacturer; + } }); } return result; } return new Promise((resolve) => { process.nextTick(() => { - - const commitResult = res => { + const commitResult = (res) => { for (let i = 0; i < res.length; i++) { delete res[i].BSDName; } @@ -1105,30 +1183,50 @@ function diskLayout(callback) { resolve(res); }; - let result = []; + const result = []; let cmd = ''; if (_linux) { let cmdFullSmart = ''; - exec('export LC_ALL=C; lsblk -ablJO 2>/dev/null; unset LC_ALL', { maxBuffer: 1024 * 1024 }, function (error, stdout) { + exec('export LC_ALL=C; lsblk -ablJO 2>/dev/null; unset LC_ALL', { maxBuffer: 1024 * 1024 }, (error, stdout) => { if (!error) { try { const out = stdout.toString().trim(); let devices = []; try { const outJSON = JSON.parse(out); if (outJSON && {}.hasOwnProperty.call(outJSON, 'blockdevices')) { - devices = outJSON.blockdevices.filter(item => { return (item.type === 'disk') && item.size > 0 && (item.model !== null || (item.mountpoint === null && item.label === null && item.fstype === null && item.parttype === null && item.path && item.path.indexOf('/ram') !== 0 && item.path.indexOf('/loop') !== 0 && item['disc-max'] && item['disc-max'] !== 0)); }); + devices = outJSON.blockdevices.filter((item) => { + return ( + item.type === 'disk' && + item.size > 0 && + (item.model !== null || + (item.mountpoint === null && + item.label === null && + item.fstype === null && + item.parttype === null && + item.path && + item.path.indexOf('/ram') !== 0 && + item.path.indexOf('/loop') !== 0 && + item['disc-max'] && + item['disc-max'] !== 0)) + ); + }); } - } catch (e) { + } catch { // fallback to older version of lsblk try { - const out2 = execSync('export LC_ALL=C; lsblk -bPo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,RM,LABEL,MODEL,OWNER,GROUP 2>/dev/null; unset LC_ALL', util.execOptsLinux).toString(); - let lines = blkStdoutToObject(out2).split('\n'); + const out2 = execSync( + 'export LC_ALL=C; lsblk -bPo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,RM,LABEL,MODEL,OWNER,GROUP 2>/dev/null; unset LC_ALL', + util.execOptsLinux + ).toString(); + const lines = blkStdoutToObject(out2).split('\n'); const data = parseBlk(lines); - devices = data.filter(item => { return (item.type === 'disk') && item.size > 0 && ((item.model !== null && item.model !== '') || (item.mount === '' && item.label === '' && item.fsType === '')); }); - } catch (e) { + devices = data.filter((item) => { + return item.type === 'disk' && item.size > 0 && ((item.model !== null && item.model !== '') || (item.mount === '' && item.label === '' && item.fsType === '')); + }); + } catch { util.noop(); } } @@ -1137,8 +1235,10 @@ function diskLayout(callback) { const BSDName = '/dev/' + device.name; const logical = device.name; try { - mediumType = execSync('cat /sys/block/' + logical + '/queue/rotational 2>/dev/null', util.execOptsLinux).toString().split('\n')[0]; - } catch (e) { + mediumType = execSync('cat /sys/block/' + logical + '/queue/rotational 2>/dev/null', util.execOptsLinux) + .toString() + .split('\n')[0]; + } catch { util.noop(); } let interfaceType = device.tran ? device.tran.toUpperCase().trim() : ''; @@ -1148,7 +1248,18 @@ function diskLayout(callback) { } result.push({ device: BSDName, - type: (mediumType === '0' ? 'SSD' : (mediumType === '1' ? 'HD' : (mediumType === '2' ? 'NVMe' : (device.model && device.model.indexOf('SSD') > -1 ? 'SSD' : (device.model && device.model.indexOf('NVM') > -1 ? 'NVMe' : 'HD'))))), + type: + mediumType === '0' + ? 'SSD' + : mediumType === '1' + ? 'HD' + : mediumType === '2' + ? 'NVMe' + : device.model && device.model.indexOf('SSD') > -1 + ? 'SSD' + : device.model && device.model.indexOf('NVM') > -1 + ? 'NVMe' + : 'HD', name: device.model || '', vendor: getVendorFromModel(device.model) || (device.vendor ? device.vendor.trim() : ''), size: device.size || 0, @@ -1169,47 +1280,47 @@ function diskLayout(callback) { cmd += `printf "\n${BSDName}|"; smartctl -H ${BSDName} | grep overall;`; cmdFullSmart += `${cmdFullSmart ? 'printf ",";' : ''}smartctl -a -j ${BSDName};`; }); - } catch (e) { + } catch { util.noop(); } } // check S.M.A.R.T. status if (cmdFullSmart) { - exec(cmdFullSmart, { maxBuffer: 1024 * 1024 }, function (error, stdout) { + exec(cmdFullSmart, { maxBuffer: 1024 * 1024 }, (error, stdout) => { try { const data = JSON.parse(`[${stdout}]`); - data.forEach(disk => { + data.forEach((disk) => { const diskBSDName = disk.smartctl.argv[disk.smartctl.argv.length - 1]; for (let i = 0; i < result.length; i++) { if (result[i].BSDName === diskBSDName) { - result[i].smartStatus = (disk.smart_status.passed ? 'Ok' : (disk.smart_status.passed === false ? 'Predicted Failure' : 'unknown')); - if (disk.temperature && disk.temperature.current) { + result[i].smartStatus = disk.smart_status.passed ? 'Ok' : disk.smart_status.passed === false ? 'Predicted Failure' : 'unknown'; + if (disk.temperature?.current) { result[i].temperature = disk.temperature.current; } result[i].smartData = disk; } } }); commitResult(result); - } catch (e) { + } catch { if (cmd) { cmd = cmd + 'printf "\n"'; - exec(cmd, { maxBuffer: 1024 * 1024 }, function (error, stdout) { - let lines = stdout.toString().split('\n'); - lines.forEach(line => { + exec(cmd, { maxBuffer: 1024 * 1024 }, (error, stdout) => { + const lines = stdout.toString().split('\n'); + lines.forEach((line) => { if (line) { - let parts = line.split('|'); + const parts = line.split('|'); if (parts.length === 2) { - let BSDName = parts[0]; + const BSDName = parts[0]; parts[1] = parts[1].trim(); - let parts2 = parts[1].split(':'); + const parts2 = parts[1].split(':'); if (parts2.length === 2) { parts2[1] = parts2[1].trim(); - let status = parts2[1].toLowerCase(); + const status = parts2[1].toLowerCase(); for (let i = 0; i < result.length; i++) { if (result[i].BSDName === BSDName) { - result[i].smartStatus = (status === 'passed' ? 'Ok' : (status === 'failed!' ? 'Predicted Failure' : 'unknown')); + result[i].smartStatus = status === 'passed' ? 'Ok' : status === 'failed!' ? 'Predicted Failure' : 'unknown'; } } } @@ -1229,47 +1340,65 @@ function diskLayout(callback) { }); } if (_freebsd || _openbsd || _netbsd) { - if (callback) { callback(result); } + if (callback) { + callback(result); + } resolve(result); } if (_sunos) { - if (callback) { callback(result); } + if (callback) { + callback(result); + } resolve(result); } if (_darwin) { - exec('system_profiler SPSerialATADataType SPNVMeDataType SPUSBDataType', { maxBuffer: 1024 * 1024 }, function (error, stdout) { + exec('system_profiler SPSerialATADataType SPNVMeDataType SPUSBDataType', { maxBuffer: 1024 * 1024 }, (error, stdout) => { if (!error) { // split by type: - let lines = stdout.toString().split('\n'); - let linesSATA = []; - let linesNVMe = []; - let linesUSB = []; + const lines = stdout.toString().split('\n'); + const linesSATA = []; + const linesNVMe = []; + const linesUSB = []; let dataType = 'SATA'; - lines.forEach(line => { - if (line === 'NVMExpress:') { dataType = 'NVMe'; } - else if (line === 'USB:') { dataType = 'USB'; } - else if (line === 'SATA/SATA Express:') { dataType = 'SATA'; } - else if (dataType === 'SATA') { linesSATA.push(line); } - else if (dataType === 'NVMe') { linesNVMe.push(line); } - else if (dataType === 'USB') { linesUSB.push(line); } + lines.forEach((line) => { + if (line === 'NVMExpress:') { + dataType = 'NVMe'; + } else if (line === 'USB:') { + dataType = 'USB'; + } else if (line === 'SATA/SATA Express:') { + dataType = 'SATA'; + } else if (dataType === 'SATA') { + linesSATA.push(line); + } else if (dataType === 'NVMe') { + linesNVMe.push(line); + } else if (dataType === 'USB') { + linesUSB.push(line); + } }); try { // Serial ATA Drives - let devices = linesSATA.join('\n').split(' Physical Interconnect: '); + const devices = linesSATA.join('\n').split(' Physical Interconnect: '); devices.shift(); - devices.forEach(function (device) { + devices.forEach((device) => { device = 'InterfaceType: ' + device; - let lines = device.split('\n'); + const lines = device.split('\n'); const mediumType = util.getValue(lines, 'Medium Type', ':', true).trim(); const sizeStr = util.getValue(lines, 'capacity', ':', true).trim(); const BSDName = util.getValue(lines, 'BSD Name', ':', true).trim(); if (sizeStr) { let sizeValue = 0; if (sizeStr.indexOf('(') >= 0) { - sizeValue = parseInt(sizeStr.match(/\(([^)]+)\)/)[1].replace(/\./g, '').replace(/,/g, '').replace(/\s/g, '')); + sizeValue = parseInt( + sizeStr + .match(/\(([^)]+)\)/)[1] + .replace(/\./g, '') + .replace(/,/g, '') + .replace(/\s/g, ''), + 10 + ); } if (!sizeValue) { - sizeValue = parseInt(sizeStr); + sizeValue = parseInt(sizeStr, 10); } if (sizeValue) { const smartStatusString = util.getValue(lines, 'S.M.A.R.T. status', ':', true).trim().toLowerCase(); @@ -1297,27 +1426,34 @@ function diskLayout(callback) { } } }); - } catch (e) { + } catch { util.noop(); } // NVME Drives try { - let devices = linesNVMe.join('\n').split('\n\n Capacity:'); + const devices = linesNVMe.join('\n').split('\n\n Capacity:'); devices.shift(); - devices.forEach(function (device) { - device = '!Capacity: ' + device; - let lines = device.split('\n'); + devices.forEach((device) => { + device = `!Capacity: ${device}`; + const lines = device.split('\n'); const linkWidth = util.getValue(lines, 'link width', ':', true).trim(); const sizeStr = util.getValue(lines, '!capacity', ':', true).trim(); const BSDName = util.getValue(lines, 'BSD Name', ':', true).trim(); if (sizeStr) { let sizeValue = 0; if (sizeStr.indexOf('(') >= 0) { - sizeValue = parseInt(sizeStr.match(/\(([^)]+)\)/)[1].replace(/\./g, '').replace(/,/g, '').replace(/\s/g, '')); + sizeValue = parseInt( + sizeStr + .match(/\(([^)]+)\)/)[1] + .replace(/\./g, '') + .replace(/,/g, '') + .replace(/\s/g, ''), + 10 + ); } if (!sizeValue) { - sizeValue = parseInt(sizeStr); + sizeValue = parseInt(sizeStr, 10); } if (sizeValue) { const smartStatusString = util.getValue(lines, 'S.M.A.R.T. status', ':', true).trim().toLowerCase(); @@ -1341,28 +1477,35 @@ function diskLayout(callback) { temperature: null, BSDName: BSDName }); - cmd = cmd + 'printf "\n' + BSDName + '|"; diskutil info /dev/' + BSDName + ' | grep SMART;'; + cmd = `${cmd}printf "\n${BSDName}|"; diskutil info /dev/${BSDName} | grep SMART;`; } } }); - } catch (e) { + } catch { util.noop(); } // USB Drives try { - let devices = linesUSB.join('\n').replaceAll('Media:\n ', 'Model:').split('\n\n Product ID:'); + const devices = linesUSB.join('\n').replaceAll('Media:\n ', 'Model:').split('\n\n Product ID:'); devices.shift(); - devices.forEach(function (device) { - let lines = device.split('\n'); + devices.forEach((device) => { + const lines = device.split('\n'); const sizeStr = util.getValue(lines, 'Capacity', ':', true).trim(); const BSDName = util.getValue(lines, 'BSD Name', ':', true).trim(); if (sizeStr) { let sizeValue = 0; if (sizeStr.indexOf('(') >= 0) { - sizeValue = parseInt(sizeStr.match(/\(([^)]+)\)/)[1].replace(/\./g, '').replace(/,/g, '').replace(/\s/g, '')); + sizeValue = parseInt( + sizeStr + .match(/\(([^)]+)\)/)[1] + .replace(/\./g, '') + .replace(/,/g, '') + .replace(/\s/g, ''), + 10 + ); } if (!sizeValue) { - sizeValue = parseInt(sizeStr); + sizeValue = parseInt(sizeStr, 10); } if (sizeValue) { const smartStatusString = util.getValue(lines, 'S.M.A.R.T. status', ':', true).trim().toLowerCase(); @@ -1390,26 +1533,26 @@ function diskLayout(callback) { } } }); - } catch (e) { + } catch { util.noop(); } if (cmd) { cmd = cmd + 'printf "\n"'; - exec(cmd, { maxBuffer: 1024 * 1024 }, function (error, stdout) { - let lines = stdout.toString().split('\n'); - lines.forEach(line => { + exec(cmd, { maxBuffer: 1024 * 1024 }, (error, stdout) => { + const lines = stdout.toString().split('\n'); + lines.forEach((line) => { if (line) { - let parts = line.split('|'); + const parts = line.split('|'); if (parts.length === 2) { - let BSDName = parts[0]; + const BSDName = parts[0]; parts[1] = parts[1].trim(); - let parts2 = parts[1].split(':'); + const parts2 = parts[1].split(':'); if (parts2.length === 2) { parts2[1] = parts2[1].trim(); - let status = parts2[1].toLowerCase(); + const status = parts2[1].toLowerCase(); for (let i = 0; i < result.length; i++) { if (result[i].BSDName === BSDName) { - result[i].smartStatus = (status === 'not supported' ? 'not supported' : (status === 'verified' ? 'Ok' : (status === 'failing' ? 'Predicted Failure' : 'unknown'))); + result[i].smartStatus = status === 'not supported' ? 'not supported' : status === 'verified' ? 'Ok' : status === 'failing' ? 'Predicted Failure' : 'unknown'; } } } @@ -1429,69 +1572,79 @@ function diskLayout(callback) { if (_windows) { try { const workload = []; - workload.push(util.powerShell('Get-CimInstance Win32_DiskDrive | select Caption,Size,Status,PNPDeviceId,DeviceId,BytesPerSector,TotalCylinders,TotalHeads,TotalSectors,TotalTracks,TracksPerCylinder,SectorsPerTrack,FirmwareRevision,SerialNumber,InterfaceType | fl')); + workload.push( + util.powerShell( + 'Get-CimInstance Win32_DiskDrive | select Caption,Size,Status,PNPDeviceId,DeviceId,BytesPerSector,TotalCylinders,TotalHeads,TotalSectors,TotalTracks,TracksPerCylinder,SectorsPerTrack,FirmwareRevision,SerialNumber,InterfaceType | fl' + ) + ); workload.push(util.powerShell('Get-PhysicalDisk | select BusType,MediaType,FriendlyName,Model,SerialNumber,Size | fl')); if (util.smartMonToolsInstalled()) { try { const smartDev = JSON.parse(execSync('smartctl --scan -j').toString()); - if (smartDev && smartDev.devices && smartDev.devices.length > 0) { + if (smartDev?.devices && smartDev.devices.length > 0) { smartDev.devices.forEach((dev) => { workload.push(execPromiseSave(`smartctl -j -a ${dev.name}`, util.execOptsWin)); }); } - } catch (e) { + } catch { util.noop(); } } - util.promiseAll( - workload - ).then((data) => { + util.promiseAll(workload).then((data) => { let devices = data.results[0].toString().split(/\n\s*\n/); - devices.forEach(function (device) { - let lines = device.split('\r\n'); + devices.forEach((device) => { + const lines = device.split('\r\n'); const size = util.getValue(lines, 'Size', ':').trim(); const status = util.getValue(lines, 'Status', ':').trim().toLowerCase(); if (size) { result.push({ - device: util.getValue(lines, 'DeviceId', ':'), // changed from PNPDeviceId to DeviceID (be be able to match devices) - type: device.indexOf('SSD') > -1 ? 'SSD' : 'HD', // just a starting point ... better: MSFT_PhysicalDisk - Media Type ... see below + device: util.getValue(lines, 'DeviceId', ':'), // changed from PNPDeviceId to DeviceID (be be able to match devices) + type: device.indexOf('SSD') > -1 ? 'SSD' : 'HD', // just a starting point ... better: MSFT_PhysicalDisk - Media Type ... see below name: util.getValue(lines, 'Caption', ':'), vendor: getVendorFromModel(util.getValue(lines, 'Caption', ':', true).trim()), - size: parseInt(size), - ... [truncated]
lib/util.js+250 −171 modified@@ -22,12 +22,12 @@ const execSync = require('child_process').execSync; const util = require('util'); let _platform = process.platform; -const _linux = (_platform === 'linux' || _platform === 'android'); -const _darwin = (_platform === 'darwin'); -const _windows = (_platform === 'win32'); -const _freebsd = (_platform === 'freebsd'); -const _openbsd = (_platform === 'openbsd'); -const _netbsd = (_platform === 'netbsd'); +const _linux = _platform === 'linux' || _platform === 'android'; +const _darwin = _platform === 'darwin'; +const _windows = _platform === 'win32'; +const _freebsd = _platform === 'freebsd'; +const _openbsd = _platform === 'openbsd'; +const _netbsd = _platform === 'netbsd'; let _cores = 0; let wmicPath = ''; @@ -105,7 +105,9 @@ function unique(obj) { let stringify = {}; for (let i = 0; i < obj.length; i++) { let keys = Object.keys(obj[i]); - keys.sort(function (a, b) { return a - b; }); + keys.sort(function (a, b) { + return a - b; + }); let str = ''; for (let j = 0; j < keys.length; j++) { str += JSON.stringify(keys[j]); @@ -124,9 +126,10 @@ function sortByKey(array, keys) { let x = ''; let y = ''; keys.forEach(function (key) { - x = x + a[key]; y = y + b[key]; + x = x + a[key]; + y = y + b[key]; }); - return ((x < y) ? -1 : ((x > y) ? 1 : 0)); + return x < y ? -1 : x > y ? 1 : 0; }); } @@ -148,7 +151,7 @@ function getValue(lines, property, separator, trimmed, lineMatch) { if (trimmed) { lineLower = lineLower.trim(); } - if (lineLower.startsWith(property) && (lineMatch ? (lineLower.match(property + separator)) || (lineLower.match(property + ' ' + separator)) : true)) { + if (lineLower.startsWith(property) && (lineMatch ? lineLower.match(property + separator) || lineLower.match(property + ' ' + separator) : true)) { const parts = trimmed ? line.trim().split(separator) : line.split(separator); if (parts.length >= 2) { parts.shift(); @@ -170,11 +173,15 @@ function decodeEscapeSequence(str, base) { function detectSplit(str) { let seperator = ''; let part = 0; - str.split('').forEach(element => { + str.split('').forEach((element) => { if (element >= '0' && element <= '9') { - if (part === 1) { part++; } + if (part === 1) { + part++; + } } else { - if (part === 0) { part++; } + if (part === 0) { + part++; + } if (part === 1) { seperator += element; } @@ -194,7 +201,14 @@ function parseTime(t, pmDesignator) { if (parts[2]) { parts[1] += parts[2]; } - let isPM = (parts[1] && (parts[1].toLowerCase().indexOf('pm') > -1) || (parts[1].toLowerCase().indexOf('p.m.') > -1) || (parts[1].toLowerCase().indexOf('p. m.') > -1) || (parts[1].toLowerCase().indexOf('n') > -1) || (parts[1].toLowerCase().indexOf('ch') > -1) || (parts[1].toLowerCase().indexOf('ös') > -1) || (pmDesignator && parts[1].toLowerCase().indexOf(pmDesignator) > -1)); + let isPM = + (parts[1] && parts[1].toLowerCase().indexOf('pm') > -1) || + parts[1].toLowerCase().indexOf('p.m.') > -1 || + parts[1].toLowerCase().indexOf('p. m.') > -1 || + parts[1].toLowerCase().indexOf('n') > -1 || + parts[1].toLowerCase().indexOf('ch') > -1 || + parts[1].toLowerCase().indexOf('ös') > -1 || + (pmDesignator && parts[1].toLowerCase().indexOf(pmDesignator) > -1); hour = parseInt(parts[0], 10); min = parseInt(parts[1], 10); hour = isPM && hour < 12 ? hour + 12 : hour; @@ -209,7 +223,7 @@ function parseDateTime(dt, culture) { }; culture = culture || {}; let dateFormat = (culture.dateFormat || '').toLowerCase(); - let pmDesignator = (culture.pmDesignator || ''); + let pmDesignator = culture.pmDesignator || ''; const parts = dt.split(' '); if (parts[0]) { @@ -221,7 +235,7 @@ function parseDateTime(dt, culture) { // Dateformat: yyyy/mm/dd result.date = dtparts[0] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[2]).substr(-2); } else if (dtparts[2].length === 2) { - if ((dateFormat.indexOf('/d/') > -1 || dateFormat.indexOf('/dd/') > -1)) { + if (dateFormat.indexOf('/d/') > -1 || dateFormat.indexOf('/dd/') > -1) { // Dateformat: mm/dd/yy result.date = '20' + dtparts[2] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[0]).substr(-2); } else { @@ -230,7 +244,13 @@ function parseDateTime(dt, culture) { } } else { // Dateformat: mm/dd/yyyy or dd/mm/yyyy - const isEN = ((dt.toLowerCase().indexOf('pm') > -1) || (dt.toLowerCase().indexOf('p.m.') > -1) || (dt.toLowerCase().indexOf('p. m.') > -1) || (dt.toLowerCase().indexOf('am') > -1) || (dt.toLowerCase().indexOf('a.m.') > -1) || (dt.toLowerCase().indexOf('a. m.') > -1)); + const isEN = + dt.toLowerCase().indexOf('pm') > -1 || + dt.toLowerCase().indexOf('p.m.') > -1 || + dt.toLowerCase().indexOf('p. m.') > -1 || + dt.toLowerCase().indexOf('am') > -1 || + dt.toLowerCase().indexOf('a.m.') > -1 || + dt.toLowerCase().indexOf('a. m.') > -1; if ((isEN || dateFormat.indexOf('/d/') > -1 || dateFormat.indexOf('/dd/') > -1) && dateFormat.indexOf('dd/') !== 0) { // Dateformat: mm/dd/yyyy result.date = dtparts[2] + '-' + ('0' + dtparts[0]).substr(-2) + '-' + ('0' + dtparts[1]).substr(-2); @@ -270,7 +290,7 @@ function parseDateTime(dt, culture) { } function parseHead(head, rights) { - let space = (rights > 0); + let space = rights > 0; let count = 1; let from = 0; let to = 0; @@ -366,7 +386,7 @@ function wmic(command) { return new Promise((resolve) => { process.nextTick(() => { try { - powerShell(getWmic() + ' ' + command).then(stdout => { + powerShell(getWmic() + ' ' + command).then((stdout) => { resolve(stdout, ''); }); } catch (e) { @@ -435,7 +455,9 @@ function powerShellStart() { powerShellProceedResults(_psResult + _psError); }); _psChild.on('close', function () { - if (_psChild) { _psChild.kill(); } + if (_psChild) { + _psChild.kill(); + } }); } } @@ -449,13 +471,14 @@ function powerShellRelease() { _psPersistent = false; } } catch (e) { - if (_psChild) { _psChild.kill(); } + if (_psChild) { + _psChild.kill(); + } } _psChild = null; } function powerShell(cmd) { - /// const pattern = [ /// '[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)', /// '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))' @@ -483,7 +506,6 @@ function powerShell(cmd) { } }); }); - } else { let result = ''; @@ -640,17 +662,7 @@ function smartMonToolsInstalled() { // https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#hardware-revision-codes function isRaspberry(cpuinfo) { - const PI_MODEL_NO = [ - 'BCM2708', - 'BCM2709', - 'BCM2710', - 'BCM2711', - 'BCM2712', - 'BCM2835', - 'BCM2836', - 'BCM2837', - 'BCM2837B0' - ]; + const PI_MODEL_NO = ['BCM2708', 'BCM2709', 'BCM2710', 'BCM2711', 'BCM2712', 'BCM2835', 'BCM2836', 'BCM2837', 'BCM2837B0']; if (_rpi_cpuinfo !== null) { cpuinfo = _rpi_cpuinfo; } else if (cpuinfo === undefined) { @@ -664,7 +676,7 @@ function isRaspberry(cpuinfo) { const hardware = getValue(cpuinfo, 'hardware'); const model = getValue(cpuinfo, 'model'); - return ((hardware && PI_MODEL_NO.indexOf(hardware) > -1) || (model && model.indexOf('Raspberry Pi') > -1)); + return (hardware && PI_MODEL_NO.indexOf(hardware) > -1) || (model && model.indexOf('Raspberry Pi') > -1); } function isRaspbian() { @@ -675,7 +687,7 @@ function isRaspbian() { return false; } const id = getValue(osrelease, 'id', '='); - return (id && id.indexOf('raspbian') > -1); + return id && id.indexOf('raspbian') > -1; } function execWin(cmd, opts, callback) { @@ -693,7 +705,7 @@ function darwinXcodeExists() { const cmdLineToolsExists = fs.existsSync('/Library/Developer/CommandLineTools/usr/bin/'); const xcodeAppExists = fs.existsSync('/Applications/Xcode.app/Contents/Developer/Tools'); const xcodeExists = fs.existsSync('/Library/Developer/Xcode/'); - return (cmdLineToolsExists || xcodeExists || xcodeAppExists); + return cmdLineToolsExists || xcodeExists || xcodeAppExists; } function nanoSeconds() { @@ -707,7 +719,7 @@ function nanoSeconds() { function countUniqueLines(lines, startingWith) { startingWith = startingWith || ''; const uniqueLines = []; - lines.forEach(line => { + lines.forEach((line) => { if (line.startsWith(startingWith)) { if (uniqueLines.indexOf(line) === -1) { uniqueLines.push(line); @@ -720,7 +732,7 @@ function countUniqueLines(lines, startingWith) { function countLines(lines, startingWith) { startingWith = startingWith || ''; const uniqueLines = []; - lines.forEach(line => { + lines.forEach((line) => { if (line.startsWith(startingWith)) { uniqueLines.push(line); } @@ -729,40 +741,46 @@ function countLines(lines, startingWith) { } function sanitizeShellString(str, strict) { - if (typeof strict === 'undefined') { strict = false; } + if (typeof strict === 'undefined') { + strict = false; + } const s = str || ''; let result = ''; const l = mathMin(s.length, 2000); for (let i = 0; i <= l; i++) { - if (!(s[i] === undefined || - s[i] === '>' || - s[i] === '<' || - s[i] === '*' || - s[i] === '?' || - s[i] === '[' || - s[i] === ']' || - s[i] === '|' || - s[i] === '˚' || - s[i] === '$' || - s[i] === ';' || - s[i] === '&' || - s[i] === ']' || - s[i] === '#' || - s[i] === '\\' || - s[i] === '\t' || - s[i] === '\n' || - s[i] === '\r' || - s[i] === '\'' || - s[i] === '`' || - s[i] === '"' || - s[i].length > 1 || - (strict && s[i] === '(') || - (strict && s[i] === ')') || - (strict && s[i] === '@') || - (strict && s[i] === ' ') || - (strict && s[i] == '{') || - (strict && s[i] == ';') || - (strict && s[i] == '}'))) { + if ( + !( + s[i] === undefined || + s[i] === '>' || + s[i] === '<' || + s[i] === '*' || + s[i] === '?' || + s[i] === '[' || + s[i] === ']' || + s[i] === '|' || + s[i] === '˚' || + s[i] === '$' || + s[i] === ';' || + s[i] === '&' || + s[i] === ']' || + s[i] === '#' || + s[i] === '\\' || + s[i] === '\t' || + s[i] === '\n' || + s[i] === '\r' || + s[i] === "'" || + s[i] === '`' || + s[i] === '"' || + s[i].length > 1 || + (strict && s[i] === '(') || + (strict && s[i] === ')') || + (strict && s[i] === '@') || + (strict && s[i] === ' ') || + (strict && s[i] === '{') || + (strict && s[i] === ';') || + (strict && s[i] === '}') + ) + ) { result = result + s[i]; } } @@ -785,18 +803,18 @@ function isPrototypePolluted() { } catch (e) { Object.setPrototypeOf(st, stringObj); } - notPolluted = notPolluted || (s.length !== 62); + notPolluted = notPolluted || s.length !== 62; const ms = Date.now(); if (typeof ms === 'number' && ms > 1600000000000) { - const l = ms % 100 + 15; + const l = (ms % 100) + 15; for (let i = 0; i < l; i++) { const r = Math.random() * 61.99999999 + 1; const rs = parseInt(Math.floor(r).toString(), 10); const rs2 = parseInt(r.toString().split('.')[0], 10); const q = Math.random() * 61.99999999 + 1; const qs = parseInt(Math.floor(q).toString(), 10); const qs2 = parseInt(q.toString().split('.')[0], 10); - notPolluted = notPolluted && (r !== q); + notPolluted = notPolluted && r !== q; notPolluted = notPolluted && rs === rs2 && qs === qs2; st += s[rs - 1]; } @@ -826,7 +844,7 @@ function isPrototypePolluted() { // lower const stl = st.toLowerCase(); - notPolluted = notPolluted && (stl.length === l) && stl[l - 1] && !(stl[l]); + notPolluted = notPolluted && stl.length === l && stl[l - 1] && !stl[l]; for (let i = 0; i < l; i++) { const s1 = st[i]; try { @@ -836,14 +854,14 @@ function isPrototypePolluted() { } const s2 = stl ? stl[i] : ''; const s1l = s1.toLowerCase(); - notPolluted = notPolluted && s1l[0] === s2 && s1l[0] && !(s1l[1]); + notPolluted = notPolluted && s1l[0] === s2 && s1l[0] && !s1l[1]; } } return !notPolluted; } function hex2bin(hex) { - return ('00000000' + (parseInt(hex, 16)).toString(2)).substr(-8); + return ('00000000' + parseInt(hex, 16).toString(2)).substr(-8); } function getFilesInPath(source) { @@ -854,21 +872,35 @@ function getFilesInPath(source) { function isDirectory(source) { return lstatSync(source).isDirectory(); } - function isFile(source) { return lstatSync(source).isFile(); } + function isFile(source) { + return lstatSync(source).isFile(); + } function getDirectories(source) { - return readdirSync(source).map(function (name) { return join(source, name); }).filter(isDirectory); + return readdirSync(source) + .map(function (name) { + return join(source, name); + }) + .filter(isDirectory); } function getFiles(source) { - return readdirSync(source).map(function (name) { return join(source, name); }).filter(isFile); + return readdirSync(source) + .map(function (name) { + return join(source, name); + }) + .filter(isFile); } function getFilesRecursively(source) { try { let dirs = getDirectories(source); let files = dirs - .map(function (dir) { return getFilesRecursively(dir); }) - .reduce(function (a, b) { return a.concat(b); }, []); + .map(function (dir) { + return getFilesRecursively(dir); + }) + .reduce(function (a, b) { + return a.concat(b); + }, []); return files.concat(getFiles(source)); } catch (e) { return []; @@ -883,7 +915,6 @@ function getFilesInPath(source) { } function decodePiCpuinfo(lines) { - if (_rpi_cpuinfo === null) { _rpi_cpuinfo = lines; } else if (lines === undefined) { @@ -1014,21 +1045,8 @@ function decodePiCpuinfo(lines) { } }; - const processorList = [ - 'BCM2835', - 'BCM2836', - 'BCM2837', - 'BCM2711', - 'BCM2712', - ]; - const manufacturerList = [ - 'Sony UK', - 'Egoman', - 'Embest', - 'Sony Japan', - 'Embest', - 'Stadium' - ]; + const processorList = ['BCM2835', 'BCM2836', 'BCM2837', 'BCM2711', 'BCM2712']; + const manufacturerList = ['Sony UK', 'Egoman', 'Embest', 'Sony Japan', 'Embest', 'Stadium']; const typeList = { '00': 'A', '01': 'B', @@ -1044,17 +1062,17 @@ function decodePiCpuinfo(lines) { '0d': '3B+', '0e': '3A+', '0f': 'Internal use only', - '10': 'CM3+', - '11': '4B', - '12': 'Zero 2 W', - '13': '400', - '14': 'CM4', - '15': 'CM4S', - '16': 'Internal use only', - '17': '5', - '18': 'CM5', - '19': '500/500+', - '1a': 'CM5 Lite', + 10: 'CM3+', + 11: '4B', + 12: 'Zero 2 W', + 13: '400', + 14: 'CM4', + 15: 'CM4S', + 16: 'Internal use only', + 17: '5', + 18: 'CM5', + 19: '500/500+', + '1a': 'CM5 Lite' }; const revisionCode = getValue(lines, 'revision', ':', true); @@ -1072,9 +1090,8 @@ function decodePiCpuinfo(lines) { manufacturer: oldRevisionCodes[revisionCode].manufacturer, processor: oldRevisionCodes[revisionCode].processor, type: oldRevisionCodes[revisionCode].type, - revision: oldRevisionCodes[revisionCode].revision, + revision: oldRevisionCodes[revisionCode].revision }; - } else { // new revision code const revision = ('00000000' + getValue(lines, 'revision', ':', true).toLowerCase()).substr(-8); @@ -1083,7 +1100,6 @@ function decodePiCpuinfo(lines) { const processor = processorList[parseInt(revision.substr(4, 1), 10)]; const typeCode = revision.substr(5, 2); - result = { model, serial, @@ -1092,14 +1108,13 @@ function decodePiCpuinfo(lines) { manufacturer, processor, type: {}.hasOwnProperty.call(typeList, typeCode) ? typeList[typeCode] : '', - revision: '1.' + revision.substr(7, 1), + revision: '1.' + revision.substr(7, 1) }; } return result; } function getRpiGpu(cpuinfo) { - if (_rpi_cpuinfo === null && cpuinfo !== undefined) { _rpi_cpuinfo = cpuinfo; } else if (cpuinfo === undefined && _rpi_cpuinfo !== null) { @@ -1114,18 +1129,23 @@ function getRpiGpu(cpuinfo) { } const rpi = decodePiCpuinfo(cpuinfo); - if (rpi.type === '4B' || rpi.type === 'CM4' || rpi.type === 'CM4S' || rpi.type === '400') { return 'VideoCore VI'; } - if (rpi.type === '5' || rpi.type === '500') { return 'VideoCore VII'; } + if (rpi.type === '4B' || rpi.type === 'CM4' || rpi.type === 'CM4S' || rpi.type === '400') { + return 'VideoCore VI'; + } + if (rpi.type === '5' || rpi.type === '500') { + return 'VideoCore VII'; + } return 'VideoCore IV'; } function promiseAll(promises) { const resolvingPromises = promises.map(function (promise) { return new Promise(function (resolve) { let payload = new Array(2); - promise.then(function (result) { - payload[0] = result; - }) + promise + .then(function (result) { + payload[0] = result; + }) .catch(function (error) { payload[1] = error; }) @@ -1139,23 +1159,22 @@ function promiseAll(promises) { const results = []; // Execute all wrapped Promises - return Promise.all(resolvingPromises) - .then(function (items) { - items.forEach(function (payload) { - if (payload[1]) { - errors.push(payload[1]); - results.push(null); - } else { - errors.push(null); - results.push(payload[0]); - } - }); - - return { - errors: errors, - results: results - }; + return Promise.all(resolvingPromises).then(function (items) { + items.forEach(function (payload) { + if (payload[1]) { + errors.push(payload[1]); + results.push(null); + } else { + errors.push(null); + results.push(payload[0]); + } }); + + return { + errors: errors, + results: results + }; + }); } function promisify(nodeStyleFunction) { @@ -1218,24 +1237,50 @@ function plistParser(xmlStr) { while (pos < len) { c = cn; - if (pos + 1 < len) { cn = xmlStr[pos + 1]; } + if (pos + 1 < len) { + cn = xmlStr[pos + 1]; + } if (c === '<') { inTagContent = false; - if (cn === '/') { inTagEnd = true; } - else if (metaData[depth].tagStart) { + if (cn === '/') { + inTagEnd = true; + } else if (metaData[depth].tagStart) { metaData[depth].tagContent = ''; - if (!metaData[depth].data) { metaData[depth].data = metaData[depth].tagStart === 'array' ? [] : {}; } + if (!metaData[depth].data) { + metaData[depth].data = metaData[depth].tagStart === 'array' ? [] : {}; + } depth++; metaData.push({ tagStart: '', tagEnd: '', tagContent: '', key: null, data: null }); inTagStart = true; inTagContent = false; + } else if (!inTagStart) { + inTagStart = true; } - else if (!inTagStart) { inTagStart = true; } } else if (c === '>') { - if (metaData[depth].tagStart === 'true/') { inTagStart = false; inTagEnd = true; metaData[depth].tagStart = ''; metaData[depth].tagEnd = '/boolean'; metaData[depth].data = true; } - if (metaData[depth].tagStart === 'false/') { inTagStart = false; inTagEnd = true; metaData[depth].tagStart = ''; metaData[depth].tagEnd = '/boolean'; metaData[depth].data = false; } - if (metaData[depth].tagStart === 'array/') { inTagStart = false; inTagEnd = true; metaData[depth].tagStart = ''; metaData[depth].tagEnd = '/arrayEmpty'; metaData[depth].data = []; } - if (inTagContent) { inTagContent = false; } + if (metaData[depth].tagStart === 'true/') { + inTagStart = false; + inTagEnd = true; + metaData[depth].tagStart = ''; + metaData[depth].tagEnd = '/boolean'; + metaData[depth].data = true; + } + if (metaData[depth].tagStart === 'false/') { + inTagStart = false; + inTagEnd = true; + metaData[depth].tagStart = ''; + metaData[depth].tagEnd = '/boolean'; + metaData[depth].data = false; + } + if (metaData[depth].tagStart === 'array/') { + inTagStart = false; + inTagEnd = true; + metaData[depth].tagStart = ''; + metaData[depth].tagEnd = '/arrayEmpty'; + metaData[depth].data = []; + } + if (inTagContent) { + inTagContent = false; + } if (inTagStart) { inTagStart = false; inTagContent = true; @@ -1261,18 +1306,31 @@ function plistParser(xmlStr) { metaData[depth].tagContent = ''; metaData[depth].tagStart = ''; metaData[depth].tagEnd = ''; - } - else { + } else { if (metaData[depth].tagEnd === '/key' && metaData[depth].tagContent) { metaData[depth].key = metaData[depth].tagContent; } else { - if (metaData[depth].tagEnd === '/real' && metaData[depth].tagContent) { metaData[depth].data = parseFloat(metaData[depth].tagContent) || 0; } - if (metaData[depth].tagEnd === '/integer' && metaData[depth].tagContent) { metaData[depth].data = parseInt(metaData[depth].tagContent) || 0; } - if (metaData[depth].tagEnd === '/string' && metaData[depth].tagContent) { metaData[depth].data = metaData[depth].tagContent || ''; } - if (metaData[depth].tagEnd === '/boolean') { metaData[depth].data = metaData[depth].tagContent || false; } - if (metaData[depth].tagEnd === '/arrayEmpty') { metaData[depth].data = metaData[depth].tagContent || []; } - if (depth > 0 && metaData[depth - 1].tagStart === 'array') { metaData[depth - 1].data.push(metaData[depth].data); } - if (depth > 0 && metaData[depth - 1].tagStart === 'dict') { metaData[depth - 1].data[metaData[depth].key] = metaData[depth].data; } + if (metaData[depth].tagEnd === '/real' && metaData[depth].tagContent) { + metaData[depth].data = parseFloat(metaData[depth].tagContent) || 0; + } + if (metaData[depth].tagEnd === '/integer' && metaData[depth].tagContent) { + metaData[depth].data = parseInt(metaData[depth].tagContent) || 0; + } + if (metaData[depth].tagEnd === '/string' && metaData[depth].tagContent) { + metaData[depth].data = metaData[depth].tagContent || ''; + } + if (metaData[depth].tagEnd === '/boolean') { + metaData[depth].data = metaData[depth].tagContent || false; + } + if (metaData[depth].tagEnd === '/arrayEmpty') { + metaData[depth].data = metaData[depth].tagContent || []; + } + if (depth > 0 && metaData[depth - 1].tagStart === 'array') { + metaData[depth - 1].data.push(metaData[depth].data); + } + if (depth > 0 && metaData[depth - 1].tagStart === 'dict') { + metaData[depth - 1].data[metaData[depth].key] = metaData[depth].data; + } } metaData[depth].tagContent = ''; metaData[depth].tagStart = ''; @@ -1284,9 +1342,15 @@ function plistParser(xmlStr) { inTagContent = false; } } else { - if (inTagStart) { metaData[depth].tagStart += c; } - if (inTagEnd) { metaData[depth].tagEnd += c; } - if (inTagContent) { metaData[depth].tagContent += c; } + if (inTagStart) { + metaData[depth].tagStart += c; + } + if (inTagEnd) { + metaData[depth].tagEnd += c; + } + if (inTagContent) { + metaData[depth].tagContent += c; + } } pos++; } @@ -1340,15 +1404,22 @@ function semverCompare(v1, v2) { let res = 0; const parts1 = v1.split('.'); const parts2 = v2.split('.'); - if (parts1[0] < parts2[0]) { res = 1; } - else if (parts1[0] > parts2[0]) { res = -1; } - else if (parts1[0] === parts2[0] && parts1.length >= 2 && parts2.length >= 2) { - if (parts1[1] < parts2[1]) { res = 1; } - else if (parts1[1] > parts2[1]) { res = -1; } - else if (parts1[1] === parts2[1]) { + if (parts1[0] < parts2[0]) { + res = 1; + } else if (parts1[0] > parts2[0]) { + res = -1; + } else if (parts1[0] === parts2[0] && parts1.length >= 2 && parts2.length >= 2) { + if (parts1[1] < parts2[1]) { + res = 1; + } else if (parts1[1] > parts2[1]) { + res = -1; + } else if (parts1[1] === parts2[1]) { if (parts1.length >= 3 && parts2.length >= 3) { - if (parts1[2] < parts2[2]) { res = 1; } - else if (parts1[2] > parts2[2]) { res = -1; } + if (parts1[2] < parts2[2]) { + res = 1; + } else if (parts1[2] > parts2[2]) { + res = -1; + } } else if (parts2.length >= 3) { res = 1; } @@ -2522,10 +2593,18 @@ function getAppleModel(key) { }; } const features = []; - if (list[0].size) { features.push(list[0].size); } - if (list[0].processor) { features.push(list[0].processor); } - if (list[0].year) { features.push(list[0].year); } - if (list[0].additional) { features.push(list[0].additional); } + if (list[0].size) { + features.push(list[0].size); + } + if (list[0].processor) { + features.push(list[0].processor); + } + if (list[0].year) { + features.push(list[0].year); + } + if (list[0].additional) { + features.push(list[0].additional); + } return { key: key, model: list[0].name, @@ -2534,12 +2613,12 @@ function getAppleModel(key) { } function checkWebsite(url, timeout = 5000) { - const http = ((url.startsWith('https:') || url.indexOf(':443/') > 0 || url.indexOf(':8443/') > 0) ? require('https') : require('http')); + const http = url.startsWith('https:') || url.indexOf(':443/') > 0 || url.indexOf(':8443/') > 0 ? require('https') : require('http'); const t = Date.now(); return new Promise((resolve) => { const request = http .get(url, function (res) { - res.on('data', () => { }); + res.on('data', () => {}); res.on('end', () => { resolve({ url, @@ -2549,7 +2628,7 @@ function checkWebsite(url, timeout = 5000) { }); }); }) - .on("error", function (e) { + .on('error', function (e) { resolve({ url, statusCode: 404, @@ -2567,12 +2646,12 @@ function checkWebsite(url, timeout = 5000) { }); }); }); -}; +} function cleanString(str) { return str.replace(/To Be Filled By O.E.M./g, ''); } -function noop() { } +function noop() {} exports.toInt = toInt; exports.splitByNumber = splitByNumber;
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-wphj-fx3q-84chghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-68154ghsaADVISORY
- github.com/sebhildebrandt/systeminformation/commit/c52f9fd07fef42d2d8e8c66f75b42178da701c68ghsax_refsource_MISCWEB
- github.com/sebhildebrandt/systeminformation/security/advisories/GHSA-wphj-fx3q-84chghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.