@ohos-ports/drivelist 12.0.2-beta.1
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/CHANGELOG.md +732 -0
- package/LICENSE +177 -0
- package/README.md +215 -0
- package/build/Release/drivelist.node +0 -0
- package/js/index.d.ts +39 -0
- package/js/index.js +84 -0
- package/js/index.js.map +1 -0
- package/js/lsblk/index.d.ts +3 -0
- package/js/lsblk/index.js +104 -0
- package/js/lsblk/index.js.map +1 -0
- package/js/lsblk/json.d.ts +31 -0
- package/js/lsblk/json.js +114 -0
- package/js/lsblk/json.js.map +1 -0
- package/js/lsblk/pairs.d.ts +2 -0
- package/js/lsblk/pairs.js +158 -0
- package/js/lsblk/pairs.js.map +1 -0
- package/lib/index.ts +113 -0
- package/lib/lsblk/index.ts +126 -0
- package/lib/lsblk/json.ts +155 -0
- package/lib/lsblk/pairs.ts +188 -0
- package/package.json +84 -0
- package/src/darwin/REDiskList.h +41 -0
- package/src/darwin/REDiskList.m +61 -0
- package/src/darwin/list.mm +185 -0
- package/src/device-descriptor.cpp +125 -0
- package/src/drivelist.cpp +69 -0
- package/src/drivelist.hpp +65 -0
- package/src/linux/list.cpp +29 -0
- package/src/windows/list.cpp +741 -0
- package/src/windows/list.hpp +108 -0
package/js/lsblk/json.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2018 Balena.io
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.parse = exports.transform = void 0;
|
|
19
|
+
const path_1 = require("path");
|
|
20
|
+
const _1 = require(".");
|
|
21
|
+
function getMountpoints(children) {
|
|
22
|
+
return children
|
|
23
|
+
.filter((child) => {
|
|
24
|
+
return child.mountpoint;
|
|
25
|
+
})
|
|
26
|
+
.map((child) => {
|
|
27
|
+
return {
|
|
28
|
+
path: child.mountpoint,
|
|
29
|
+
label: child.label || child.partlabel,
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function getDescription(device) {
|
|
34
|
+
const description = [
|
|
35
|
+
device.label || '',
|
|
36
|
+
device.vendor || '',
|
|
37
|
+
device.model || '',
|
|
38
|
+
];
|
|
39
|
+
if (device.children) {
|
|
40
|
+
let subLabels = device.children
|
|
41
|
+
.filter((c) => (c.label && c.label !== device.label) || c.mountpoint)
|
|
42
|
+
.map((c) => c.label || c.mountpoint);
|
|
43
|
+
subLabels = Array.from(new Set(subLabels));
|
|
44
|
+
if (subLabels.length) {
|
|
45
|
+
description.push(`(${subLabels.join(', ')})`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return description.join(' ').replace(/\s+/g, ' ').trim();
|
|
49
|
+
}
|
|
50
|
+
function resolveDeviceName(name) {
|
|
51
|
+
if (!name) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
if (!path_1.posix.isAbsolute(name)) {
|
|
55
|
+
return path_1.posix.resolve('/dev', name);
|
|
56
|
+
}
|
|
57
|
+
return name;
|
|
58
|
+
}
|
|
59
|
+
function transform(data) {
|
|
60
|
+
return data.blockdevices
|
|
61
|
+
.map((device) => Object.assign({}, device, {
|
|
62
|
+
name: resolveDeviceName(device.name),
|
|
63
|
+
kname: resolveDeviceName(device.kname),
|
|
64
|
+
}))
|
|
65
|
+
.filter((device) =>
|
|
66
|
+
// Omit loop devices, CD/DVD drives, and RAM
|
|
67
|
+
!device.name.startsWith('/dev/loop') &&
|
|
68
|
+
!device.name.startsWith('/dev/sr') &&
|
|
69
|
+
!device.name.startsWith('/dev/ram'))
|
|
70
|
+
.map((device) => {
|
|
71
|
+
const isVirtual = device.subsystems
|
|
72
|
+
? /^(block)$/i.test(device.subsystems)
|
|
73
|
+
: null;
|
|
74
|
+
const isSCSI = device.tran
|
|
75
|
+
? /^(sata|scsi|ata|ide|pci)$/i.test(device.tran)
|
|
76
|
+
: null;
|
|
77
|
+
const isUSB = device.tran ? /^(usb)$/i.test(device.tran) : null;
|
|
78
|
+
const isReadOnly = Number(device.ro) === 1;
|
|
79
|
+
const isRemovable = Number(device.rm) === 1 ||
|
|
80
|
+
Number(device.hotplug) === 1 ||
|
|
81
|
+
Boolean(isVirtual);
|
|
82
|
+
return {
|
|
83
|
+
enumerator: 'lsblk:json',
|
|
84
|
+
busType: (device.tran || 'UNKNOWN').toUpperCase(),
|
|
85
|
+
busVersion: null,
|
|
86
|
+
device: device.name,
|
|
87
|
+
devicePath: null,
|
|
88
|
+
raw: device.kname || device.name,
|
|
89
|
+
description: getDescription(device),
|
|
90
|
+
error: null,
|
|
91
|
+
size: Number(device.size) || null,
|
|
92
|
+
blockSize: Number(device['phy-sec']) || 512,
|
|
93
|
+
logicalBlockSize: Number(device['log-sec']) || 512,
|
|
94
|
+
mountpoints: device.children
|
|
95
|
+
? getMountpoints(device.children)
|
|
96
|
+
: getMountpoints([device]),
|
|
97
|
+
isReadOnly,
|
|
98
|
+
isSystem: !isRemovable && !isVirtual,
|
|
99
|
+
isVirtual,
|
|
100
|
+
isRemovable,
|
|
101
|
+
isCard: null,
|
|
102
|
+
isSCSI,
|
|
103
|
+
isUSB,
|
|
104
|
+
isUAS: null,
|
|
105
|
+
partitionTableType: (0, _1.getPartitionTableType)(device.pttype),
|
|
106
|
+
};
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
exports.transform = transform;
|
|
110
|
+
function parse(stdout) {
|
|
111
|
+
return transform(JSON.parse(stdout));
|
|
112
|
+
}
|
|
113
|
+
exports.parse = parse;
|
|
114
|
+
//# sourceMappingURL=json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../lib/lsblk/json.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2018 Balena.io
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.parse = void 0;
|
|
19
|
+
const _1 = require(".");
|
|
20
|
+
function parseLsblkLine(line) {
|
|
21
|
+
const data = {};
|
|
22
|
+
let offset = 0;
|
|
23
|
+
let key = '';
|
|
24
|
+
let value = '';
|
|
25
|
+
const keyChar = /[^"=]/;
|
|
26
|
+
const whitespace = /\s+/;
|
|
27
|
+
const escape = '\\';
|
|
28
|
+
let state = 'key';
|
|
29
|
+
while (offset < line.length) {
|
|
30
|
+
if (state === 'key') {
|
|
31
|
+
while (keyChar.test(line[offset])) {
|
|
32
|
+
key += line[offset];
|
|
33
|
+
offset += 1;
|
|
34
|
+
}
|
|
35
|
+
if (line[offset] === '=') {
|
|
36
|
+
state = 'value';
|
|
37
|
+
offset += 1;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else if (state === 'value') {
|
|
41
|
+
if (line[offset] !== '"') {
|
|
42
|
+
throw new Error(`Expected '"', saw "${line[offset]}"`);
|
|
43
|
+
}
|
|
44
|
+
offset += 1;
|
|
45
|
+
while (line[offset - 1] === escape ||
|
|
46
|
+
(line[offset - 1] !== escape && line[offset] !== '"')) {
|
|
47
|
+
value += line[offset];
|
|
48
|
+
offset += 1;
|
|
49
|
+
}
|
|
50
|
+
if (line[offset] !== '"') {
|
|
51
|
+
throw new Error(`Expected '"', saw "${line[offset]}"`);
|
|
52
|
+
}
|
|
53
|
+
offset += 1;
|
|
54
|
+
data[key.toLowerCase()] = value.trim();
|
|
55
|
+
key = '';
|
|
56
|
+
value = '';
|
|
57
|
+
state = 'space';
|
|
58
|
+
}
|
|
59
|
+
else if (state === 'space') {
|
|
60
|
+
while (whitespace.test(line[offset])) {
|
|
61
|
+
offset += 1;
|
|
62
|
+
}
|
|
63
|
+
state = 'key';
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
throw new Error(`Undefined state "${state}"`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return data;
|
|
70
|
+
}
|
|
71
|
+
function parseLsblk(output) {
|
|
72
|
+
return output.trim().split(/\r?\n/g).map(parseLsblkLine);
|
|
73
|
+
}
|
|
74
|
+
function consolidate(devices) {
|
|
75
|
+
const primaries = devices.filter((device) => {
|
|
76
|
+
return (device.type === 'disk' &&
|
|
77
|
+
!device.name.startsWith('ram') &&
|
|
78
|
+
!device.name.startsWith('sr'));
|
|
79
|
+
});
|
|
80
|
+
return primaries.map((device) => {
|
|
81
|
+
const children = devices.filter((child) => {
|
|
82
|
+
return (['disk', 'part'].includes(child.type) &&
|
|
83
|
+
child.name.startsWith(device.name));
|
|
84
|
+
});
|
|
85
|
+
return Object.assign({}, device, {
|
|
86
|
+
mountpoints: children
|
|
87
|
+
.filter((child) => child.mountpoint)
|
|
88
|
+
.map((child) => {
|
|
89
|
+
return {
|
|
90
|
+
path: child.mountpoint,
|
|
91
|
+
label: child.label,
|
|
92
|
+
};
|
|
93
|
+
}),
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
function getDescription(device) {
|
|
98
|
+
const description = [
|
|
99
|
+
device.label || '',
|
|
100
|
+
device.vendor || '',
|
|
101
|
+
device.model || '',
|
|
102
|
+
];
|
|
103
|
+
if (device.mountpoints.length) {
|
|
104
|
+
let subLabels = device.mountpoints
|
|
105
|
+
.filter((c) => {
|
|
106
|
+
return (c.label && c.label !== device.label) || c.path;
|
|
107
|
+
})
|
|
108
|
+
.map((c) => {
|
|
109
|
+
return c.label || c.path;
|
|
110
|
+
});
|
|
111
|
+
subLabels = Array.from(new Set(subLabels));
|
|
112
|
+
if (subLabels.length) {
|
|
113
|
+
description.push(`(${subLabels.join(', ')})`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return description.join(' ').replace(/\s+/g, ' ').trim();
|
|
117
|
+
}
|
|
118
|
+
function parse(stdout) {
|
|
119
|
+
const devices = consolidate(parseLsblk(stdout));
|
|
120
|
+
return devices.map((device) => {
|
|
121
|
+
const isVirtual = device.subsystems
|
|
122
|
+
? /^block$/i.test(device.subsystems)
|
|
123
|
+
: null;
|
|
124
|
+
const isSCSI = device.tran
|
|
125
|
+
? /^(?:sata|scsi|ata|ide|pci)$/i.test(device.tran)
|
|
126
|
+
: null;
|
|
127
|
+
const isUSB = device.tran ? /^usb$/i.test(device.tran) : null;
|
|
128
|
+
const isReadOnly = Number(device.ro) === 1;
|
|
129
|
+
const isRemovable = Number(device.rm) === 1 ||
|
|
130
|
+
Number(device.hotplug) === 1 ||
|
|
131
|
+
Boolean(isVirtual);
|
|
132
|
+
return {
|
|
133
|
+
enumerator: 'lsblk:pairs',
|
|
134
|
+
busType: (device.tran || 'UNKNOWN').toUpperCase(),
|
|
135
|
+
busVersion: null,
|
|
136
|
+
device: '/dev/' + device.name,
|
|
137
|
+
devicePath: null,
|
|
138
|
+
raw: '/dev/' + device.name,
|
|
139
|
+
description: getDescription(device) || device.name,
|
|
140
|
+
error: null,
|
|
141
|
+
size: Number(device.size) || null,
|
|
142
|
+
blockSize: Number(device['phy-sec']) || 512,
|
|
143
|
+
logicalBlockSize: Number(device['log-sec']) || 512,
|
|
144
|
+
mountpoints: device.mountpoints,
|
|
145
|
+
isReadOnly,
|
|
146
|
+
isSystem: !isRemovable && !isVirtual,
|
|
147
|
+
isVirtual,
|
|
148
|
+
isRemovable,
|
|
149
|
+
isCard: null,
|
|
150
|
+
isSCSI,
|
|
151
|
+
isUSB,
|
|
152
|
+
isUAS: null,
|
|
153
|
+
partitionTableType: (0, _1.getPartitionTableType)(device.pttype),
|
|
154
|
+
};
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
exports.parse = parse;
|
|
158
|
+
//# sourceMappingURL=pairs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pairs.js","sourceRoot":"","sources":["../../lib/lsblk/pairs.ts"],"names":[],"mappings":"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"}
|
package/lib/index.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2016 Balena.io
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @module drivelist
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import bindings = require('bindings');
|
|
22
|
+
import { platform } from 'os';
|
|
23
|
+
|
|
24
|
+
import { lsblk } from './lsblk';
|
|
25
|
+
|
|
26
|
+
export interface Mountpoint {
|
|
27
|
+
path: string;
|
|
28
|
+
label: string | null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface Drive {
|
|
32
|
+
blockSize: number;
|
|
33
|
+
busType: string;
|
|
34
|
+
busVersion: null;
|
|
35
|
+
description: string;
|
|
36
|
+
device: string;
|
|
37
|
+
devicePath: string | null;
|
|
38
|
+
enumerator: string;
|
|
39
|
+
error: null;
|
|
40
|
+
isCard: null;
|
|
41
|
+
isReadOnly: boolean;
|
|
42
|
+
isRemovable: boolean;
|
|
43
|
+
isSCSI: boolean | null;
|
|
44
|
+
isSystem: boolean;
|
|
45
|
+
isUAS: null;
|
|
46
|
+
isUSB: boolean | null;
|
|
47
|
+
isVirtual: boolean | null;
|
|
48
|
+
logicalBlockSize: number;
|
|
49
|
+
mountpoints: Mountpoint[];
|
|
50
|
+
raw: string;
|
|
51
|
+
size: number | null;
|
|
52
|
+
partitionTableType: 'mbr' | 'gpt' | null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const drivelistBindings = bindings('drivelist');
|
|
56
|
+
|
|
57
|
+
function bindingsList(): Promise<Drive[]> {
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
drivelistBindings.list((error: Error, drives: Drive[]) => {
|
|
60
|
+
if (error != null) {
|
|
61
|
+
reject(error);
|
|
62
|
+
} else {
|
|
63
|
+
resolve(drives);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function handleApfs(disks: Drive[]): void {
|
|
70
|
+
const apfs: Drive[] = [];
|
|
71
|
+
const other: Drive[] = [];
|
|
72
|
+
for (const disk of disks) {
|
|
73
|
+
if (disk.description === 'AppleAPFSMedia') {
|
|
74
|
+
apfs.push(disk);
|
|
75
|
+
} else {
|
|
76
|
+
other.push(disk);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
for (const disk of apfs) {
|
|
80
|
+
const source = other.find(
|
|
81
|
+
(d) => d.devicePath === disk.devicePath && !d.isVirtual,
|
|
82
|
+
);
|
|
83
|
+
if (source !== undefined) {
|
|
84
|
+
source.mountpoints.push(...disk.mountpoints);
|
|
85
|
+
disk.isVirtual = true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @summary List available drives
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* const drivelist = require('drivelist');
|
|
95
|
+
*
|
|
96
|
+
* const drives = await drivelist.list();
|
|
97
|
+
* drives.forEach((drive) => {
|
|
98
|
+
* console.log(drive);
|
|
99
|
+
* });
|
|
100
|
+
*/
|
|
101
|
+
export async function list(): Promise<Drive[]> {
|
|
102
|
+
const plat = platform();
|
|
103
|
+
if (plat === 'win32') {
|
|
104
|
+
return await bindingsList();
|
|
105
|
+
} else if (plat === 'darwin') {
|
|
106
|
+
const disks = await bindingsList();
|
|
107
|
+
handleApfs(disks);
|
|
108
|
+
return disks;
|
|
109
|
+
} else if (plat === 'linux' || plat === 'openharmony') {
|
|
110
|
+
return await lsblk();
|
|
111
|
+
}
|
|
112
|
+
throw new Error(`Your OS is not supported by this module: ${platform()}`);
|
|
113
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2018 Balena.io
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { execFile } from 'child_process';
|
|
18
|
+
import { promises as fs } from 'fs';
|
|
19
|
+
import { join, resolve } from 'path';
|
|
20
|
+
import { promisify } from 'util';
|
|
21
|
+
|
|
22
|
+
import { Drive } from '..';
|
|
23
|
+
import { parse as parseJSON } from './json';
|
|
24
|
+
import { parse as parsePairs } from './pairs';
|
|
25
|
+
|
|
26
|
+
const execFileAsync = promisify(execFile);
|
|
27
|
+
|
|
28
|
+
const DISK_PATH_DIR = '/dev/disk/by-path/';
|
|
29
|
+
|
|
30
|
+
let SUPPORTS_JSON = true;
|
|
31
|
+
let SUPPORTS_PTTYPE = true;
|
|
32
|
+
|
|
33
|
+
export function getPartitionTableType(
|
|
34
|
+
pttype?: 'gpt' | 'dos',
|
|
35
|
+
): 'gpt' | 'mbr' | null {
|
|
36
|
+
if (pttype === 'gpt') {
|
|
37
|
+
return 'gpt';
|
|
38
|
+
} else if (pttype === 'dos') {
|
|
39
|
+
return 'mbr';
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function getDevicePaths(): Promise<Map<string, string>> {
|
|
45
|
+
const mapping = new Map();
|
|
46
|
+
for (const filename of await fs.readdir(DISK_PATH_DIR)) {
|
|
47
|
+
const linkPath = join(DISK_PATH_DIR, filename);
|
|
48
|
+
let link: string;
|
|
49
|
+
try {
|
|
50
|
+
link = await fs.readlink(linkPath);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const devicePath = resolve(DISK_PATH_DIR, link);
|
|
55
|
+
mapping.set(devicePath, linkPath);
|
|
56
|
+
}
|
|
57
|
+
return mapping;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function addDevicePaths(devices: Drive[]): Promise<void> {
|
|
61
|
+
const devicePaths = await getDevicePaths();
|
|
62
|
+
for (const device of devices) {
|
|
63
|
+
device.devicePath = devicePaths.get(device.device) || null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function getOutput(command: string, ...args: string[]) {
|
|
68
|
+
const { stdout } = await execFileAsync(command, args);
|
|
69
|
+
return stdout;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function lsblkJSON(): Promise<Drive[]> {
|
|
73
|
+
return parseJSON(
|
|
74
|
+
await getOutput(
|
|
75
|
+
'lsblk',
|
|
76
|
+
'--bytes',
|
|
77
|
+
'--all',
|
|
78
|
+
'--json',
|
|
79
|
+
'--paths',
|
|
80
|
+
'--output-all',
|
|
81
|
+
),
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function getLsblkPairsOutput() {
|
|
86
|
+
if (SUPPORTS_PTTYPE) {
|
|
87
|
+
try {
|
|
88
|
+
return await getOutput(
|
|
89
|
+
'lsblk',
|
|
90
|
+
'--bytes',
|
|
91
|
+
'--all',
|
|
92
|
+
'--pairs',
|
|
93
|
+
'-o',
|
|
94
|
+
'+pttype',
|
|
95
|
+
);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
SUPPORTS_PTTYPE = false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return await getOutput('lsblk', '--bytes', '--all', '--pairs');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async function lsblkPairs(): Promise<Drive[]> {
|
|
104
|
+
return parsePairs(await getLsblkPairsOutput());
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function $lsblk(): Promise<Drive[]> {
|
|
108
|
+
if (SUPPORTS_JSON) {
|
|
109
|
+
try {
|
|
110
|
+
return await lsblkJSON();
|
|
111
|
+
} catch (error) {
|
|
112
|
+
SUPPORTS_JSON = false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return await lsblkPairs();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export async function lsblk(): Promise<Drive[]> {
|
|
119
|
+
const drives = await $lsblk();
|
|
120
|
+
try {
|
|
121
|
+
await addDevicePaths(drives);
|
|
122
|
+
} catch (error) {
|
|
123
|
+
// Couldn't add device paths
|
|
124
|
+
}
|
|
125
|
+
return drives;
|
|
126
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2018 Balena.io
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { posix } from 'path';
|
|
18
|
+
|
|
19
|
+
import { getPartitionTableType } from '.';
|
|
20
|
+
import { Drive, Mountpoint } from '..';
|
|
21
|
+
|
|
22
|
+
interface LsblkJsonOutput {
|
|
23
|
+
blockdevices: LsblkJsonOutputDevice[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface LsblkJsonOutputDevice {
|
|
27
|
+
children: LsblkJsonOutputDeviceChild[];
|
|
28
|
+
hotplug?: string;
|
|
29
|
+
kname?: string;
|
|
30
|
+
label: string | null;
|
|
31
|
+
'log-sec'?: string;
|
|
32
|
+
model: string | null;
|
|
33
|
+
mountpoint: string | null;
|
|
34
|
+
name: string;
|
|
35
|
+
partlabel: string | null;
|
|
36
|
+
'phy-sec'?: string;
|
|
37
|
+
rm?: string;
|
|
38
|
+
ro?: string;
|
|
39
|
+
size?: string;
|
|
40
|
+
subsystems?: string;
|
|
41
|
+
tran?: string;
|
|
42
|
+
vendor: string | null;
|
|
43
|
+
pttype?: 'gpt' | 'dos';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface LsblkJsonOutputDeviceChild {
|
|
47
|
+
label: string | null;
|
|
48
|
+
mountpoint?: string;
|
|
49
|
+
partlabel: string | null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function getMountpoints(
|
|
53
|
+
children: Array<LsblkJsonOutputDeviceChild | LsblkJsonOutputDevice>,
|
|
54
|
+
): Mountpoint[] {
|
|
55
|
+
return children
|
|
56
|
+
.filter((child) => {
|
|
57
|
+
return child.mountpoint;
|
|
58
|
+
})
|
|
59
|
+
.map((child) => {
|
|
60
|
+
return {
|
|
61
|
+
path: child.mountpoint!,
|
|
62
|
+
label: child.label || child.partlabel,
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function getDescription(device: LsblkJsonOutputDevice): string {
|
|
68
|
+
const description = [
|
|
69
|
+
device.label || '',
|
|
70
|
+
device.vendor || '',
|
|
71
|
+
device.model || '',
|
|
72
|
+
];
|
|
73
|
+
if (device.children) {
|
|
74
|
+
let subLabels = device.children
|
|
75
|
+
.filter((c) => (c.label && c.label !== device.label) || c.mountpoint)
|
|
76
|
+
.map((c) => c.label || c.mountpoint);
|
|
77
|
+
subLabels = Array.from(new Set(subLabels));
|
|
78
|
+
if (subLabels.length) {
|
|
79
|
+
description.push(`(${subLabels.join(', ')})`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return description.join(' ').replace(/\s+/g, ' ').trim();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function resolveDeviceName(name?: string): string | null {
|
|
86
|
+
if (!name) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
if (!posix.isAbsolute(name)) {
|
|
90
|
+
return posix.resolve('/dev', name);
|
|
91
|
+
}
|
|
92
|
+
return name;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function transform(data: LsblkJsonOutput): Drive[] {
|
|
96
|
+
return data.blockdevices
|
|
97
|
+
.map((device) =>
|
|
98
|
+
Object.assign({}, device, {
|
|
99
|
+
name: resolveDeviceName(device.name),
|
|
100
|
+
kname: resolveDeviceName(device.kname),
|
|
101
|
+
}),
|
|
102
|
+
)
|
|
103
|
+
.filter(
|
|
104
|
+
(device) =>
|
|
105
|
+
// Omit loop devices, CD/DVD drives, and RAM
|
|
106
|
+
!device.name.startsWith('/dev/loop') &&
|
|
107
|
+
!device.name.startsWith('/dev/sr') &&
|
|
108
|
+
!device.name.startsWith('/dev/ram'),
|
|
109
|
+
)
|
|
110
|
+
.map(
|
|
111
|
+
(device: LsblkJsonOutputDevice): Drive => {
|
|
112
|
+
const isVirtual = device.subsystems
|
|
113
|
+
? /^(block)$/i.test(device.subsystems)
|
|
114
|
+
: null;
|
|
115
|
+
const isSCSI = device.tran
|
|
116
|
+
? /^(sata|scsi|ata|ide|pci)$/i.test(device.tran)
|
|
117
|
+
: null;
|
|
118
|
+
const isUSB = device.tran ? /^(usb)$/i.test(device.tran) : null;
|
|
119
|
+
const isReadOnly = Number(device.ro) === 1;
|
|
120
|
+
const isRemovable =
|
|
121
|
+
Number(device.rm) === 1 ||
|
|
122
|
+
Number(device.hotplug) === 1 ||
|
|
123
|
+
Boolean(isVirtual);
|
|
124
|
+
return {
|
|
125
|
+
enumerator: 'lsblk:json',
|
|
126
|
+
busType: (device.tran || 'UNKNOWN').toUpperCase(),
|
|
127
|
+
busVersion: null,
|
|
128
|
+
device: device.name,
|
|
129
|
+
devicePath: null,
|
|
130
|
+
raw: device.kname || device.name,
|
|
131
|
+
description: getDescription(device),
|
|
132
|
+
error: null,
|
|
133
|
+
size: Number(device.size) || null,
|
|
134
|
+
blockSize: Number(device['phy-sec']) || 512,
|
|
135
|
+
logicalBlockSize: Number(device['log-sec']) || 512,
|
|
136
|
+
mountpoints: device.children
|
|
137
|
+
? getMountpoints(device.children)
|
|
138
|
+
: getMountpoints([device]),
|
|
139
|
+
isReadOnly,
|
|
140
|
+
isSystem: !isRemovable && !isVirtual,
|
|
141
|
+
isVirtual,
|
|
142
|
+
isRemovable,
|
|
143
|
+
isCard: null,
|
|
144
|
+
isSCSI,
|
|
145
|
+
isUSB,
|
|
146
|
+
isUAS: null,
|
|
147
|
+
partitionTableType: getPartitionTableType(device.pttype),
|
|
148
|
+
};
|
|
149
|
+
},
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function parse(stdout: string): Drive[] {
|
|
154
|
+
return transform(JSON.parse(stdout));
|
|
155
|
+
}
|