etcher-sdk
Version:
150 lines • 5.45 kB
JavaScript
"use strict";
/*
* Copyright 2018 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.BlockDeviceAdapter = void 0;
const _debug = require("debug");
const drivelist_1 = require("drivelist");
const block_device_1 = require("../../source-destination/block-device");
const utils_1 = require("../../utils");
const adapter_1 = require("./adapter");
const debug = _debug('etcher-sdk:block-device-adapter');
const SCAN_INTERVAL = 1000;
const USBBOOT_RPI_COMPUTE_MODULE_NAMES = [
'0001',
'RPi-MSD- 0001',
'File-Stor Gadget',
'Linux File-Stor_Gadget',
'Linux File-Stor Gadget',
'Linux File-Stor Gadget USB Device',
'Linux File-Stor Gadget Media',
];
function looksLikeComputeModule(description) {
for (const name of USBBOOT_RPI_COMPUTE_MODULE_NAMES) {
if (description.startsWith(name)) {
return true;
}
}
return false;
}
function driveKey(drive) {
return [
drive.device,
drive.size,
drive.description,
drive.mountpoints
.map((m) => m.path)
.sort()
.join(','),
].join('|');
}
class BlockDeviceAdapter extends adapter_1.Adapter {
constructor({ includeSystemDrives = () => false, includeVirtualDrives = () => false, unmountOnSuccess = false, write = false, direct = true, }) {
super();
this.drives = new Map();
this.running = false;
this.ready = false;
this.includeSystemDrives = includeSystemDrives;
this.includeVitualDrives = includeVirtualDrives;
this.unmountOnSuccess = unmountOnSuccess;
this.oWrite = write;
this.oDirect = direct;
}
start() {
this.running = true;
this.scanLoop();
}
stop() {
this.running = false;
this.ready = false;
this.drives.clear();
}
async scanLoop() {
while (this.running) {
await this.scan();
if (!this.ready) {
this.ready = true;
this.emit('ready');
}
await (0, utils_1.delay)(SCAN_INTERVAL);
}
}
async scan() {
const drives = await this.listDrives();
if (this.running) {
// we may have been stopped while listing the drives.
const oldDevices = new Set(this.drives.keys());
const newDevices = new Set(drives.keys());
for (const removed of (0, utils_1.difference)(oldDevices, newDevices)) {
this.emit('detach', this.drives.get(removed));
this.drives.delete(removed);
}
for (const added of (0, utils_1.difference)(newDevices, oldDevices)) {
const drive = drives.get(added);
const blockDevice = new block_device_1.BlockDevice({
drive: drive,
unmountOnSuccess: this.unmountOnSuccess,
write: this.oWrite,
direct: this.oDirect,
});
this.emit('attach', blockDevice);
this.drives.set(added, blockDevice);
}
}
}
async listDrives() {
let drives;
const result = new Map();
try {
drives = await (0, drivelist_1.list)();
}
catch (error) {
debug(error);
this.emit('error', error);
return result;
}
for (const drive of drives) {
if (!(
// Always ignore RAID attached devices, as they are in danger-country;
// Even flashing RAIDs intentionally can have unintended effects
(drive.busType !== 'RAID' &&
// Exclude errored drives
!drive.error &&
// Exclude system drives if needed
(this.includeSystemDrives() || !drive.isSystem) &&
// Exclude drives with no size
typeof drive.size === 'number' &&
// Exclude virtual drives (DMG, TimeMachine, ... on macOS)
(this.includeVitualDrives() || !drive.isVirtual)))) {
continue;
}
const displayName = /PhysicalDrive/i.test(drive.device) && drive.mountpoints.length
? drive.mountpoints.map((m) => m.path).join(', ') // Windows
: drive.device;
const resultDrive = { ...drive, displayName };
if (looksLikeComputeModule(resultDrive.description)) {
resultDrive.description = 'Compute Module';
// TODO: Should this be in the sdk?
resultDrive.icon = 'raspberrypi';
resultDrive.isSystem = false;
}
result.set(driveKey(drive), resultDrive);
}
return result;
}
}
exports.BlockDeviceAdapter = BlockDeviceAdapter;
//# sourceMappingURL=block-device.js.map