diff --git a/lib/filesystem.js b/lib/filesystem.js index 8fef85a..99a7321 100755 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -757,6 +757,8 @@ function diskLayout(callback) { { pattern: 'CRUCIAL.+', manufacturer: 'Crucial' }, { pattern: 'ECM.+', manufacturer: 'ECM' }, { pattern: 'INTEL.+', manufacturer: 'INTEL' }, + { pattern: '.+EVO', manufacturer: 'Samsung' }, + { pattern: 'APPLE.+', manufacturer: 'Apple' }, ]; let result = ''; @@ -911,11 +913,24 @@ function diskLayout(callback) { resolve(result); } if (_darwin) { - exec('system_profiler SPSerialATADataType SPNVMeDataType', function (error, stdout) { + exec('system_profiler SPSerialATADataType SPNVMeDataType SPUSBDataType', function (error, stdout) { if (!error) { - let parts = stdout.toString().split('NVMExpress:'); - - let devices = parts[0].split(' Physical Interconnect: '); + // 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); } + }); + // Serial ATA Drives + let devices = linesSATA.join('\n').split(' Physical Interconnect: '); devices.shift(); devices.forEach(function (device) { device = 'InterfaceType: ' + device; @@ -932,10 +947,54 @@ function diskLayout(callback) { 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;'; + } + } + }); + // NVME Drives + 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, '')); + } + 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, @@ -947,8 +1006,8 @@ function diskLayout(callback) { 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: 'unknown', + interfaceType: ('PCIe ' + linkWidth).trim(), + smartStatus: smartStatusString === 'verified' ? 'OK' : smartStatusString || 'unknown', temperature: null, BSDName: BSDName }); @@ -956,49 +1015,47 @@ function diskLayout(callback) { } } }); - if (parts.length > 1) { - let devices = parts[1].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, '')); - } - if (!sizeValue) { - sizeValue = parseInt(sizeStr); - } - if (sizeValue) { - 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: 'unknown', - temperature: null, - BSDName: BSDName - }); - cmd = cmd + 'printf "\n' + BSDName + '|"; diskutil info /dev/' + BSDName + ' | grep SMART;'; - } + // USB Drives + 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, '')); } - }); - } + 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;'; + } + } + }); } if (cmd) { cmd = cmd + 'printf "\n"';