1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276 |
- 'use strict';
- // @ts-check
- // ==================================================================================
- // filesystem.js
- // ----------------------------------------------------------------------------------
- // Description: System Information - library
- // for Node.js
- // Copyright: (c) 2014 - 2022
- // Author: Sebastian Hildebrandt
- // ----------------------------------------------------------------------------------
- // License: MIT
- // ==================================================================================
- // 8. File System
- // ----------------------------------------------------------------------------------
- const util = require('./util');
- const fs = require('fs');
- 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 _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 = {};
- // --------------------------
- // FS - mounted file systems
- function fsSize(callback) {
- let macOsDisks = [];
- function getmacOsFsType(fs) {
- 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'; }
- return 'HFS';
- }
- function parseDf(lines) {
- let data = [];
- lines.forEach(function (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))) {
- 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 use = parseFloat((100.0 * (used / (used + available))).toFixed(2));
- line.splice(0, (_linux || _freebsd || _openbsd || _netbsd) ? 6 : 5);
- const mount = line.join(' ');
- // const mount = line[line.length - 1];
- if (!data.find(el => (el.fs === fs && el.type === fsType))) {
- data.push({
- fs,
- type: fsType,
- size,
- used,
- available,
- use,
- mount
- });
- }
- }
- }
- });
- return data;
- }
- return new Promise((resolve) => {
- process.nextTick(() => {
- let data = [];
- if (_linux || _freebsd || _openbsd || _netbsd || _darwin) {
- let cmd = '';
- if (_darwin) {
- cmd = 'df -kP';
- try {
- macOsDisks = execSync('diskutil list').toString().split('\n').filter(line => {
- return !line.startsWith('/') && line.indexOf(':') > 0;
- });
- } catch (e) {
- macOsDisks = [];
- }
- }
- if (_linux) { cmd = 'df -lkPTx squashfs | grep -E "^/|^.\\:"'; }
- if (_freebsd || _openbsd || _netbsd) { cmd = 'df -lkPT'; }
- exec(cmd, { maxBuffer: 1024 * 1024 }, function (error, stdout) {
- if (!error) {
- let lines = stdout.toString().split('\n');
- data = parseDf(lines);
- if (callback) {
- callback(data);
- }
- resolve(data);
- } else {
- exec('df -kPT', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
- if (!error) {
- let lines = stdout.toString().split('\n');
- data = parseDf(lines);
- }
- if (callback) {
- callback(data);
- }
- resolve(data);
- });
- }
- });
- }
- if (_sunos) {
- if (callback) { callback(data); }
- resolve(data);
- }
- if (_windows) {
- try {
- // util.wmic('logicaldisk get Caption,FileSystem,FreeSpace,Size').then((stdout) => {
- util.powerShell('Get-WmiObject Win32_logicaldisk | select Caption,FileSystem,FreeSpace,Size | fl').then((stdout, error) => {
- if (!error) {
- let devices = stdout.toString().split(/\n\s*\n/);
- devices.forEach(function (device) {
- let 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', ':');
- if (size) {
- data.push({
- fs: caption,
- type: util.getValue(lines, 'filesystem', ':'),
- size,
- used: size - free,
- available: free,
- use: parseFloat(((100.0 * (size - free)) / size).toFixed(2)),
- mount: caption
- });
- }
- });
- }
- if (callback) {
- callback(data);
- }
- resolve(data);
- });
- } catch (e) {
- if (callback) { callback(data); }
- resolve(data);
- }
- }
- });
- });
- }
- exports.fsSize = fsSize;
- // --------------------------
- // FS - open files count
- function fsOpenFiles(callback) {
- return new Promise((resolve) => {
- process.nextTick(() => {
- const result = {
- max: null,
- allocated: null,
- 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) {
- if (!error) {
- let 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;
- }
- if (callback) {
- callback(result);
- }
- resolve(result);
- });
- }
- if (_linux) {
- fs.readFile('/proc/sys/fs/file-nr', function (error, stdout) {
- if (!error) {
- let 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 (callback) {
- callback(result);
- }
- resolve(result);
- } else {
- fs.readFile('/proc/sys/fs/file-max', function (error, stdout) {
- if (!error) {
- let lines = stdout.toString().split('\n');
- if (lines[0]) {
- result.max = parseInt(lines[0], 10);
- }
- }
- if (callback) {
- callback(result);
- }
- resolve(result);
- });
- }
- });
- }
- if (_sunos) {
- if (callback) { callback(null); }
- resolve(null);
- }
- if (_windows) {
- if (callback) { callback(null); }
- resolve(null);
- }
- });
- });
- }
- exports.fsOpenFiles = fsOpenFiles;
- // --------------------------
- // disks
- function parseBytes(s) {
- return parseInt(s.substr(s.indexOf(' (') + 2, s.indexOf(' Bytes)') - 10));
- }
- function parseDevices(lines) {
- let devices = [];
- let i = 0;
- lines.forEach(line => {
- if (line.length > 0) {
- if (line[0] === '*') {
- i++;
- } else {
- let parts = line.split(':');
- if (parts.length > 1) {
- if (!devices[i]) {
- devices[i] = {
- name: '',
- identifier: '',
- type: 'disk',
- fsType: '',
- mount: '',
- size: 0,
- physical: 'HDD',
- uuid: '',
- label: '',
- model: '',
- serial: '',
- removable: false,
- protocol: ''
- };
- }
- 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 ('VOLUMENAME' === parts[0]) {
- 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]; }
- }
- }
- }
- });
- return devices;
- }
- 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,
- 'serial': disk.serial,
- 'removable': disk.rm === '1',
- 'protocol': disk.tran,
- 'group': disk.group,
- });
- } catch (e) {
- util.noop();
- }
- });
- data = util.unique(data);
- data = util.sortByKey(data, ['type', 'name']);
- return data;
- }
- function blkStdoutToObject(stdout) {
- return stdout.toString()
- .replace(/NAME=/g, '{"name":')
- .replace(/FSTYPE=/g, ',"fsType":')
- .replace(/TYPE=/g, ',"type":')
- .replace(/SIZE=/g, ',"size":')
- .replace(/MOUNTPOINT=/g, ',"mountpoint":')
- .replace(/UUID=/g, ',"uuid":')
- .replace(/ROTA=/g, ',"rota":')
- .replace(/RO=/g, ',"ro":')
- .replace(/RM=/g, ',"rm":')
- .replace(/TRAN=/g, ',"tran":')
- .replace(/SERIAL=/g, ',"serial":')
- .replace(/LABEL=/g, ',"label":')
- .replace(/MODEL=/g, ',"model":')
- .replace(/OWNER=/g, ',"owner":')
- .replace(/GROUP=/g, ',"group":')
- .replace(/\n/g, '}\n');
- }
- 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) {
- 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) {
- if (!error) {
- let lines = blkStdoutToObject(stdout).split('\n');
- data = parseBlk(lines);
- if (callback) {
- callback(data);
- }
- resolve(data);
- } else {
- exec('lsblk -bPo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,RM,LABEL,MODEL,OWNER 2>/dev/null', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
- if (!error) {
- let lines = blkStdoutToObject(stdout).split('\n');
- data = parseBlk(lines);
- }
- if (callback) {
- callback(data);
- }
- resolve(data);
- });
- }
- });
- }
- if (_darwin) {
- exec('diskutil info -all', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
- if (!error) {
- let lines = stdout.toString().split('\n');
- // parse lines into temp array of devices
- data = parseDevices(lines);
- }
- if (callback) {
- callback(data);
- }
- resolve(data);
- });
- }
- if (_sunos) {
- if (callback) { callback(data); }
- resolve(data);
- }
- if (_windows) {
- let 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-WmiObject Win32_logicaldisk | select Caption,DriveType,Name,FileSystem,Size,VolumeSerialNumber,VolumeName | fl').then((stdout, error) => {
- util.powerShell('Get-CimInstance -ClassName Win32_LogicalDisk | select Caption,DriveType,Name,FileSystem,Size,VolumeSerialNumber,VolumeName | fl').then((stdout, error) => {
- if (!error) {
- let devices = stdout.toString().split(/\n\s*\n/);
- devices.forEach(function (device) {
- let lines = device.split('\r\n');
- let drivetype = util.getValue(lines, 'drivetype', ':');
- if (drivetype) {
- data.push({
- name: util.getValue(lines, 'name', ':'),
- identifier: util.getValue(lines, 'caption', ':'),
- type: 'disk',
- 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],
- uuid: util.getValue(lines, 'volumeserialnumber', ':'),
- label: util.getValue(lines, 'volumename', ':'),
- model: '',
- serial: util.getValue(lines, 'volumeserialnumber', ':'),
- removable: drivetype === '2',
- protocol: ''
- });
- }
- });
- }
- if (callback) {
- callback(data);
- }
- resolve(data);
- });
- } catch (e) {
- if (callback) { callback(data); }
- resolve(data);
- }
- }
- if (_freebsd || _openbsd || _netbsd) {
- // will follow
- if (callback) { callback(null); }
- resolve(null);
- }
- });
- });
- }
- exports.blockDevices = blockDevices;
- // --------------------------
- // FS - speed
- function calcFsSpeed(rx, wx) {
- let result = {
- rx: 0,
- wx: 0,
- tx: 0,
- rx_sec: null,
- wx_sec: null,
- tx_sec: null,
- ms: 0
- };
- if (_fs_speed && _fs_speed.ms) {
- result.rx = rx;
- result.wx = wx;
- result.tx = result.rx + result.wx;
- result.ms = Date.now() - _fs_speed.ms;
- result.rx_sec = (result.rx - _fs_speed.bytes_read) / (result.ms / 1000);
- result.wx_sec = (result.wx - _fs_speed.bytes_write) / (result.ms / 1000);
- result.tx_sec = result.rx_sec + result.wx_sec;
- _fs_speed.rx_sec = result.rx_sec;
- _fs_speed.wx_sec = result.wx_sec;
- _fs_speed.tx_sec = result.tx_sec;
- _fs_speed.bytes_read = result.rx;
- _fs_speed.bytes_write = result.wx;
- _fs_speed.bytes_overall = result.rx + result.wx;
- _fs_speed.ms = Date.now();
- _fs_speed.last_ms = result.ms;
- } else {
- result.rx = rx;
- result.wx = wx;
- result.tx = result.rx + result.wx;
- _fs_speed.rx_sec = null;
- _fs_speed.wx_sec = null;
- _fs_speed.tx_sec = null;
- _fs_speed.bytes_read = result.rx;
- _fs_speed.bytes_write = result.wx;
- _fs_speed.bytes_overall = result.rx + result.wx;
- _fs_speed.ms = Date.now();
- _fs_speed.last_ms = 0;
- }
- return result;
- }
- function fsStats(callback) {
- return new Promise((resolve) => {
- process.nextTick(() => {
- if (_windows || _freebsd || _openbsd || _netbsd || _sunos) {
- return resolve(null);
- }
- let result = {
- rx: 0,
- wx: 0,
- tx: 0,
- rx_sec: null,
- wx_sec: null,
- tx_sec: null,
- ms: 0
- };
- let rx = 0;
- let wx = 0;
- if ((_fs_speed && !_fs_speed.ms) || (_fs_speed && _fs_speed.ms && Date.now() - _fs_speed.ms >= 500)) {
- if (_linux) {
- // exec("df -k | grep /dev/", function(error, stdout) {
- exec('lsblk -r 2>/dev/null | grep /', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
- if (!error) {
- let lines = stdout.toString().split('\n');
- let fs_filter = [];
- lines.forEach(function (line) {
- if (line !== '') {
- line = line.trim().split(' ');
- if (fs_filter.indexOf(line[0]) === -1) { fs_filter.push(line[0]); }
- }
- });
- let output = fs_filter.join('|');
- exec('cat /proc/diskstats | egrep "' + output + '"', { 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.replace(/ +/g, ' ').split(' ');
- rx += parseInt(line[5]) * 512;
- wx += parseInt(line[9]) * 512;
- }
- });
- result = calcFsSpeed(rx, wx);
- }
- if (callback) {
- callback(result);
- }
- resolve(result);
- });
- } else {
- if (callback) {
- callback(result);
- }
- resolve(result);
- }
- });
- }
- 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(',');
- rx += parseInt(line[2]);
- wx += parseInt(line[9]);
- }
- });
- result = calcFsSpeed(rx, wx);
- }
- if (callback) {
- callback(result);
- }
- resolve(result);
- });
- }
- } else {
- result.ms = _fs_speed.last_ms;
- result.rx = _fs_speed.bytes_read;
- result.wx = _fs_speed.bytes_write;
- result.tx = _fs_speed.bytes_read + _fs_speed.bytes_write;
- result.rx_sec = _fs_speed.rx_sec;
- result.wx_sec = _fs_speed.wx_sec;
- result.tx_sec = _fs_speed.tx_sec;
- if (callback) {
- callback(result);
- }
- resolve(result);
- }
- });
- });
- }
- exports.fsStats = fsStats;
- function calcDiskIO(rIO, wIO, rWaitTime, wWaitTime, tWaitTime) {
- let result = {
- rIO: 0,
- wIO: 0,
- tIO: 0,
- rIO_sec: null,
- wIO_sec: null,
- tIO_sec: null,
- rWaitTime: 0,
- wWaitTime: 0,
- tWaitTime: 0,
- rWaitPercent: null,
- wWaitPercent: null,
- tWaitPercent: null,
- ms: 0
- };
- if (_disk_io && _disk_io.ms) {
- result.rIO = rIO;
- result.wIO = wIO;
- result.tIO = rIO + wIO;
- result.ms = Date.now() - _disk_io.ms;
- result.rIO_sec = (result.rIO - _disk_io.rIO) / (result.ms / 1000);
- result.wIO_sec = (result.wIO - _disk_io.wIO) / (result.ms / 1000);
- result.tIO_sec = result.rIO_sec + result.wIO_sec;
- 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);
- _disk_io.rIO = rIO;
- _disk_io.wIO = wIO;
- _disk_io.rIO_sec = result.rIO_sec;
- _disk_io.wIO_sec = result.wIO_sec;
- _disk_io.tIO_sec = result.tIO_sec;
- _disk_io.rWaitTime = rWaitTime;
- _disk_io.wWaitTime = wWaitTime;
- _disk_io.tWaitTime = tWaitTime;
- _disk_io.rWaitPercent = result.rWaitPercent;
- _disk_io.wWaitPercent = result.wWaitPercent;
- _disk_io.tWaitPercent = result.tWaitPercent;
- _disk_io.last_ms = result.ms;
- _disk_io.ms = Date.now();
- } else {
- result.rIO = rIO;
- result.wIO = wIO;
- result.tIO = rIO + wIO;
- result.rWaitTime = rWaitTime;
- result.wWaitTime = wWaitTime;
- result.tWaitTime = tWaitTime;
- _disk_io.rIO = rIO;
- _disk_io.wIO = wIO;
- _disk_io.rIO_sec = null;
- _disk_io.wIO_sec = null;
- _disk_io.tIO_sec = null;
- _disk_io.rWaitTime = rWaitTime;
- _disk_io.wWaitTime = wWaitTime;
- _disk_io.tWaitTime = tWaitTime;
- _disk_io.rWaitPercent = null;
- _disk_io.wWaitPercent = null;
- _disk_io.tWaitPercent = null;
- _disk_io.last_ms = 0;
- _disk_io.ms = Date.now();
- }
- return result;
- }
- function disksIO(callback) {
- return new Promise((resolve) => {
- process.nextTick(() => {
- if (_windows) {
- return resolve(null);
- }
- if (_sunos) {
- return resolve(null);
- }
- let result = {
- rIO: 0,
- wIO: 0,
- tIO: 0,
- rIO_sec: null,
- wIO_sec: null,
- tIO_sec: null,
- rWaitTime: 0,
- wWaitTime: 0,
- tWaitTime: 0,
- rWaitPercent: null,
- wWaitPercent: null,
- tWaitPercent: null,
- ms: 0
- };
- let rIO = 0;
- let wIO = 0;
- let rWaitTime = 0;
- let wWaitTime = 0;
- let tWaitTime = 0;
- if ((_disk_io && !_disk_io.ms) || (_disk_io && _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';
- exec(cmd, { maxBuffer: 1024 * 1024 }, function (error, stdout) {
- if (!error) {
- let lines = stdout.split('\n');
- lines.forEach(function (line) {
- // ignore empty lines
- 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]);
- });
- result = calcDiskIO(rIO, wIO, rWaitTime, wWaitTime, tWaitTime);
- if (callback) {
- callback(result);
- }
- resolve(result);
- } else {
- if (callback) {
- callback(result);
- }
- resolve(result);
- }
- });
- }
- 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);
- }
- resolve(result);
- });
- }
- } else {
- result.rIO = _disk_io.rIO;
- result.wIO = _disk_io.wIO;
- result.tIO = _disk_io.rIO + _disk_io.wIO;
- result.ms = _disk_io.last_ms;
- result.rIO_sec = _disk_io.rIO_sec;
- result.wIO_sec = _disk_io.wIO_sec;
- result.tIO_sec = _disk_io.tIO_sec;
- result.rWaitTime = _disk_io.rWaitTime;
- result.wWaitTime = _disk_io.wWaitTime;
- result.tWaitTime = _disk_io.tWaitTime;
- result.rWaitPercent = _disk_io.rWaitPercent;
- result.wWaitPercent = _disk_io.wWaitPercent;
- result.tWaitPercent = _disk_io.tWaitPercent;
- if (callback) {
- callback(result);
- }
- resolve(result);
- }
- });
- });
- }
- exports.disksIO = disksIO;
- function diskLayout(callback) {
- function getVendorFromModel(model) {
- const diskManufacturers = [
- { pattern: 'WESTERN.*', manufacturer: 'Western Digital' },
- { pattern: '^WDC.*', manufacturer: 'Western Digital' },
- { pattern: 'WD.*', manufacturer: 'Western Digital' },
- { pattern: 'TOSHIBA.*', manufacturer: 'Toshiba' },
- { pattern: 'HITACHI.*', manufacturer: 'Hitachi' },
- { pattern: '^IC.*', manufacturer: 'Hitachi' },
- { pattern: '^HTS.*', manufacturer: 'Hitachi' },
- { pattern: 'SANDISK.*', manufacturer: 'SanDisk' },
- { pattern: 'KINGSTON.*', manufacturer: 'Kingston Technology' },
- { pattern: '^SONY.*', manufacturer: 'Sony' },
- { pattern: 'TRANSCEND.*', manufacturer: 'Transcend' },
- { pattern: 'SAMSUNG.*', manufacturer: 'Samsung' },
- { pattern: '^ST(?!I\\ ).*', manufacturer: 'Seagate' },
- { pattern: '^STI\\ .*', manufacturer: 'SimpleTech' },
- { pattern: '^D...-.*', manufacturer: 'IBM' },
- { pattern: '^IBM.*', manufacturer: 'IBM' },
- { pattern: '^FUJITSU.*', manufacturer: 'Fujitsu' },
- { pattern: '^MP.*', manufacturer: 'Fujitsu' },
- { pattern: '^MK.*', manufacturer: 'Toshiba' },
- { pattern: 'MAXTO.*', manufacturer: 'Maxtor' },
- { pattern: 'PIONEER.*', manufacturer: 'Pioneer' },
- { pattern: 'PHILIPS.*', manufacturer: 'Philips' },
- { pattern: 'QUANTUM.*', manufacturer: 'Quantum Technology' },
- { pattern: 'FIREBALL.*', manufacturer: 'Quantum Technology' },
- { pattern: '^VBOX.*', manufacturer: 'VirtualBox' },
- { pattern: 'CORSAIR.*', manufacturer: 'Corsair Components' },
- { pattern: 'CRUCIAL.*', manufacturer: 'Crucial' },
- { pattern: 'ECM.*', manufacturer: 'ECM' },
- { pattern: 'INTEL.*', manufacturer: 'INTEL' },
- { pattern: 'EVO.*', manufacturer: 'Samsung' },
- { 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; }
- });
- }
- return result;
- }
- return new Promise((resolve) => {
- process.nextTick(() => {
- const commitResult = res => {
- for (let i = 0; i < res.length; i++) {
- delete res[i].BSDName;
- }
- if (callback) {
- callback(res);
- }
- resolve(res);
- };
- let 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) {
- 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)); });
- }
- } catch (e) {
- // fallback to older version of lsblk
- 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').toString();
- let 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 === '')); });
- }
- devices.forEach((device) => {
- let mediumType = '';
- const BSDName = '/dev/' + device.name;
- const logical = device.name;
- try {
- mediumType = execSync('cat /sys/block/' + logical + '/queue/rotational 2>/dev/null').toString().split('\n')[0];
- } catch (e) {
- util.noop();
- }
- let interfaceType = device.tran ? device.tran.toUpperCase().trim() : '';
- if (interfaceType === 'NVME') {
- mediumType = '2';
- interfaceType = 'PCIe';
- }
- 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'))))),
- name: device.model || '',
- vendor: getVendorFromModel(device.model) || (device.vendor ? device.vendor.trim() : ''),
- size: device.size || 0,
- bytesPerSector: null,
- totalCylinders: null,
- totalHeads: null,
- totalSectors: null,
- totalTracks: null,
- tracksPerCylinder: null,
- sectorsPerTrack: null,
- firmwareRevision: device.rev ? device.rev.trim() : '',
- serialNum: device.serial ? device.serial.trim() : '',
- interfaceType: interfaceType,
- smartStatus: 'unknown',
- temperature: null,
- BSDName: BSDName
- });
- cmd += `printf "\n${BSDName}|"; smartctl -H ${BSDName} | grep overall;`;
- cmdFullSmart += `${cmdFullSmart ? 'printf ",";' : ''}smartctl -a -j ${BSDName};`;
- });
- } catch (e) {
- util.noop();
- }
- }
- // check S.M.A.R.T. status
- if (cmdFullSmart) {
- exec(cmdFullSmart, { maxBuffer: 1024 * 1024 }, function (error, stdout) {
- try {
- const data = JSON.parse(`[${stdout}]`);
- 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].temperature = disk.temperature.current;
- }
- result[i].smartData = disk;
- }
- }
- });
- commitResult(result);
- } catch (e) {
- if (cmd) {
- cmd = cmd + 'printf "\n"';
- exec(cmd, { maxBuffer: 1024 * 1024 }, function (error, stdout) {
- let lines = stdout.toString().split('\n');
- lines.forEach(line => {
- if (line) {
- let parts = line.split('|');
- if (parts.length === 2) {
- let BSDName = parts[0];
- parts[1] = parts[1].trim();
- let parts2 = parts[1].split(':');
- if (parts2.length === 2) {
- parts2[1] = parts2[1].trim();
- let 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'));
- }
- }
- }
- }
- }
- });
- commitResult(result);
- });
- } else {
- commitResult(result);
- }
- }
- });
- } else {
- commitResult(result);
- }
- });
- }
- if (_freebsd || _openbsd || _netbsd) {
- if (callback) { callback(result); }
- resolve(result);
- }
- if (_sunos) {
- if (callback) { callback(result); }
- resolve(result);
- }
- if (_darwin) {
- exec('system_profiler SPSerialATADataType SPNVMeDataType SPUSBDataType', { maxBuffer: 1024 * 1024 }, function (error, stdout) {
- if (!error) {
- // split by type:
- let lines = stdout.toString().split('\n');
- let linesSATA = [];
- let linesNVMe = [];
- let 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); }
- });
- try {
- // Serial ATA Drives
- let devices = linesSATA.join('\n').split(' Physical Interconnect: ');
- devices.shift();
- devices.forEach(function (device) {
- device = 'InterfaceType: ' + device;
- let 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, ''));
- }
- if (!sizeValue) {
- sizeValue = parseInt(sizeStr);
- }
- if (sizeValue) {
- const smartStatusString = util.getValue(lines, 'S.M.A.R.T. status', ':', true).trim().toLowerCase();
- result.push({
- device: BSDName,
- type: mediumType.startsWith('Solid') ? 'SSD' : 'HD',
- name: util.getValue(lines, 'Model', ':', true).trim(),
- vendor: getVendorFromModel(util.getValue(lines, 'Model', ':', true).trim()) || util.getValue(lines, 'Manufacturer', ':', true),
- size: sizeValue,
- bytesPerSector: null,
- totalCylinders: null,
- totalHeads: null,
- totalSectors: null,
- totalTracks: null,
- tracksPerCylinder: null,
- sectorsPerTrack: null,
- firmwareRevision: util.getValue(lines, 'Revision', ':', true).trim(),
- serialNum: util.getValue(lines, 'Serial Number', ':', true).trim(),
- interfaceType: util.getValue(lines, 'InterfaceType', ':', true).trim(),
- smartStatus: smartStatusString === 'verified' ? 'OK' : smartStatusString || 'unknown',
- temperature: null,
- BSDName: BSDName
- });
- cmd = cmd + 'printf "\n' + BSDName + '|"; diskutil info /dev/' + BSDName + ' | grep SMART;';
- }
- }
- });
- } catch (e) {
- util.noop();
- }
- // NVME Drives
- try {
- let devices = linesNVMe.join('\n').split('\n\n Capacity:');
- devices.shift();
- devices.forEach(function (device) {
- device = '!Capacity: ' + device;
- let 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, ''));
- }
- if (!sizeValue) {
- sizeValue = parseInt(sizeStr);
- }
- if (sizeValue) {
- const smartStatusString = util.getValue(lines, 'S.M.A.R.T. status', ':', true).trim().toLowerCase();
- result.push({
- device: BSDName,
- type: 'NVMe',
- name: util.getValue(lines, 'Model', ':', true).trim(),
- vendor: getVendorFromModel(util.getValue(lines, 'Model', ':', true).trim()),
- size: sizeValue,
- bytesPerSector: null,
- totalCylinders: null,
- totalHeads: null,
- totalSectors: null,
- totalTracks: null,
- tracksPerCylinder: null,
- sectorsPerTrack: null,
- firmwareRevision: util.getValue(lines, 'Revision', ':', true).trim(),
- serialNum: util.getValue(lines, 'Serial Number', ':', true).trim(),
- interfaceType: ('PCIe ' + linkWidth).trim(),
- smartStatus: smartStatusString === 'verified' ? 'OK' : smartStatusString || 'unknown',
- temperature: null,
- BSDName: BSDName
- });
- cmd = cmd + 'printf "\n' + BSDName + '|"; diskutil info /dev/' + BSDName + ' | grep SMART;';
- }
- }
- });
- } catch (e) {
- util.noop();
- }
- // USB Drives
- try {
- let devices = linesUSB.join('\n').replaceAll('Media:\n ', 'Model:').split('\n\n Product ID:');
- devices.shift();
- devices.forEach(function (device) {
- let 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, ''));
- }
- if (!sizeValue) {
- sizeValue = parseInt(sizeStr);
- }
- if (sizeValue) {
- const smartStatusString = util.getValue(lines, 'S.M.A.R.T. status', ':', true).trim().toLowerCase();
- result.push({
- device: BSDName,
- type: 'USB',
- name: util.getValue(lines, 'Model', ':', true).trim().replaceAll(':', ''),
- vendor: getVendorFromModel(util.getValue(lines, 'Model', ':', true).trim()),
- size: sizeValue,
- bytesPerSector: null,
- totalCylinders: null,
- totalHeads: null,
- totalSectors: null,
- totalTracks: null,
- tracksPerCylinder: null,
- sectorsPerTrack: null,
- firmwareRevision: util.getValue(lines, 'Revision', ':', true).trim(),
- serialNum: util.getValue(lines, 'Serial Number', ':', true).trim(),
- interfaceType: 'USB',
- smartStatus: smartStatusString === 'verified' ? 'OK' : smartStatusString || 'unknown',
- temperature: null,
- BSDName: BSDName
- });
- cmd = cmd + 'printf "\n' + BSDName + '|"; diskutil info /dev/' + BSDName + ' | grep SMART;';
- }
- }
- });
- } catch (e) {
- 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 => {
- if (line) {
- let parts = line.split('|');
- if (parts.length === 2) {
- let BSDName = parts[0];
- parts[1] = parts[1].trim();
- let parts2 = parts[1].split(':');
- if (parts2.length === 2) {
- parts2[1] = parts2[1].trim();
- let 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')));
- }
- }
- }
- }
- }
- });
- for (let i = 0; i < result.length; i++) {
- delete result[i].BSDName;
- }
- if (callback) {
- callback(result);
- }
- resolve(result);
- });
- } else {
- for (let i = 0; i < result.length; i++) {
- delete result[i].BSDName;
- }
- if (callback) {
- callback(result);
- }
- resolve(result);
- }
- }
- });
- }
- if (_windows) {
- try {
- const workload = [];
- workload.push(util.powerShell('Get-WmiObject Win32_DiskDrive | select Caption,Size,Status,PNPDeviceId,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'));
- if (smartDev && smartDev.devices && smartDev.devices.length > 0) {
- smartDev.devices.forEach((dev) => {
- workload.push(execPromiseSave(`smartctl -j -a ${dev.name}`, util.execOptsWin));
- });
- }
- } catch (e) {
- util.noop();
- }
- }
- 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');
- const size = util.getValue(lines, 'Size', ':').trim();
- const status = util.getValue(lines, 'Status', ':').trim().toLowerCase();
- if (size) {
- result.push({
- device: util.getValue(lines, 'PNPDeviceId', ':'),
- 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),
- bytesPerSector: parseInt(util.getValue(lines, 'BytesPerSector', ':')),
- totalCylinders: parseInt(util.getValue(lines, 'TotalCylinders', ':')),
- totalHeads: parseInt(util.getValue(lines, 'TotalHeads', ':')),
- totalSectors: parseInt(util.getValue(lines, 'TotalSectors', ':')),
- totalTracks: parseInt(util.getValue(lines, 'TotalTracks', ':')),
- tracksPerCylinder: parseInt(util.getValue(lines, 'TracksPerCylinder', ':')),
- sectorsPerTrack: parseInt(util.getValue(lines, 'SectorsPerTrack', ':')),
- firmwareRevision: util.getValue(lines, 'FirmwareRevision', ':').trim(),
- serialNum: util.getValue(lines, 'SerialNumber', ':').trim(),
- interfaceType: util.getValue(lines, 'InterfaceType', ':').trim(),
- smartStatus: (status === 'ok' ? 'Ok' : (status === 'degraded' ? 'Degraded' : (status === 'pred fail' ? 'Predicted Failure' : 'Unknown'))),
- temperature: null,
- });
- }
- });
- devices = data.results[1].split(/\n\s*\n/);
- devices.forEach(function (device) {
- let lines = device.split('\r\n');
- const serialNum = util.getValue(lines, 'SerialNumber', ':').trim();
- const name = util.getValue(lines, 'FriendlyName', ':').trim().replace('Msft ', 'Microsoft');
- const size = util.getValue(lines, 'Size', ':').trim();
- const model = util.getValue(lines, 'Model', ':').trim();
- const interfaceType = util.getValue(lines, 'BusType', ':').trim();
- let mediaType = util.getValue(lines, 'MediaType', ':').trim();
- if (mediaType === '3' || mediaType === 'HDD') { mediaType = 'HD'; }
- if (mediaType === '4') { mediaType = 'SSD'; }
- if (mediaType === '5') { mediaType = 'SCM'; }
- if (mediaType === 'Unspecified' && (model.toLowerCase().indexOf('virtual') > -1 || model.toLowerCase().indexOf('vbox') > -1)) { mediaType = 'Virtual'; }
- if (size) {
- let i = util.findObjectByKey(result, 'serialNum', serialNum);
- if (i === -1 || serialNum === '') {
- i = util.findObjectByKey(result, 'name', name);
- }
- if (i != -1) {
- result[i].type = mediaType;
- result[i].interfaceType = interfaceType;
- }
- }
- });
- // S.M.A.R.T
- data.results.shift();
- data.results.shift();
- if (data.results.length) {
- data.results.forEach((smartStr) => {
- try {
- const smartData = JSON.parse(smartStr);
- if (smartData.serial_number) {
- const serialNum = smartData.serial_number;
- let i = util.findObjectByKey(result, 'serialNum', serialNum);
- if (i != -1) {
- result[i].smartStatus = (smartData.smart_status && smartData.smart_status.passed ? 'Ok' : (smartData.smart_status && smartData.smart_status.passed === false ? 'Predicted Failure' : 'unknown'));
- if (smartData.temperature && smartData.temperature.current) {
- result[i].temperature = smartData.temperature.current;
- }
- result[i].smartData = smartData;
- }
- }
- } catch (e) {
- util.noop();
- }
- });
- }
- if (callback) {
- callback(result);
- }
- resolve(result);
- });
- } catch (e) {
- if (callback) { callback(result); }
- resolve(result);
- }
- }
- });
- });
- }
- exports.diskLayout = diskLayout;
|