UNPKG

etcher-sdk

Version:
150 lines 5.45 kB
"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