@depup/systeminformation 5.31.4-depup.0 → 5.33.1-depup.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/filesystem.js CHANGED
@@ -15,7 +15,6 @@
15
15
 
16
16
  const util = require('./util');
17
17
  const fs = require('fs');
18
- const os = require('os');
19
18
 
20
19
  const exec = require('child_process').exec;
21
20
  const execSync = require('child_process').execSync;
@@ -73,7 +72,7 @@ function fsSize(drive, callback) {
73
72
  function filterLines(stdout) {
74
73
  const lines = stdout.toString().split('\n');
75
74
  lines.shift();
76
- if (stdout.toString().toLowerCase().indexOf('filesystem')) {
75
+ if (stdout.toString().toLowerCase().indexOf('filesystem') >= 0) {
77
76
  let removeLines = 0;
78
77
  for (let i = 0; i < lines.length; i++) {
79
78
  if (lines[i] && lines[i].toLowerCase().startsWith('filesystem')) {
@@ -89,19 +88,23 @@ function fsSize(drive, callback) {
89
88
 
90
89
  function parseDf(lines) {
91
90
  const data = [];
91
+ // filesystem (first column) and mount point (last column) may contain spaces:
92
+ // anchor parsing on the numeric columns in between (blocks, used, available, capacity)
93
+ const dfWithType = /^(.+?)\s+(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(?:\d+%|-)\s+(.+)$/;
94
+ const dfNoType = /^(.+?)\s+(\d+)\s+(\d+)\s+(\d+)\s+(?:\d+%|-)\s+(.+)$/;
95
+ const hasType = _linux || _freebsd || _openbsd || _netbsd;
92
96
  lines.forEach((line) => {
93
97
  if (line !== '') {
94
- line = line.replace(/ +/g, ' ').split(' ');
95
- if (line && (line[0].startsWith('/') || (line[6] && line[6] === '/') || line[0].indexOf('/') > 0 || line[0].indexOf(':') === 1 || (!_darwin && !isLinuxTmpFs(line[1])))) {
96
- const fs = line[0];
97
- const fsType = _linux || _freebsd || _openbsd || _netbsd ? line[1] : getmacOsFsType(line[0]);
98
- const size = parseInt(_linux || _freebsd || _openbsd || _netbsd ? line[2] : line[1], 10) * 1024;
99
- const used = parseInt(_linux || _freebsd || _openbsd || _netbsd ? line[3] : line[2], 10) * 1024;
100
- const available = parseInt(_linux || _freebsd || _openbsd || _netbsd ? line[4] : line[3], 10) * 1024;
98
+ const parts = line.trim().match(hasType ? dfWithType : dfNoType);
99
+ if (parts && (parts[1].startsWith('/') || parts[hasType ? 6 : 5] === '/' || parts[1].indexOf('/') > 0 || parts[1].indexOf(':') === 1 || (!_darwin && !isLinuxTmpFs(parts[2])))) {
100
+ const fs = parts[1];
101
+ const fsType = hasType ? parts[2] : getmacOsFsType(parts[1]);
102
+ const size = parseInt(parts[hasType ? 3 : 2], 10) * 1024;
103
+ const used = parseInt(parts[hasType ? 4 : 3], 10) * 1024;
104
+ const available = parseInt(parts[hasType ? 5 : 4], 10) * 1024;
101
105
  const use = parseFloat((100.0 * (used / (used + available))).toFixed(2));
102
106
  const rw = osMounts && Object.keys(osMounts).length > 0 ? osMounts[fs] || false : null;
103
- line.splice(0, _linux || _freebsd || _openbsd || _netbsd ? 6 : 5);
104
- const mount = line.join(' ');
107
+ const mount = parts[hasType ? 6 : 5];
105
108
  if (!data.find((el) => el.fs === fs && el.type === fsType && el.mount === mount)) {
106
109
  data.push({
107
110
  fs,
@@ -159,9 +162,11 @@ function fsSize(drive, callback) {
159
162
  return line.startsWith('/');
160
163
  })
161
164
  .forEach((line) => {
162
- osMounts[line.split(' ')[0]] = osMounts[line.split(' ')[0]] || false;
165
+ // /proc/mounts escapes spaces as \040
166
+ const fs = line.split(' ')[0].replace(/\\040/g, ' ');
167
+ osMounts[fs] = osMounts[fs] || false;
163
168
  if (line.toLowerCase().indexOf('/snap/') === -1) {
164
- osMounts[line.split(' ')[0]] = line.toLowerCase().indexOf('rw,') >= 0 || line.toLowerCase().indexOf(' rw ') >= 0;
169
+ osMounts[fs] = line.toLowerCase().indexOf('rw,') >= 0 || line.toLowerCase().indexOf(' rw ') >= 0;
165
170
  }
166
171
  });
167
172
  } catch {
@@ -215,7 +220,7 @@ function fsSize(drive, callback) {
215
220
  }
216
221
  if (_windows) {
217
222
  try {
218
- const driveSanitized = drive ? util.sanitizeShellString(drive, true) : '';
223
+ const driveSanitized = drive ? util.sanitizeString(drive, true) : '';
219
224
  const cmd = `Get-WmiObject Win32_logicaldisk | select Access,Caption,FileSystem,FreeSpace,Size ${driveSanitized ? '| where -property Caption -eq ' + driveSanitized : ''} | fl`;
220
225
  util.powerShell(cmd).then((stdout, error) => {
221
226
  if (!error) {
@@ -342,7 +347,9 @@ exports.fsOpenFiles = fsOpenFiles;
342
347
  // disks
343
348
 
344
349
  function parseBytes(s) {
345
- return parseInt(s.substr(s.indexOf(' (') + 2, s.indexOf(' Bytes)') - 10), 10);
350
+ const start = s.indexOf(' (') + 2;
351
+ const end = s.indexOf(' Bytes)');
352
+ return parseInt(s.substr(start, end - start), 10);
346
353
  }
347
354
 
348
355
  function parseDevices(lines) {
@@ -485,7 +492,7 @@ function raidMatchLinux(data) {
485
492
  try {
486
493
  data.forEach((element) => {
487
494
  if (element.type.startsWith('raid')) {
488
- const lines = execSync(`mdadm --export --detail /dev/${element.name}`, util.execOptsLinux).toString().split('\n');
495
+ const lines = execSync(`mdadm --export --detail /dev/${util.sanitizeString(element.name, true)}`, util.execOptsLinux).toString().split('\n');
489
496
  const mdData = decodeMdabmData(lines);
490
497
 
491
498
  element.label = mdData.label; // <- assign label info
@@ -837,8 +844,9 @@ function fsStats(callback) {
837
844
  lines.forEach((line) => {
838
845
  if (line !== '') {
839
846
  line = line.trim().split(' ');
840
- if (fs_filter.indexOf(line[0]) === -1) {
841
- fs_filter.push(line[0]);
847
+ const dev = util.sanitizeShellString(line[0], true);
848
+ if (dev && fs_filter.indexOf(dev) === -1) {
849
+ fs_filter.push(dev);
842
850
  }
843
851
  }
844
852
  });
@@ -1230,8 +1238,8 @@ function diskLayout(callback) {
1230
1238
  }
1231
1239
  devices.forEach((device) => {
1232
1240
  let mediumType = '';
1233
- const BSDName = '/dev/' + device.name;
1234
- const logical = device.name;
1241
+ const logical = util.sanitizeShellString(device.name, true);
1242
+ const BSDName = '/dev/' + logical;
1235
1243
  try {
1236
1244
  mediumType = execSync('cat /sys/block/' + logical + '/queue/rotational 2>/dev/null', util.execOptsLinux)
1237
1245
  .toString()
@@ -1351,17 +1359,20 @@ function diskLayout(callback) {
1351
1359
  }
1352
1360
  if (_darwin) {
1353
1361
  let cmdFullSmart = '';
1354
- exec(`system_profiler SPSerialATADataType SPNVMeDataType ${parseInt(os.release(), 10) > 24 ? 'SPUSBHostDataType' : 'SPUSBDataType'} `, { maxBuffer: 1024 * 1024 }, (error, stdout) => {
1362
+ exec(`system_profiler SPSerialATADataType SPNVMeDataType SPUSBDataType SPStorageDataType`, { maxBuffer: 1024 * 1024 }, (error, stdout) => {
1355
1363
  if (!error) {
1356
1364
  // split by type:
1357
1365
  const lines = stdout.toString().split('\n');
1358
1366
  const linesSATA = [];
1359
1367
  const linesNVMe = [];
1368
+ const linesStorage = [];
1360
1369
  const linesUSB = [];
1361
1370
  let dataType = 'SATA';
1362
1371
  lines.forEach((line) => {
1363
1372
  if (line === 'NVMExpress:') {
1364
1373
  dataType = 'NVMe';
1374
+ } else if (line === 'Storage:') {
1375
+ dataType = 'Storage';
1365
1376
  } else if (line === 'USB:') {
1366
1377
  dataType = 'USB';
1367
1378
  } else if (line === 'SATA/SATA Express:') {
@@ -1370,6 +1381,8 @@ function diskLayout(callback) {
1370
1381
  linesSATA.push(line);
1371
1382
  } else if (dataType === 'NVMe') {
1372
1383
  linesNVMe.push(line);
1384
+ } else if (dataType === 'Storage') {
1385
+ linesStorage.push(line);
1373
1386
  } else if (dataType === 'USB') {
1374
1387
  linesUSB.push(line);
1375
1388
  }
@@ -1383,7 +1396,7 @@ function diskLayout(callback) {
1383
1396
  const lines = device.split('\n');
1384
1397
  const mediumType = util.getValue(lines, 'Medium Type', ':', true).trim();
1385
1398
  const sizeStr = util.getValue(lines, 'capacity', ':', true).trim();
1386
- const BSDName = util.getValue(lines, 'BSD Name', ':', true).trim();
1399
+ const BSDName = util.sanitizeShellString(util.getValue(lines, 'BSD Name', ':', true).trim(), true);
1387
1400
  if (sizeStr) {
1388
1401
  let sizeValue = 0;
1389
1402
  if (sizeStr.indexOf('(') >= 0) {
@@ -1439,7 +1452,7 @@ function diskLayout(callback) {
1439
1452
  const lines = device.split('\n');
1440
1453
  const linkWidth = util.getValue(lines, 'link width', ':', true).trim();
1441
1454
  const sizeStr = util.getValue(lines, '!capacity', ':', true).trim();
1442
- const BSDName = util.getValue(lines, 'BSD Name', ':', true).trim();
1455
+ const BSDName = util.sanitizeShellString(util.getValue(lines, 'BSD Name', ':', true).trim(), true);
1443
1456
  if (sizeStr) {
1444
1457
  let sizeValue = 0;
1445
1458
  if (sizeStr.indexOf('(') >= 0) {
@@ -1485,14 +1498,14 @@ function diskLayout(callback) {
1485
1498
  } catch {
1486
1499
  util.noop();
1487
1500
  }
1488
- // USB Drives
1501
+ // USB Drives (older macOS report storage devices under SPUSBDataType)
1489
1502
  try {
1490
- const devices = linesUSB.join('\n').replaceAll('Media:\n ', 'Model:').split('\n\n Product ID:');
1503
+ const devices = linesUSB.join('\n').replace(/Media:\n /g, 'Model:').split('\n\n Product ID:');
1491
1504
  devices.shift();
1492
1505
  devices.forEach((device) => {
1493
1506
  const lines = device.split('\n');
1494
1507
  const sizeStr = util.getValue(lines, 'Capacity', ':', true).trim();
1495
- const BSDName = util.getValue(lines, 'BSD Name', ':', true).trim();
1508
+ const BSDName = util.sanitizeShellString(util.getValue(lines, 'BSD Name', ':', true).trim(), true);
1496
1509
  if (sizeStr) {
1497
1510
  let sizeValue = 0;
1498
1511
  if (sizeStr.indexOf('(') >= 0) {
@@ -1513,7 +1526,7 @@ function diskLayout(callback) {
1513
1526
  result.push({
1514
1527
  device: BSDName,
1515
1528
  type: 'USB',
1516
- name: util.getValue(lines, 'Model', ':', true).trim().replaceAll(':', ''),
1529
+ name: util.getValue(lines, 'Model', ':', true).trim().replace(/:/g, ''),
1517
1530
  vendor: getVendorFromModel(util.getValue(lines, 'Model', ':', true).trim()),
1518
1531
  size: sizeValue,
1519
1532
  bytesPerSector: null,
@@ -1538,6 +1551,80 @@ function diskLayout(callback) {
1538
1551
  } catch {
1539
1552
  util.noop();
1540
1553
  }
1554
+ // External drives (USB, Thunderbolt, ...) via SPStorageDataType
1555
+ // only add drives not already reported by the SATA/NVMe/USB data types above
1556
+ try {
1557
+ const seen = {};
1558
+ result.forEach((d) => {
1559
+ const m = (d.BSDName || '').match(/disk\d+/);
1560
+ if (m) {
1561
+ seen[m[0]] = true;
1562
+ }
1563
+ });
1564
+ const devices = linesStorage.join('\n').split(' Free:');
1565
+ devices.shift();
1566
+ devices.forEach((device) => {
1567
+ const lines = device.split('\n');
1568
+ const internal = util.getValue(lines, 'Internal', ':', true).trim().toLowerCase();
1569
+ if (internal !== 'no') {
1570
+ return;
1571
+ }
1572
+ const bsdMatch = util
1573
+ .getValue(lines, 'BSD Name', ':', true)
1574
+ .trim()
1575
+ .match(/disk\d+/);
1576
+ const BSDName = bsdMatch ? bsdMatch[0] : '';
1577
+ if (!BSDName || seen[BSDName]) {
1578
+ return;
1579
+ }
1580
+ const sizeStr = util.getValue(lines, 'Capacity', ':', true).trim();
1581
+ if (sizeStr) {
1582
+ let sizeValue = 0;
1583
+ if (sizeStr.indexOf('(') >= 0) {
1584
+ sizeValue = parseInt(
1585
+ sizeStr
1586
+ .match(/\(([^)]+)\)/)[1]
1587
+ .replace(/\./g, '')
1588
+ .replace(/,/g, '')
1589
+ .replace(/\s/g, ''),
1590
+ 10
1591
+ );
1592
+ }
1593
+ if (!sizeValue) {
1594
+ sizeValue = parseInt(sizeStr, 10);
1595
+ }
1596
+ if (sizeValue) {
1597
+ seen[BSDName] = true;
1598
+ const protocol = util.getValue(lines, 'Protocol', ':', true).trim();
1599
+ const model = util.getValue(lines, 'Device Name', ':', true).trim();
1600
+ result.push({
1601
+ device: BSDName,
1602
+ type: protocol && protocol !== 'USB' ? protocol : 'USB',
1603
+ name: model,
1604
+ vendor: getVendorFromModel(model),
1605
+ size: sizeValue,
1606
+ bytesPerSector: null,
1607
+ totalCylinders: null,
1608
+ totalHeads: null,
1609
+ totalSectors: null,
1610
+ totalTracks: null,
1611
+ tracksPerCylinder: null,
1612
+ sectorsPerTrack: null,
1613
+ firmwareRevision: '',
1614
+ serialNum: '',
1615
+ interfaceType: protocol || 'USB',
1616
+ smartStatus: 'unknown',
1617
+ temperature: null,
1618
+ BSDName: BSDName
1619
+ });
1620
+ cmd = cmd + 'printf "\n' + BSDName + '|"; diskutil info /dev/' + BSDName + ' | grep SMART;';
1621
+ cmdFullSmart += `${cmdFullSmart ? 'printf ",";' : ''}smartctl -a -j ${BSDName};`;
1622
+ }
1623
+ }
1624
+ });
1625
+ } catch {
1626
+ util.noop();
1627
+ }
1541
1628
  // check S.M.A.R.T. status
1542
1629
  if (cmdFullSmart) {
1543
1630
  exec(cmdFullSmart, { maxBuffer: 1024 * 1024 }, (error, stdout) => {