mirror of
https://github.com/cmclark00/retro-imager.git
synced 2025-05-19 08:25:21 +01:00
Qt/QML edition
This commit is contained in:
commit
d7b361ba44
2168 changed files with 721948 additions and 0 deletions
16
dependencies/drivelist/.editorconfig
vendored
Normal file
16
dependencies/drivelist/.editorconfig
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
# editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.plist]
|
||||
indent_style = tab
|
467
dependencies/drivelist/.eslintrc.yml
vendored
Normal file
467
dependencies/drivelist/.eslintrc.yml
vendored
Normal file
|
@ -0,0 +1,467 @@
|
|||
env:
|
||||
browser: true
|
||||
commonjs: true
|
||||
es6: true
|
||||
node: true
|
||||
mocha: true
|
||||
extends: 'eslint:recommended'
|
||||
rules:
|
||||
|
||||
# Possible Errors
|
||||
|
||||
comma-dangle:
|
||||
- error
|
||||
- never
|
||||
no-cond-assign:
|
||||
- off
|
||||
no-console:
|
||||
- off
|
||||
no-constant-condition:
|
||||
- error
|
||||
no-control-regex:
|
||||
- error
|
||||
no-debugger:
|
||||
- error
|
||||
no-dupe-args:
|
||||
- error
|
||||
no-dupe-keys:
|
||||
- error
|
||||
no-duplicate-case:
|
||||
- error
|
||||
no-empty:
|
||||
- error
|
||||
no-empty-character-class:
|
||||
- error
|
||||
no-ex-assign:
|
||||
- error
|
||||
no-extra-boolean-cast:
|
||||
- error
|
||||
no-extra-parens:
|
||||
- error
|
||||
no-extra-semi:
|
||||
- error
|
||||
no-func-assign:
|
||||
- error
|
||||
no-inner-declarations:
|
||||
- error
|
||||
- both
|
||||
no-invalid-regexp:
|
||||
- error
|
||||
no-irregular-whitespace:
|
||||
- error
|
||||
no-negated-in-lhs:
|
||||
- error
|
||||
no-obj-calls:
|
||||
- error
|
||||
no-prototype-builtins:
|
||||
- error
|
||||
no-regex-spaces:
|
||||
- error
|
||||
no-sparse-arrays:
|
||||
- error
|
||||
no-unexpected-multiline:
|
||||
- error
|
||||
no-unreachable:
|
||||
- error
|
||||
no-unsafe-finally:
|
||||
- error
|
||||
use-isnan:
|
||||
- error
|
||||
valid-jsdoc:
|
||||
- error
|
||||
- requireReturn: false
|
||||
requireReturnDescription: false
|
||||
valid-typeof:
|
||||
- error
|
||||
|
||||
# Best Practices
|
||||
|
||||
accessor-pairs:
|
||||
- error
|
||||
array-callback-return:
|
||||
- error
|
||||
block-scoped-var:
|
||||
- error
|
||||
complexity:
|
||||
- off
|
||||
curly:
|
||||
- error
|
||||
default-case:
|
||||
- error
|
||||
dot-location:
|
||||
- error
|
||||
- property
|
||||
dot-notation:
|
||||
- error
|
||||
eqeqeq:
|
||||
- 1
|
||||
guard-for-in:
|
||||
- error
|
||||
no-alert:
|
||||
- error
|
||||
no-caller:
|
||||
- error
|
||||
no-case-declarations:
|
||||
- error
|
||||
no-div-regex:
|
||||
- error
|
||||
no-else-return:
|
||||
- error
|
||||
no-empty-function:
|
||||
- error
|
||||
no-empty-pattern:
|
||||
- error
|
||||
no-eq-null:
|
||||
- off
|
||||
no-eval:
|
||||
- error
|
||||
no-extend-native:
|
||||
- error
|
||||
no-extra-bind:
|
||||
- error
|
||||
no-extra-label:
|
||||
- error
|
||||
no-fallthrough:
|
||||
- error
|
||||
no-floating-decimal:
|
||||
- error
|
||||
no-implicit-coercion:
|
||||
- error
|
||||
no-implicit-globals:
|
||||
- error
|
||||
no-implied-eval:
|
||||
- error
|
||||
no-iterator:
|
||||
- error
|
||||
no-labels:
|
||||
- error
|
||||
no-lone-blocks:
|
||||
- error
|
||||
no-loop-func:
|
||||
- error
|
||||
no-multi-spaces:
|
||||
- error
|
||||
no-multi-str:
|
||||
- error
|
||||
no-native-reassign:
|
||||
- error
|
||||
no-new:
|
||||
- error
|
||||
no-new-func:
|
||||
- error
|
||||
no-new-wrappers:
|
||||
- error
|
||||
no-octal:
|
||||
- error
|
||||
no-octal-escape:
|
||||
- error
|
||||
no-proto:
|
||||
- error
|
||||
no-redeclare:
|
||||
- error
|
||||
no-return-assign:
|
||||
- error
|
||||
no-script-url:
|
||||
- error
|
||||
no-self-assign:
|
||||
- error
|
||||
no-self-compare:
|
||||
- error
|
||||
no-sequences:
|
||||
- error
|
||||
no-throw-literal:
|
||||
- error
|
||||
no-unmodified-loop-condition:
|
||||
- error
|
||||
no-unused-labels:
|
||||
- error
|
||||
no-useless-call:
|
||||
- error
|
||||
no-useless-concat:
|
||||
- error
|
||||
no-useless-escape:
|
||||
- error
|
||||
no-void:
|
||||
- error
|
||||
no-warning-comments:
|
||||
- off
|
||||
no-with:
|
||||
- error
|
||||
radix:
|
||||
- error
|
||||
vars-on-top:
|
||||
- off
|
||||
wrap-iife:
|
||||
- error
|
||||
- outside
|
||||
yoda:
|
||||
- error
|
||||
|
||||
# Strict mode
|
||||
|
||||
strict:
|
||||
- error
|
||||
- global
|
||||
|
||||
# Variables
|
||||
|
||||
no-catch-shadow:
|
||||
- error
|
||||
no-delete-var:
|
||||
- error
|
||||
no-label-var:
|
||||
- error
|
||||
no-shadow:
|
||||
- error
|
||||
no-shadow-restricted-names:
|
||||
- error
|
||||
no-undef:
|
||||
- error
|
||||
no-undef-init:
|
||||
- error
|
||||
no-unused-vars:
|
||||
- error
|
||||
no-use-before-define:
|
||||
- error
|
||||
|
||||
# NodeJS and CommonJS
|
||||
|
||||
callback-return:
|
||||
- error
|
||||
global-require:
|
||||
- off
|
||||
handle-callback-err:
|
||||
- error
|
||||
no-mixed-requires:
|
||||
- error
|
||||
no-new-require:
|
||||
- error
|
||||
no-path-concat:
|
||||
- error
|
||||
no-process-env:
|
||||
- off
|
||||
no-process-exit:
|
||||
- off
|
||||
no-sync:
|
||||
- off
|
||||
|
||||
# Stylistic Issues
|
||||
|
||||
array-bracket-spacing:
|
||||
- error
|
||||
- always
|
||||
block-spacing:
|
||||
- error
|
||||
brace-style:
|
||||
- error
|
||||
- 1tbs
|
||||
camelcase:
|
||||
- error
|
||||
comma-spacing:
|
||||
- error
|
||||
- before: false
|
||||
after: true
|
||||
comma-style:
|
||||
- error
|
||||
- last
|
||||
computed-property-spacing:
|
||||
- error
|
||||
- never
|
||||
consistent-this:
|
||||
- error
|
||||
- self
|
||||
eol-last:
|
||||
- error
|
||||
func-names:
|
||||
- error
|
||||
- never
|
||||
func-style:
|
||||
- error
|
||||
- expression
|
||||
id-blacklist:
|
||||
- error
|
||||
indent:
|
||||
- error
|
||||
- 2
|
||||
- SwitchCase: 1
|
||||
key-spacing:
|
||||
- error
|
||||
- beforeColon: false
|
||||
afterColon: true
|
||||
mode: strict
|
||||
keyword-spacing:
|
||||
- error
|
||||
- before: true
|
||||
after: true
|
||||
linebreak-style:
|
||||
- error
|
||||
- unix
|
||||
lines-around-comment:
|
||||
- error
|
||||
- beforeBlockComment: true
|
||||
afterBlockComment: false
|
||||
beforeLineComment: true
|
||||
afterLineComment: false
|
||||
allowBlockStart: true
|
||||
allowBlockEnd: false
|
||||
allowObjectStart: true
|
||||
allowObjectEnd: false
|
||||
allowArrayStart: true
|
||||
allowArrayEnd: false
|
||||
max-len:
|
||||
- error
|
||||
- code: 130
|
||||
comments: 150
|
||||
ignoreComments: false
|
||||
ignoreTrailingComments: false
|
||||
ignoreUrls: true
|
||||
max-statements-per-line:
|
||||
- error
|
||||
- max: 1
|
||||
new-parens:
|
||||
- error
|
||||
no-array-constructor:
|
||||
- error
|
||||
no-bitwise:
|
||||
- error
|
||||
no-continue:
|
||||
- error
|
||||
no-inline-comments:
|
||||
- error
|
||||
no-mixed-operators:
|
||||
- off
|
||||
no-mixed-spaces-and-tabs:
|
||||
- error
|
||||
no-multiple-empty-lines:
|
||||
- error
|
||||
- max: 1
|
||||
maxEOF: 1
|
||||
maxBOF: 0
|
||||
no-negated-condition:
|
||||
- error
|
||||
no-nested-ternary:
|
||||
- error
|
||||
no-new-object:
|
||||
- error
|
||||
no-plusplus:
|
||||
- error
|
||||
no-spaced-func:
|
||||
- error
|
||||
no-trailing-spaces:
|
||||
- error
|
||||
no-underscore-dangle:
|
||||
- error
|
||||
- allowAfterThis: false
|
||||
no-unneeded-ternary:
|
||||
- error
|
||||
no-whitespace-before-property:
|
||||
- error
|
||||
object-curly-newline:
|
||||
- error
|
||||
- minProperties: 1
|
||||
object-curly-spacing:
|
||||
- error
|
||||
- always
|
||||
object-property-newline:
|
||||
- error
|
||||
one-var:
|
||||
- error
|
||||
- never
|
||||
operator-assignment:
|
||||
- error
|
||||
- always
|
||||
operator-linebreak:
|
||||
- error
|
||||
- before
|
||||
quote-props:
|
||||
- error
|
||||
- as-needed
|
||||
quotes:
|
||||
- error
|
||||
- single
|
||||
require-jsdoc:
|
||||
- error
|
||||
- require:
|
||||
FunctionDeclaration: true
|
||||
ClassDeclaration: true
|
||||
MethodDefinition: true
|
||||
semi:
|
||||
- error
|
||||
- always
|
||||
semi-spacing:
|
||||
- error
|
||||
- before: false
|
||||
after: true
|
||||
space-before-blocks:
|
||||
- error
|
||||
space-before-function-paren:
|
||||
- error
|
||||
- never
|
||||
space-in-parens:
|
||||
- error
|
||||
- never
|
||||
space-infix-ops:
|
||||
- error
|
||||
spaced-comment:
|
||||
- error
|
||||
- always
|
||||
unicode-bom:
|
||||
- error
|
||||
|
||||
# ECMAScript 6
|
||||
|
||||
arrow-body-style:
|
||||
- error
|
||||
- always
|
||||
arrow-parens:
|
||||
- error
|
||||
- always
|
||||
arrow-spacing:
|
||||
- error
|
||||
- before: true
|
||||
after: true
|
||||
constructor-super:
|
||||
- error
|
||||
generator-star-spacing:
|
||||
- error
|
||||
- before: true
|
||||
after: false
|
||||
no-class-assign:
|
||||
- error
|
||||
no-confusing-arrow:
|
||||
- error
|
||||
no-const-assign:
|
||||
- error
|
||||
no-dupe-class-members:
|
||||
- error
|
||||
no-duplicate-imports:
|
||||
- error
|
||||
no-new-symbol:
|
||||
- error
|
||||
no-this-before-super:
|
||||
- error
|
||||
no-useless-computed-key:
|
||||
- error
|
||||
no-useless-constructor:
|
||||
- error
|
||||
no-useless-rename:
|
||||
- error
|
||||
no-var:
|
||||
- error
|
||||
prefer-const:
|
||||
- error
|
||||
prefer-reflect:
|
||||
- error
|
||||
prefer-spread:
|
||||
- error
|
||||
require-yield:
|
||||
- error
|
||||
rest-spread-spacing:
|
||||
- error
|
||||
template-curly-spacing:
|
||||
- error
|
||||
- never
|
||||
yield-star-spacing:
|
||||
- error
|
||||
- before: true
|
||||
after: false
|
29
dependencies/drivelist/.gitignore
vendored
Normal file
29
dependencies/drivelist/.gitignore
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||
build
|
||||
|
||||
# Dependency directory
|
||||
# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
|
||||
node_modules
|
||||
prebuilds
|
9
dependencies/drivelist/.npmignore
vendored
Normal file
9
dependencies/drivelist/.npmignore
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
.*
|
||||
*.yml
|
||||
|
||||
build
|
||||
doc
|
||||
example
|
||||
tests
|
||||
prebuilds
|
||||
ci
|
41
dependencies/drivelist/.resinci.yml
vendored
Normal file
41
dependencies/drivelist/.resinci.yml
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
---
|
||||
npm:
|
||||
environment:
|
||||
- name: CCACHE_TEMPDIR
|
||||
value: /tmp/.ccache-temp
|
||||
- name: CCACHE_COMPRESS
|
||||
value: 1
|
||||
- name: CC
|
||||
value: clang
|
||||
- name: CXX
|
||||
value: clang++
|
||||
platforms:
|
||||
- name: linux
|
||||
os: ubuntu
|
||||
architecture: x86_64
|
||||
node_versions:
|
||||
- "10"
|
||||
- "8"
|
||||
- "6"
|
||||
- name: linux
|
||||
os: ubuntu
|
||||
architecture: x86
|
||||
node_versions:
|
||||
- "8"
|
||||
- "6"
|
||||
- name: darwin
|
||||
os: macos
|
||||
architecture: x86_64
|
||||
node_versions:
|
||||
- "6"
|
||||
- name: windows
|
||||
os: windows
|
||||
architecture: x86_64
|
||||
node_versions:
|
||||
- "6"
|
||||
- name: windows
|
||||
os: windows
|
||||
architecture: x86
|
||||
node_versions:
|
||||
- "6"
|
||||
|
39
dependencies/drivelist/.travis.yml
vendored
Normal file
39
dependencies/drivelist/.travis.yml
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 10
|
||||
- 8
|
||||
- 6
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
before_install:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
pip install --user -r requirements.txt;
|
||||
else
|
||||
pip2 install -r requirements.txt;
|
||||
fi
|
||||
script:
|
||||
- npm test
|
||||
compiler: clang-4.0
|
||||
env:
|
||||
global:
|
||||
- CCACHE_TEMPDIR=/tmp/.ccache-temp
|
||||
- CCACHE_COMPRESS=1
|
||||
- CC="clang"
|
||||
- CXX="clang++"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- libstdc++-5-dev
|
||||
notifications:
|
||||
email: false
|
||||
deploy:
|
||||
skip_cleanup: true
|
||||
provider: script
|
||||
script: ./ci/prebuild-publish.sh
|
||||
on:
|
||||
node: 10
|
||||
tags: true
|
||||
branch: master
|
606
dependencies/drivelist/CHANGELOG.md
vendored
Normal file
606
dependencies/drivelist/CHANGELOG.md
vendored
Normal file
|
@ -0,0 +1,606 @@
|
|||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file
|
||||
automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY!
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## 8.0.9 - 2019-11-06
|
||||
|
||||
* Avoid segfaulting on mac when some disk description fields are null [Alexis Svinartchouk]
|
||||
|
||||
## 8.0.8 - 2019-10-08
|
||||
|
||||
* Fix tests [Alexis Svinartchouk]
|
||||
* Fix typo in readme [Alexis Svinartchouk]
|
||||
|
||||
## 8.0.7 - 2019-09-20
|
||||
|
||||
* Update nan to ^2.14 to fix builds targetting electron 6 [Alexis Svinartchouk]
|
||||
|
||||
## 8.0.6 - 2019-03-20
|
||||
|
||||
* Update example in readme [Alexis Svinartchouk]
|
||||
|
||||
## 8.0.5 - 2019-03-20
|
||||
|
||||
* Update resin-lint to ^3.0.1 [Alexis Svinartchouk]
|
||||
|
||||
## 8.0.4 - 2019-03-19
|
||||
|
||||
* Unregister DASession callback to avoid crash [Robert Vojta]
|
||||
|
||||
## 8.0.3 - 2019-03-18
|
||||
|
||||
* Fix DASession and NSMutableArray leaks on macOS [Alexis Svinartchouk]
|
||||
|
||||
## 8.0.2 - 2019-03-04
|
||||
|
||||
* Fix isVirtual value on macOS [Robert Vojta]
|
||||
|
||||
## 8.0.1 - 2019-02-27
|
||||
|
||||
* Fix macOS crash when SD card is ejected [Robert Vojta]
|
||||
|
||||
## 8.0.0 - 2019-02-22
|
||||
|
||||
* Address PR comments [Alexis Svinartchouk]
|
||||
* Try `lsblk --pairs` if parsing `lsblk --json` fails [Alexis Svinartchouk]
|
||||
* Convert to typescript, use promises instead of callbacks [Alexis Svinartchouk]
|
||||
|
||||
## 7.0.3 - 2019-02-20
|
||||
|
||||
* Fix parsing lsblk --pairs output for disks with no partition table [Alexis Svinartchouk]
|
||||
|
||||
## 7.0.2 - 2019-02-20
|
||||
|
||||
* Update prebuild to ^8.1.2 [Alexis Svinartchouk]
|
||||
|
||||
## 7.0.1 - 2019-01-28
|
||||
|
||||
* Remove unused diskutil file and its tests [Alexis Svinartchouk]
|
||||
|
||||
## 7.0.0 - 2019-01-28
|
||||
|
||||
* Remove outdated docs. [Alexis Svinartchouk]
|
||||
* Feat(mac): Native implementation for drivelist [Robin Andersson]
|
||||
|
||||
## 6.4.6 - 2019-01-10
|
||||
|
||||
* Fix tests incorrect mountpoints [Lorenzo Alberto Maria Ambrosi]
|
||||
* Fix devices mountpoints for lsblk in pairs mode [Lorenzo Alberto Maria Ambrosi]
|
||||
|
||||
## 6.4.5 - 2019-01-10
|
||||
|
||||
* Fix tests incorrect device.size [Lorenzo Alberto Maria Ambrosi]
|
||||
* Fix linting errors & add specs with plist return value assertions [Robin Andersson]
|
||||
|
||||
## 6.4.4 - 2019-01-10
|
||||
|
||||
* Fix build on xcode 10.1 [Alexis Svinartchouk]
|
||||
|
||||
## v6.4.3 - 2018-09-10
|
||||
|
||||
* Lsblk: Fix listing of empty mountpoints [Jonas Hermsmeier]
|
||||
|
||||
## v6.4.2 - 2018-09-03
|
||||
|
||||
* Lsblk: Check `hotplug` to set `isRemovable` [Jonas Hermsmeier]
|
||||
* Ci: Add .resinci.yml [John (Jack) Brown]
|
||||
|
||||
## v6.4.1 - 2018-08-28
|
||||
|
||||
* Lsblk: Fix missing `devicePath` property [Jonas Hermsmeier]
|
||||
|
||||
## v6.4.0 - 2018-08-02
|
||||
|
||||
* Feat(diskutil): Populate devicePath on Mac OS #297 [Jonas Hermsmeier]
|
||||
|
||||
## v6.3.2 - 2018-08-02
|
||||
|
||||
* Fix(diskutil): Also probe Ejectable to determine removabililty #298 [Jonas Hermsmeier]
|
||||
|
||||
## v6.3.1 - 2018-08-01
|
||||
|
||||
* Test(lsblk): Add test case for root device mountpoints #293 [Jonas Hermsmeier]
|
||||
* Fix(lsblk): Enumerate mountpoints on root devices #293 [Jonas Hermsmeier]
|
||||
* Fix(lsblk): Fall back to mountpoint if no label given #293 [Jonas Hermsmeier]
|
||||
* Fix(lsblk): Resolve relative device names #293 [Jonas Hermsmeier]
|
||||
|
||||
## v6.3.0 - 2018-07-09
|
||||
|
||||
* Fix(linux): Fix pair consolidation for lsblk #255 [Jonas Hermsmeier]
|
||||
* Feat(lib): Use lsblk directly, parse json output #255 [Jonas Hermsmeier]
|
||||
|
||||
## v6.2.5 - 2018-07-06
|
||||
|
||||
* Fix(linux): Add flag to lsblk to list all devices #287 [Jonas Hermsmeier]
|
||||
|
||||
## v6.2.4 - 2018-07-04
|
||||
|
||||
* Fix(test): Add python requirements.txt for tests #288 [Jonas Hermsmeier]
|
||||
|
||||
## v6.2.3 - 2018-05-25
|
||||
|
||||
* Fix(src): Fix nan callback deprecation warning #284 [Jonas Hermsmeier]
|
||||
|
||||
## v6.2.2 - 2018-05-10
|
||||
|
||||
* Fix(ci): Fix Node version arg passed to prebuild script #280 [Jonas Hermsmeier]
|
||||
|
||||
## v6.2.1 - 2018-05-10
|
||||
|
||||
* Upgrade(package): Bump prebuild dependencies #279 [Jonas Hermsmeier]
|
||||
* Fix(ci): Only prebuild with Node 10 #279 [Jonas Hermsmeier]
|
||||
|
||||
## v6.2.0 - 2018-05-09
|
||||
|
||||
* Feat(linux): Add unique device path #278 [User Name]
|
||||
|
||||
## v6.1.8 - 2018-04-26
|
||||
|
||||
* Chore(ci): Build, test & publish releases for Node.js v10 #273 [Tim Perry]
|
||||
|
||||
## v6.1.7 - 2018-04-16
|
||||
|
||||
* Fix(diskutil): Fall back to MediaName if EntryName is not available #270 [Jonas Hermsmeier]
|
||||
* Fix(diskutil): Track & filter out device info errors #270 [Jonas Hermsmeier]
|
||||
|
||||
## v6.1.6 - 2018-04-13
|
||||
|
||||
* Fix(diskutil): Added an error for diskutil returning null [grumpyoldman-io]
|
||||
|
||||
## v6.1.5 - 2018-04-05
|
||||
|
||||
* Fix(diskutil): Fix ReferenceError when DeviceNode is undefined #266 [Jonas Hermsmeier]
|
||||
|
||||
## v6.1.4 - 2018-04-02
|
||||
|
||||
* Upgrade(package): Bump dependencies #264 [Jonas Hermsmeier]
|
||||
|
||||
## v6.1.3 - 2018-03-17
|
||||
|
||||
* Fix(diskutil): Use VolumeAllocationBlockSize if available #260 [Jonas Hermsmeier]
|
||||
|
||||
## v6.1.2 - 2018-03-16
|
||||
|
||||
* Fix(test): Avoid test timeout on AppVeyor #259 [Jonas Hermsmeier]
|
||||
* Test(diskutil): Add tests for devices without partitions #259 [Jonas Hermsmeier]
|
||||
* Fix(diskutil): Support mountpoints without partitions #259 [Jonas Hermsmeier]
|
||||
* Fix(diskutil): Fix handling of devices without partitions #259 [Jonas Hermsmeier]
|
||||
|
||||
## v6.1.1 - 2018-03-13
|
||||
|
||||
* Fix(package): Remove obsolete bin entries #256 [Jonas Hermsmeier]
|
||||
|
||||
## v6.1.0 - 2018-03-09
|
||||
|
||||
* Feat(lib): Use diskutil directly, parse plist output #253 [Jonas Hermsmeier]
|
||||
|
||||
## v6.0.5 - 2018-03-02
|
||||
|
||||
* Upgrade(package): Bump dependencies #252 [Jonas Hermsmeier]
|
||||
|
||||
## v6.0.4 - 2018-01-18
|
||||
|
||||
* Fix(windows): Impl IsSystemDevice() #250 [Jonas Hermsmeier]
|
||||
|
||||
## v6.0.3 - 2018-01-18
|
||||
|
||||
* Fix crash on Windows 7 #249 [Jonas Hermsmeier]
|
||||
|
||||
## v6.0.2 - 2018-01-14
|
||||
|
||||
* Fix(darwin): Use proper flag to enable extended regexes in `sed` Fixes #247 #248 [Andrew Scheller]
|
||||
|
||||
## v6.0.1 - 2018-01-12
|
||||
|
||||
* Fix(darwin): Allow mountpoints containing space characters #246 [Andrew Scheller]
|
||||
|
||||
## v6.0.0 - 2018-01-05
|
||||
|
||||
* Feat: Rewrite native bindings to use IOCTL #243 [Jonas Hermsmeier]
|
||||
|
||||
## v5.2.12 - 2017-12-28
|
||||
|
||||
* Chore(package): Bump dependencies #242 [Jonas Hermsmeier]
|
||||
|
||||
## v5.2.11 - 2017-12-14
|
||||
|
||||
* Refactor: Remove lodash #235 [Jonas Hermsmeier]
|
||||
|
||||
## v5.2.10 - 2017-12-12
|
||||
|
||||
* Fix(package): Fix prebuild script being run on build #236 [Jonas Hermsmeier]
|
||||
|
||||
## v5.2.9 - 2017-12-09
|
||||
|
||||
* Fix: Remove the final usage of perl from darwin.sh #238 [Andrew Scheller]
|
||||
|
||||
## v5.2.8 - 2017-12-08
|
||||
|
||||
* Chore: pip on Travis OSX is now pip2 #239 [Andrew Scheller]
|
||||
|
||||
## v5.2.7 - 2017-10-17
|
||||
|
||||
* Upgrade(package): Bump dependencies #232 [Jonas Hermsmeier]
|
||||
|
||||
## v5.2.6 - 2017-10-13
|
||||
|
||||
* Fix(ci): Ensure the Travis box finds bash #230 [Jonas Hermsmeier]
|
||||
|
||||
## v5.2.5 - 2017-10-13
|
||||
|
||||
* Chore(ci): Add CI deployment scripts #227 [Jonas Hermsmeier]
|
||||
|
||||
## v5.2.4 - 2017-10-06
|
||||
|
||||
* Correctly execute macOS and GNU/Linux scripts inside directories mounted as `noexec`. #229 [Juan Cruz Viotti]
|
||||
|
||||
## v5.2.3 - 2017-10-06
|
||||
|
||||
* Fix: Bring back support for Node.js v4 #225 [Zoltan Kochan]
|
||||
|
||||
## v5.2.2 - 2017-10-02
|
||||
|
||||
* Chore(appveyor): Explicitly set base image #223 [Jonas Hermsmeier]
|
||||
|
||||
## v5.2.1 - 2017-09-28
|
||||
|
||||
* Upgrade(package): Update dependencies #221 [Jonas Hermsmeier]
|
||||
|
||||
## v5.2.0 - 2017-09-28
|
||||
|
||||
* Feat(package): Add prebuilds for native bindings #219 [Jonas Hermsmeier]
|
||||
|
||||
## v5.1.8 - 2017-08-28
|
||||
|
||||
* Store GNU/Linux temporary scripts in `$XDG_RUNTIME_DIR`. #209 [Juan Cruz Viotti]
|
||||
|
||||
## v5.1.7 - 2017-08-28
|
||||
|
||||
* Ensure all volume handles get closed on Windows. #212 [Juan Cruz Viotti]
|
||||
|
||||
## v5.1.6 - 2017-08-28
|
||||
|
||||
* Fix(windows): log the volume we're working on #211 [Juan Cruz Viotti]
|
||||
|
||||
## v5.1.5 - 2017-08-14
|
||||
|
||||
* Correctly handle BitLocker locked Windows volumes. #206 [Juan Cruz Viotti]
|
||||
|
||||
## v5.1.4 - 2017-08-07
|
||||
|
||||
* Get more detailed error codes from the Windows implementation. [Juan Cruz Viotti]
|
||||
|
||||
## v5.1.3 - 2017-08-01
|
||||
|
||||
* Fix "Couldn't scan the drives: An unknown error occurred" where there is a mounted virtual drive. [Juan Cruz Viotti]
|
||||
|
||||
## v5.1.2 - 2017-08-01
|
||||
|
||||
* Fix "Couldn't initialize the scanner: An unknown error occurred" error. [Juan Cruz Viotti]
|
||||
|
||||
## v5.1.1 - 2017-08-01
|
||||
|
||||
* Refactor(windows): don't use COM/WMI to retrieve a drive media type [Juan Cruz Viotti]
|
||||
|
||||
## v5.1.0 - 2017-07-31
|
||||
|
||||
* Feat: add a `displayName` property to drive objects [Juan Cruz Viotti]
|
||||
|
||||
## v5.0.28 - 2017-07-31
|
||||
|
||||
* Feat(windows): print HRESULT hex in debug information [Juan Cruz Viotti]
|
||||
|
||||
## v5.0.27 - 2017-07-19
|
||||
|
||||
* Fix: small typo in EAGAIN error message [Juan Cruz Viotti]
|
||||
|
||||
## v5.0.26 - 2017-07-18
|
||||
|
||||
* Fix: handle EAGAIN spawning errors [Juan Cruz Viotti]
|
||||
* Refactor: reduce debug logging if unlink was successful [Juan Cruz Viotti]
|
||||
|
||||
## v5.0.25 - 2017-06-29
|
||||
|
||||
* Feat(windows): print debugging information when DRIVELIST_DEBUG is set [Juan Cruz Viotti]
|
||||
* Fix: property clean up tmp file after exec [Jonas Hermsmeier]
|
||||
* Fix(windows): ERROR_NOT_READY on empty SD Card reader [Juan Cruz Viotti]
|
||||
* Chore(package): Fix missing EOL in package.json [Jonas Hermsmeier]
|
||||
* Fix(windows): all drives are interpreted as read-only [Juan Cruz Viotti]
|
||||
* Refactor(windows): don't use WMI to list volumes [Juan Cruz Viotti]
|
||||
* Fix(windows): detect read-only flag on SD Cards without a filesystem (#183) [Juan Cruz Viotti]
|
||||
* Refactor(windows): Use an IOCTL to determine the partition type (#181) [Juan Cruz Viotti]
|
||||
|
||||
## v5.0.24 - 2017-06-27
|
||||
|
||||
* Refactor(windows): implement volume::GetType() [Juan Cruz Viotti]
|
||||
|
||||
## v5.0.23 - 2017-06-15
|
||||
|
||||
* Upgrade(package): Bump dependencies [Jonas Hermsmeier]
|
||||
* Doc(README): Add npm monthly download count [Jonas Hermsmeier]
|
||||
* Adapt changelog for versionbot [Kostas Lekkas]
|
||||
* Doc(README): Fix Travis link, use Etcher chat [Jonas Hermsmeier]
|
||||
|
||||
## v5.0.22
|
||||
|
||||
- Fix perl taking all the CPU in macOS in some cases
|
||||
|
||||
## v5.0.21
|
||||
|
||||
- Join volume and device names as descriptions if they both exists on macOS
|
||||
|
||||
## v5.0.20
|
||||
|
||||
- Inline platform scripts as a JSON file.
|
||||
|
||||
## v5.0.19
|
||||
|
||||
- Correctly deal with unicode characters coming from drive descriptions
|
||||
- Correctly deal with invalid escape sequences coming from drive descriptions
|
||||
|
||||
## v5.0.18
|
||||
|
||||
- Fix mountpoints getting cut if they contain a `#` in GNU/Linux and macOS
|
||||
|
||||
## v5.0.17
|
||||
|
||||
- Fix literal `\040` on mountpoints that contain spaces in GNU/Linux
|
||||
|
||||
## v5.0.16
|
||||
|
||||
- Fix awk expression that replaces periods with underscores before evaluating
|
||||
`udevadm` output in GNU/Linux.
|
||||
|
||||
## v5.0.15
|
||||
|
||||
- Increase debug logging in the case of script errors
|
||||
- Prevent errors when unplugging drives while the scripts are running
|
||||
|
||||
## v5.0.14
|
||||
|
||||
- Catch the exit code of the wrapped VBScript on Windows.
|
||||
|
||||
## v5.0.13
|
||||
|
||||
**Important:** v5.0.11 and v5.0.12 were both published to NPM from a Windows
|
||||
machine. This messed up the execution permissions of the drive detection
|
||||
scripts, causing `EACCES` errors.
|
||||
|
||||
This version is equal to v5.0.12, but was released from a UNIX based system.
|
||||
|
||||
## v5.0.12 [BROKEN]
|
||||
|
||||
- Ensure the Windows script has execution permissions.
|
||||
|
||||
## v5.0.11 [BROKEN]
|
||||
|
||||
- Omit empty SD Card readers on Windows.
|
||||
|
||||
## v5.0.10
|
||||
|
||||
- Don't include drive letters assigned to no file system in Windows mount points.
|
||||
|
||||
## v5.0.9
|
||||
|
||||
- Print platform scripts `stderr` output to a debug channel instead of throwing if the script exitted with code zero.
|
||||
- Fix bug where only the first mount point is reported on GNU/Linux.
|
||||
- Ensure every potentially problematic value is double quoted in the GNU/Linux and macOS scripts.
|
||||
|
||||
## v5.0.8
|
||||
|
||||
- Fix "is not recognised as an internal or external command" errors on Windows.
|
||||
|
||||
## v5.0.7
|
||||
|
||||
- Interpret "Fixed" drives as system drives in macOS.
|
||||
|
||||
## v5.0.6
|
||||
|
||||
- Fix uncaught error caused by a weird Windows configuration edge where multiple partitions were reported to have the same drive letter.
|
||||
|
||||
## v5.0.5
|
||||
|
||||
- Fix system drives being detected as removable drives on Mac Mini.
|
||||
|
||||
## v5.0.4
|
||||
|
||||
- Replace periods with underscores before evaluating `udevadm` output in GNU/Linux.
|
||||
|
||||
## v5.0.3
|
||||
|
||||
- Fix `drivelist` not detecting mountpoints in Windows due to a space/tab YAML parsing issue.
|
||||
|
||||
## v5.0.2
|
||||
|
||||
- Don't require .NET VBScript classes in Windows platform script.
|
||||
|
||||
## v5.0.1
|
||||
|
||||
- Fix `YAMLException: bad indentation of a sequence entry` Windows error.
|
||||
|
||||
## v5.0.0
|
||||
|
||||
- Transform `mountpoint` into an array of objects called `mountpoints`.
|
||||
- Improve GNU/Linux detection performance.
|
||||
- Correctly get SD Card readers descriptions in GNU/Linux.
|
||||
|
||||
## v4.0.0
|
||||
|
||||
- Ignore invalid YAML output from platform scripts.
|
||||
- Group mount points of drives with multiple partitions in Windows.
|
||||
- Switch project to JavaScript.
|
||||
- Switch license to Apache 2.0.
|
||||
|
||||
## v3.3.4
|
||||
|
||||
- Ensure `%SYSTEMROOT%\System32` is in the `%PATH%` before calling `cscript.exe` on Windows.
|
||||
|
||||
## v3.3.3
|
||||
|
||||
- Default device name to device id if drive doesn't have an assigned letter in Windows.
|
||||
|
||||
## v3.3.2
|
||||
|
||||
- List all partition's mountpoints in OS X.
|
||||
|
||||
## v3.3.1
|
||||
|
||||
- Fix `blkid: command not found` in GNU/Linux.
|
||||
|
||||
## v3.3.0
|
||||
|
||||
- Fix `null` device when unplugging a device while detecting drives.
|
||||
- Expose a "raw" property in all devices.
|
||||
- Attempt to display the volume name as description in OS X.
|
||||
|
||||
## v3.2.6
|
||||
|
||||
- Fix internal removable drives being considered "system" in macOS Sierra.
|
||||
|
||||
## v3.2.5
|
||||
|
||||
- Fix YAML error when a description contains question marks in GNU/Linux.
|
||||
|
||||
## v3.2.4
|
||||
|
||||
- Fix missing sizes in macOS Sierra.
|
||||
|
||||
## v3.2.3
|
||||
|
||||
- Handle mountpoints with spaces in GNU/Linux.
|
||||
|
||||
## v3.2.2
|
||||
|
||||
- Check if drive is removable when the drive has no file system in Windows.
|
||||
|
||||
## v3.2.1
|
||||
|
||||
- Make use of `df` to determine mountpoints in GNU/Linux.
|
||||
|
||||
## v3.2.0
|
||||
|
||||
- Add a property called `protected`.
|
||||
|
||||
## v3.1.2
|
||||
|
||||
- Prevent certain system drives to be detected as removable in GNU/Linux.
|
||||
|
||||
## v3.1.1
|
||||
|
||||
- Fix issue that caused some hard drives to be listed as removable drives.
|
||||
|
||||
## v3.1.0
|
||||
|
||||
- Show non-mountable disk drives in Windows.
|
||||
|
||||
## v3.0.0
|
||||
|
||||
- Parse size as a number representing bytes.
|
||||
|
||||
## v2.0.14
|
||||
|
||||
- Detect mount points of drives mounted by UUID on GNU/Linux.
|
||||
|
||||
## v2.0.13
|
||||
|
||||
- Keep once decimal in Windows drive sizes.
|
||||
|
||||
## v2.0.12
|
||||
|
||||
- Make sure MacBook's internal SDCard readers are marked as removable.
|
||||
|
||||
## v2.0.11
|
||||
|
||||
- Escape double quotes in description to prevent YAML errors.
|
||||
|
||||
## v2.0.10
|
||||
|
||||
- Improve the way we detect system drives in Windows.
|
||||
|
||||
## v2.0.9
|
||||
|
||||
- Use `udev` to determine if a drive is removable on GNU/Linux.
|
||||
- Mark internal and non-removable drives as system drives in OS X.
|
||||
- Omit loop devices in GNU/Linux.
|
||||
- Omit CD/DVD drives in GNU/Linux.
|
||||
|
||||
## v2.0.8
|
||||
|
||||
- Omit mounted DMG images in OS X.
|
||||
|
||||
## v2.0.7
|
||||
|
||||
- Add a display name property called `name`.
|
||||
|
||||
## v2.0.6
|
||||
|
||||
- Fix boolean values being surrounded by quotes.
|
||||
|
||||
## v2.0.5
|
||||
|
||||
- Trim trailing commas on GNU/Linux mountpoints.
|
||||
|
||||
## v2.0.4
|
||||
|
||||
- Support running inside Electron.
|
||||
|
||||
## v2.0.3
|
||||
|
||||
- Treat multiple mountpoint as a comma separated list of paths in GNU/Linux.
|
||||
|
||||
## v2.0.2
|
||||
|
||||
- Escape paths including spaces in unix based operating systems.
|
||||
|
||||
## v2.0.1
|
||||
|
||||
- Escape backslashes in Windows devices to avoid weird characters.
|
||||
|
||||
## v2.0.0
|
||||
|
||||
- Add example file for easy testing.
|
||||
- Redesign Windows script to match the new output scheme.
|
||||
- Refer to `osx` as Darwin everywhere.
|
||||
- Implement GNU/Linux scanning bash script.
|
||||
- Unify parsing between all supported operating systems.
|
||||
- Add `system` property to returned drives.
|
||||
- Remove `drivelist.isSystem()` predicate.
|
||||
- Fix issue that caused some OS X drives to not be detected.
|
||||
|
||||
## v1.3.2
|
||||
|
||||
- Handle edge case where OS X drives contain a description within parenthesis in `diskutil list`.
|
||||
|
||||
## v1.3.1
|
||||
|
||||
- Surround Windows script path in double quotes to avoid issues with paths incuding white space.
|
||||
|
||||
## v1.3.0
|
||||
|
||||
- Add `mountpoint` attribute to drives.
|
||||
|
||||
## v1.2.2
|
||||
|
||||
- Fix issue where a removable drive was detected as a system drive in Linux.
|
||||
|
||||
## v1.2.1
|
||||
|
||||
- Fix win32 issue where DeviceID gets part of the device description.
|
||||
|
||||
## v1.2.0
|
||||
|
||||
- Implement isSystem predicate.
|
||||
|
||||
## v1.1.2
|
||||
|
||||
- Prevent empty lsblk model crash the module. Return `undefined` description instead.
|
||||
|
||||
## v1.1.1
|
||||
|
||||
- Prevent empty wmic size crash the module. Return `undefined` size instead.
|
||||
|
||||
## v1.1.0
|
||||
|
||||
- Return non supported OS error to the callback instead of just throwing it.
|
177
dependencies/drivelist/LICENSE
vendored
Normal file
177
dependencies/drivelist/LICENSE
vendored
Normal file
|
@ -0,0 +1,177 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
218
dependencies/drivelist/README.md
vendored
Normal file
218
dependencies/drivelist/README.md
vendored
Normal file
|
@ -0,0 +1,218 @@
|
|||
<!-- Make sure you edit doc/README.hbs rather than README.md because the latter is auto-generated -->
|
||||
|
||||
drivelist
|
||||
=========
|
||||
|
||||
> List all connected drives in your computer, in all major operating systems.
|
||||
|
||||
[](https://npmjs.com/package/drivelist)
|
||||
[](https://npmjs.com/package/drivelist)
|
||||
[](https://npmjs.com/package/drivelist)
|
||||
[](https://travis-ci.org/resin-io-modules/drivelist/branches)
|
||||
[](https://ci.appveyor.com/project/resin-io/drivelist/branch/master)
|
||||
[](https://david-dm.org/resin-io-modules/drivelist)
|
||||
[](https://gitter.im/resin-io/etcher)
|
||||
|
||||
Notice that this module **does not require** admin privileges to get the drives in any supported operating system.
|
||||
|
||||
Supports:
|
||||
|
||||
- Windows.
|
||||
- GNU/Linux distributions that include [util-linux](https://github.com/karelzak/util-linux) and [udev](https://wiki.archlinux.org/index.php/udev).
|
||||
- Mac OS X.
|
||||
|
||||
When the user executes `drivelist.list()`, the module checks the operating
|
||||
system of the client and executes the corresponding drive scanning script.
|
||||
|
||||
Examples (the output will vary depending on your machine):
|
||||
|
||||
```js
|
||||
const drivelist = require('drivelist');
|
||||
|
||||
const drives = await drivelist.list();
|
||||
console.log(drives);
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
Mac OS X:
|
||||
|
||||
```sh
|
||||
[
|
||||
{
|
||||
device: '/dev/disk0',
|
||||
displayName: '/dev/disk0',
|
||||
description: 'GUID_partition_scheme',
|
||||
size: 68719476736,
|
||||
mountpoints: [
|
||||
{
|
||||
path: '/'
|
||||
}
|
||||
],
|
||||
raw: '/dev/rdisk0',
|
||||
protected: false,
|
||||
system: true
|
||||
},
|
||||
{
|
||||
device: '/dev/disk1',
|
||||
displayName: '/dev/disk1',
|
||||
description: 'Apple_HFS Macintosh HD',
|
||||
size: 68719476736,
|
||||
mountpoints: [],
|
||||
raw: '/dev/rdisk0',
|
||||
protected: false,
|
||||
system: true
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
GNU/Linux
|
||||
|
||||
```sh
|
||||
[
|
||||
{
|
||||
device: '/dev/sda',
|
||||
displayName: '/dev/sda',
|
||||
description: 'WDC WD10JPVX-75J',
|
||||
size: 68719476736,
|
||||
mountpoints: [
|
||||
{
|
||||
path: '/'
|
||||
}
|
||||
],
|
||||
raw: '/dev/sda',
|
||||
protected: false,
|
||||
system: true
|
||||
},
|
||||
{
|
||||
device: '/dev/sdb',
|
||||
displayName: '/dev/sdb',
|
||||
description: 'DataTraveler 2.0',
|
||||
size: 7823458304,
|
||||
mountpoints: [
|
||||
{
|
||||
path: '/media/UNTITLED'
|
||||
}
|
||||
],
|
||||
raw: '/dev/sdb',
|
||||
protected: true,
|
||||
system: false
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
Windows
|
||||
|
||||
```sh
|
||||
[
|
||||
{
|
||||
device: '\\\\.\\PHYSICALDRIVE0',
|
||||
displayName: 'C:',
|
||||
description: 'WDC WD10JPVX-75JC3T0',
|
||||
size: 68719476736,
|
||||
mountpoints: [
|
||||
{
|
||||
path: 'C:'
|
||||
}
|
||||
],
|
||||
raw: '\\\\.\\PHYSICALDRIVE0',
|
||||
protected: false,
|
||||
system: true
|
||||
},
|
||||
{
|
||||
device: '\\\\.\\PHYSICALDRIVE1',
|
||||
displayName: 'D:, F:',
|
||||
description: 'Generic STORAGE DEVICE USB Device',
|
||||
size: 7823458304,
|
||||
mountpoints: [
|
||||
{
|
||||
path: 'D:'
|
||||
},
|
||||
{
|
||||
path: 'F:'
|
||||
}
|
||||
],
|
||||
raw: '\\\\.\\PHYSICALDRIVE1',
|
||||
protected: true,
|
||||
system: false
|
||||
},
|
||||
{
|
||||
device: '\\\\.\\PHYSICALDRIVE2',
|
||||
displayName: '\\\\.\\PHYSICALDRIVE2',
|
||||
description: 'Silicon-Power2G',
|
||||
size: 2014314496,
|
||||
mountpoints: [],
|
||||
raw: '\\\\.\\PHYSICALDRIVE2',
|
||||
protected: false,
|
||||
system: false
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Install `drivelist` by running:
|
||||
|
||||
```sh
|
||||
$ npm install --save drivelist
|
||||
```
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
<a name="module_drivelist..list"></a>
|
||||
|
||||
### drivelist~list() ⇒ <code>Promise</code>
|
||||
**Kind**: inner method of [<code>drivelist</code>](#module_drivelist)
|
||||
**Summary**: List available drives
|
||||
**Returns**: <code>Promise</code> - <Drive>[]
|
||||
**Access**: public
|
||||
**Example**
|
||||
```js
|
||||
const drivelist = require('drivelist');
|
||||
|
||||
const drives = await drivelist.list();
|
||||
drives.forEach((drive) => {
|
||||
console.log(drive);
|
||||
});
|
||||
```
|
||||
|
||||
Tests
|
||||
-----
|
||||
|
||||
Run the test suite by doing:
|
||||
|
||||
```sh
|
||||
$ npm test
|
||||
```
|
||||
|
||||
Contribute
|
||||
----------
|
||||
|
||||
We're looking forward to support more operating systems. Please raise an issue or even better, send a PR to increase support!
|
||||
|
||||
- Issue Tracker: [github.com/balena-io-modules/drivelist/issues](https://github.com/resin-io-modules/drivelist/issues)
|
||||
- Source Code: [github.com/balena-io-modules/drivelist](https://github.com/resin-io-modules/drivelist)
|
||||
|
||||
Before submitting a PR, please make sure that you include tests, and that the linter runs without any warning:
|
||||
|
||||
```sh
|
||||
$ npm run lint
|
||||
```
|
||||
|
||||
Support
|
||||
-------
|
||||
|
||||
If you're having any problem, please [raise an issue](https://github.com/balena-io-modules/drivelist/issues/new) on GitHub.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
The project is licensed under the Apache 2.0 license.
|
||||
|
||||
[yaml]: http://yaml.org
|
38
dependencies/drivelist/appveyor.yml
vendored
Normal file
38
dependencies/drivelist/appveyor.yml
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
# appveyor file
|
||||
# http://www.appveyor.com/docs/appveyor-yml
|
||||
image:
|
||||
- Visual Studio 2015
|
||||
|
||||
init:
|
||||
- git config --global core.autocrlf input
|
||||
|
||||
cache:
|
||||
- C:\Users\appveyor\.node-gyp
|
||||
- '%AppData%\npm-cache'
|
||||
|
||||
# what combinations to test
|
||||
environment:
|
||||
matrix:
|
||||
- nodejs_version: 10
|
||||
- nodejs_version: 8
|
||||
- nodejs_version: 6
|
||||
- nodejs_version: 4
|
||||
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
|
||||
install:
|
||||
- pip install -r requirements.txt
|
||||
- ps: Install-Product node $env:nodejs_version x64
|
||||
- npm install
|
||||
|
||||
build: off
|
||||
|
||||
test_script:
|
||||
- node --version
|
||||
- npm --version
|
||||
- cmd: npm test
|
||||
|
||||
deploy_script:
|
||||
- ci\prebuild-publish.bat %nodejs_version%
|
62
dependencies/drivelist/binding.gyp
vendored
Normal file
62
dependencies/drivelist/binding.gyp
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "drivelist",
|
||||
"include_dirs" : [
|
||||
"<!(node -e \"require('nan')\")",
|
||||
"."
|
||||
],
|
||||
"sources": [
|
||||
"src/drivelist.cpp",
|
||||
"src/device-descriptor.cpp",
|
||||
],
|
||||
"msvs_settings": {
|
||||
"VCLinkerTool": {
|
||||
"SetChecksum": "true"
|
||||
},
|
||||
"VCCLCompilerTool": {
|
||||
"ExceptionHandling": 1,
|
||||
"AdditionalOptions": [
|
||||
"/EHsc"
|
||||
]
|
||||
}
|
||||
},
|
||||
"conditions": [
|
||||
[ 'OS=="mac"', {
|
||||
"xcode_settings": {
|
||||
"OTHER_CPLUSPLUSFLAGS": [
|
||||
"-stdlib=libc++"
|
||||
],
|
||||
"OTHER_LDFLAGS": [
|
||||
"-stdlib=libc++"
|
||||
]
|
||||
},
|
||||
"sources": [
|
||||
"src/darwin/list.mm",
|
||||
"src/darwin/REDiskList.m"
|
||||
],
|
||||
"link_settings": {
|
||||
"libraries": [
|
||||
"-framework Carbon,DiskArbitration"
|
||||
]
|
||||
}
|
||||
}],
|
||||
[ 'OS=="win"', {
|
||||
"sources": [
|
||||
"src/windows/list.cpp"
|
||||
],
|
||||
"libraries": [
|
||||
"-lKernel32.lib",
|
||||
"-lShell32.lib",
|
||||
"-lSetupAPI.lib"
|
||||
]
|
||||
}],
|
||||
[ 'OS=="linux"', {
|
||||
"sources": [
|
||||
"src/linux/list.cpp"
|
||||
]
|
||||
}]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
9
dependencies/drivelist/ci/prebuild-publish.bat
vendored
Normal file
9
dependencies/drivelist/ci/prebuild-publish.bat
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
@echo off
|
||||
|
||||
if %1 == 10 (
|
||||
if %APPVEYOR_REPO_BRANCH% == master (
|
||||
if %GITHUB_TOKEN% neq "" (
|
||||
npm run prebuild-release -- -u %GITHUB_TOKEN%
|
||||
)
|
||||
)
|
||||
)
|
5
dependencies/drivelist/ci/prebuild-publish.sh
vendored
Normal file
5
dependencies/drivelist/ci/prebuild-publish.sh
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [[ $GITHUB_TOKEN ]]; then
|
||||
npm run prebuild-release -- -u "$GITHUB_TOKEN"
|
||||
fi
|
208
dependencies/drivelist/doc/README.hbs
vendored
Normal file
208
dependencies/drivelist/doc/README.hbs
vendored
Normal file
|
@ -0,0 +1,208 @@
|
|||
<!-- Make sure you edit doc/README.hbs rather than README.md because the latter is auto-generated -->
|
||||
|
||||
drivelist
|
||||
=========
|
||||
|
||||
> List all connected drives in your computer, in all major operating systems.
|
||||
|
||||
[](https://npmjs.com/package/drivelist)
|
||||
[](https://npmjs.com/package/drivelist)
|
||||
[](https://npmjs.com/package/drivelist)
|
||||
[](https://travis-ci.org/resin-io-modules/drivelist/branches)
|
||||
[](https://ci.appveyor.com/project/resin-io/drivelist/branch/master)
|
||||
[](https://david-dm.org/resin-io-modules/drivelist)
|
||||
[](https://gitter.im/resin-io/etcher)
|
||||
|
||||
Notice that this module **does not require** admin privileges to get the drives in any supported operating system.
|
||||
|
||||
Supports:
|
||||
|
||||
- Windows.
|
||||
- GNU/Linux distributions that include [util-linux](https://github.com/karelzak/util-linux) and [udev](https://wiki.archlinux.org/index.php/udev).
|
||||
- Mac OS X.
|
||||
|
||||
When the user executes `drivelist.list()`, the module checks the operating
|
||||
system of the client and executes the corresponding drive scanning script.
|
||||
|
||||
Examples (the output will vary depending on your machine):
|
||||
|
||||
```js
|
||||
const drivelist = require('drivelist');
|
||||
|
||||
const drives = await drivelist.list();
|
||||
console.log(drives);
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
Mac OS X:
|
||||
|
||||
```sh
|
||||
[
|
||||
{
|
||||
device: '/dev/disk0',
|
||||
displayName: '/dev/disk0',
|
||||
description: 'GUID_partition_scheme',
|
||||
size: 68719476736,
|
||||
mountpoints: [
|
||||
{
|
||||
path: '/'
|
||||
}
|
||||
],
|
||||
raw: '/dev/rdisk0',
|
||||
protected: false,
|
||||
system: true
|
||||
},
|
||||
{
|
||||
device: '/dev/disk1',
|
||||
displayName: '/dev/disk1',
|
||||
description: 'Apple_HFS Macintosh HD',
|
||||
size: 68719476736,
|
||||
mountpoints: [],
|
||||
raw: '/dev/rdisk0',
|
||||
protected: false,
|
||||
system: true
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
GNU/Linux
|
||||
|
||||
```sh
|
||||
[
|
||||
{
|
||||
device: '/dev/sda',
|
||||
displayName: '/dev/sda',
|
||||
description: 'WDC WD10JPVX-75J',
|
||||
size: 68719476736,
|
||||
mountpoints: [
|
||||
{
|
||||
path: '/'
|
||||
}
|
||||
],
|
||||
raw: '/dev/sda',
|
||||
protected: false,
|
||||
system: true
|
||||
},
|
||||
{
|
||||
device: '/dev/sdb',
|
||||
displayName: '/dev/sdb',
|
||||
description: 'DataTraveler 2.0',
|
||||
size: 7823458304,
|
||||
mountpoints: [
|
||||
{
|
||||
path: '/media/UNTITLED'
|
||||
}
|
||||
],
|
||||
raw: '/dev/sdb',
|
||||
protected: true,
|
||||
system: false
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
Windows
|
||||
|
||||
```sh
|
||||
[
|
||||
{
|
||||
device: '\\\\.\\PHYSICALDRIVE0',
|
||||
displayName: 'C:',
|
||||
description: 'WDC WD10JPVX-75JC3T0',
|
||||
size: 68719476736,
|
||||
mountpoints: [
|
||||
{
|
||||
path: 'C:'
|
||||
}
|
||||
],
|
||||
raw: '\\\\.\\PHYSICALDRIVE0',
|
||||
protected: false,
|
||||
system: true
|
||||
},
|
||||
{
|
||||
device: '\\\\.\\PHYSICALDRIVE1',
|
||||
displayName: 'D:, F:',
|
||||
description: 'Generic STORAGE DEVICE USB Device',
|
||||
size: 7823458304,
|
||||
mountpoints: [
|
||||
{
|
||||
path: 'D:'
|
||||
},
|
||||
{
|
||||
path: 'F:'
|
||||
}
|
||||
],
|
||||
raw: '\\\\.\\PHYSICALDRIVE1',
|
||||
protected: true,
|
||||
system: false
|
||||
},
|
||||
{
|
||||
device: '\\\\.\\PHYSICALDRIVE2',
|
||||
displayName: '\\\\.\\PHYSICALDRIVE2',
|
||||
description: 'Silicon-Power2G',
|
||||
size: 2014314496,
|
||||
mountpoints: [],
|
||||
raw: '\\\\.\\PHYSICALDRIVE2',
|
||||
protected: false,
|
||||
system: false
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Install `drivelist` by running:
|
||||
|
||||
```sh
|
||||
$ npm install --save drivelist
|
||||
```
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
{{#module name="drivelist"}}
|
||||
{{>body~}}
|
||||
{{>member-index~}}
|
||||
{{>separator~}}
|
||||
{{>members~}}
|
||||
{{/module}}
|
||||
|
||||
Tests
|
||||
-----
|
||||
|
||||
Run the test suite by doing:
|
||||
|
||||
```sh
|
||||
$ npm test
|
||||
```
|
||||
|
||||
Contribute
|
||||
----------
|
||||
|
||||
We're looking forward to support more operating systems. Please raise an issue or even better, send a PR to increase support!
|
||||
|
||||
- Issue Tracker: [github.com/balena-io-modules/drivelist/issues](https://github.com/resin-io-modules/drivelist/issues)
|
||||
- Source Code: [github.com/balena-io-modules/drivelist](https://github.com/resin-io-modules/drivelist)
|
||||
|
||||
Before submitting a PR, please make sure that you include tests, and that the linter runs without any warning:
|
||||
|
||||
```sh
|
||||
$ npm run lint
|
||||
```
|
||||
|
||||
Support
|
||||
-------
|
||||
|
||||
If you're having any problem, please [raise an issue](https://github.com/balena-io-modules/drivelist/issues/new) on GitHub.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
The project is licensed under the Apache 2.0 license.
|
||||
|
||||
[yaml]: http://yaml.org
|
36
dependencies/drivelist/example/index.ts
vendored
Normal file
36
dependencies/drivelist/example/index.ts
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
import { inspect } from 'util';
|
||||
|
||||
import { list } from '..';
|
||||
|
||||
async function main() {
|
||||
let drives;
|
||||
try {
|
||||
drives = await list();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(inspect(drives, {
|
||||
colors: process.stdout.isTTY,
|
||||
depth: null
|
||||
}));
|
||||
}
|
||||
|
||||
main();
|
85
dependencies/drivelist/lib/index.ts
vendored
Normal file
85
dependencies/drivelist/lib/index.ts
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright 2016 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @module drivelist
|
||||
*/
|
||||
|
||||
import bindings = require('bindings');
|
||||
import { platform } from 'os';
|
||||
|
||||
import { lsblk } from './lsblk';
|
||||
|
||||
export interface Mountpoint {
|
||||
path: string;
|
||||
label: string | null;
|
||||
}
|
||||
|
||||
export interface Drive {
|
||||
blockSize: number;
|
||||
busType: string;
|
||||
busVersion: null;
|
||||
description: string;
|
||||
device: string;
|
||||
devicePath: string | null;
|
||||
enumerator: string;
|
||||
error: null;
|
||||
isCard: null;
|
||||
isReadOnly: boolean;
|
||||
isRemovable: boolean;
|
||||
isSCSI: boolean | null;
|
||||
isSystem: boolean;
|
||||
isUAS: null;
|
||||
isUSB: boolean | null;
|
||||
isVirtual: boolean | null;
|
||||
logicalBlockSize: number;
|
||||
mountpoints: Mountpoint[];
|
||||
raw: string;
|
||||
size: number | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary List available drives
|
||||
* @function
|
||||
* @public
|
||||
*
|
||||
* @returns {Promise} <Drive>[]
|
||||
*
|
||||
* @example
|
||||
* const drivelist = require('drivelist');
|
||||
*
|
||||
* const drives = await drivelist.list();
|
||||
* drives.forEach((drive) => {
|
||||
* console.log(drive);
|
||||
* });
|
||||
*/
|
||||
export async function list(): Promise<Drive[]> {
|
||||
const plat = platform();
|
||||
if (plat === 'win32' || plat === 'darwin') {
|
||||
return new Promise((resolve, reject) => {
|
||||
bindings('drivelist').list((error: Error, drives: Drive[]) => {
|
||||
if (error != null) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(drives);
|
||||
}
|
||||
});
|
||||
});
|
||||
} else if (plat === 'linux') {
|
||||
return await lsblk();
|
||||
}
|
||||
throw new Error(`Your OS is not supported by this module: ${platform()}`);
|
||||
}
|
93
dependencies/drivelist/lib/lsblk/index.ts
vendored
Normal file
93
dependencies/drivelist/lib/lsblk/index.ts
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { execFile } from 'mz/child_process';
|
||||
import { readdir, readlink } from 'mz/fs';
|
||||
import { join, resolve } from 'path';
|
||||
|
||||
import { Drive } from '..';
|
||||
import { parse as parseJSON } from './json';
|
||||
import { parse as parsePairs } from './pairs';
|
||||
|
||||
const DISK_PATH_DIR = '/dev/disk/by-path/';
|
||||
|
||||
let SUPPORTS_JSON = true;
|
||||
|
||||
async function getDevicePaths(): Promise<Map<string, string>> {
|
||||
const mapping = new Map();
|
||||
for (const filename of await readdir(DISK_PATH_DIR)) {
|
||||
const linkPath = join(DISK_PATH_DIR, filename);
|
||||
let link: string;
|
||||
try {
|
||||
link = await readlink(linkPath);
|
||||
} catch (error) {
|
||||
continue;
|
||||
}
|
||||
const devicePath = resolve(DISK_PATH_DIR, link);
|
||||
mapping.set(devicePath, linkPath);
|
||||
}
|
||||
return mapping;
|
||||
}
|
||||
|
||||
async function addDevicePaths(devices: Drive[]): Promise<void> {
|
||||
const devicePaths = await getDevicePaths();
|
||||
for (const device of devices) {
|
||||
device.devicePath = devicePaths.get(device.device) || null;
|
||||
}
|
||||
}
|
||||
|
||||
async function getOutput(command: string, ...args: string[]) {
|
||||
const [stdout] = await execFile(command, args);
|
||||
return stdout;
|
||||
}
|
||||
|
||||
async function lsblkJSON(): Promise<Drive[]> {
|
||||
return parseJSON(
|
||||
await getOutput(
|
||||
'lsblk',
|
||||
'--bytes',
|
||||
'--all',
|
||||
'--json',
|
||||
'--paths',
|
||||
'--output-all',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
async function lsblkPairs(): Promise<Drive[]> {
|
||||
return parsePairs(await getOutput('lsblk', '--bytes', '--all', '--pairs'));
|
||||
}
|
||||
|
||||
async function $lsblk(): Promise<Drive[]> {
|
||||
if (SUPPORTS_JSON) {
|
||||
try {
|
||||
return await lsblkJSON();
|
||||
} catch (error) {
|
||||
SUPPORTS_JSON = false;
|
||||
}
|
||||
}
|
||||
return await lsblkPairs();
|
||||
}
|
||||
|
||||
export async function lsblk(): Promise<Drive[]> {
|
||||
const drives = await $lsblk();
|
||||
try {
|
||||
await addDevicePaths(drives);
|
||||
} catch (error) {
|
||||
// Couldn't add device paths
|
||||
}
|
||||
return drives;
|
||||
}
|
155
dependencies/drivelist/lib/lsblk/json.ts
vendored
Normal file
155
dependencies/drivelist/lib/lsblk/json.ts
vendored
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { posix } from 'path';
|
||||
|
||||
import { Drive, Mountpoint } from '..';
|
||||
|
||||
interface LsblkJsonOutput {
|
||||
blockdevices: LsblkJsonOutputDevice[];
|
||||
}
|
||||
|
||||
interface LsblkJsonOutputDevice {
|
||||
children: LsblkJsonOutputDeviceChild[];
|
||||
hotplug?: string;
|
||||
kname?: string;
|
||||
label: string | null;
|
||||
'log-sec'?: string;
|
||||
model: string | null;
|
||||
mountpoint: string | null;
|
||||
name: string;
|
||||
partlabel: string | null;
|
||||
'phy-sec'?: string;
|
||||
rm?: string;
|
||||
ro?: string;
|
||||
size?: string;
|
||||
subsystems?: string;
|
||||
tran?: string;
|
||||
vendor: string | null;
|
||||
}
|
||||
|
||||
interface LsblkJsonOutputDeviceChild {
|
||||
label: string | null;
|
||||
mountpoint?: string;
|
||||
partlabel: string | null;
|
||||
}
|
||||
|
||||
function getMountpoints(
|
||||
children: Array<LsblkJsonOutputDeviceChild | LsblkJsonOutputDevice>,
|
||||
): Mountpoint[] {
|
||||
return children
|
||||
.filter(child => {
|
||||
return child.mountpoint;
|
||||
})
|
||||
.map(child => {
|
||||
return {
|
||||
path: child.mountpoint!,
|
||||
label: child.label || child.partlabel,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function getDescription(device: LsblkJsonOutputDevice): string {
|
||||
const description = [
|
||||
device.label || '',
|
||||
device.vendor || '',
|
||||
device.model || '',
|
||||
];
|
||||
if (device.children) {
|
||||
let subLabels = device.children
|
||||
.filter(c => (c.label && c.label !== device.label) || c.mountpoint)
|
||||
.map(c => c.label || c.mountpoint);
|
||||
subLabels = Array.from(new Set(subLabels));
|
||||
if (subLabels.length) {
|
||||
description.push(`(${subLabels.join(', ')})`);
|
||||
}
|
||||
}
|
||||
return description
|
||||
.join(' ')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
}
|
||||
|
||||
function resolveDeviceName(name?: string): string | null {
|
||||
if (!name) {
|
||||
return null;
|
||||
}
|
||||
if (!posix.isAbsolute(name)) {
|
||||
return posix.resolve('/dev', name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
export function transform(data: LsblkJsonOutput): Drive[] {
|
||||
return data.blockdevices
|
||||
.map(device =>
|
||||
Object.assign({}, device, {
|
||||
name: resolveDeviceName(device.name),
|
||||
kname: resolveDeviceName(device.kname),
|
||||
}),
|
||||
)
|
||||
.filter(
|
||||
device =>
|
||||
// Omit loop devices, CD/DVD drives, and RAM
|
||||
!device.name.startsWith('/dev/loop') &&
|
||||
!device.name.startsWith('/dev/sr') &&
|
||||
!device.name.startsWith('/dev/ram'),
|
||||
)
|
||||
.map(
|
||||
(device: LsblkJsonOutputDevice): Drive => {
|
||||
const isVirtual = device.subsystems
|
||||
? /^(block)$/i.test(device.subsystems)
|
||||
: null;
|
||||
const isSCSI = device.tran
|
||||
? /^(sata|scsi|ata|ide|pci)$/i.test(device.tran)
|
||||
: null;
|
||||
const isUSB = device.tran ? /^(usb)$/i.test(device.tran) : null;
|
||||
const isReadOnly = Number(device.ro) === 1;
|
||||
const isRemovable =
|
||||
Number(device.rm) === 1 ||
|
||||
Number(device.hotplug) === 1 ||
|
||||
Boolean(isVirtual);
|
||||
return {
|
||||
enumerator: 'lsblk:json',
|
||||
busType: (device.tran || 'UNKNOWN').toUpperCase(),
|
||||
busVersion: null,
|
||||
device: device.name,
|
||||
devicePath: null,
|
||||
raw: device.kname || device.name,
|
||||
description: getDescription(device),
|
||||
error: null,
|
||||
size: Number(device.size) || null,
|
||||
blockSize: Number(device['phy-sec']) || 512,
|
||||
logicalBlockSize: Number(device['log-sec']) || 512,
|
||||
mountpoints: device.children
|
||||
? getMountpoints(device.children)
|
||||
: getMountpoints([device]),
|
||||
isReadOnly,
|
||||
isSystem: !isRemovable && !isVirtual,
|
||||
isVirtual,
|
||||
isRemovable,
|
||||
isCard: null,
|
||||
isSCSI,
|
||||
isUSB,
|
||||
isUAS: null,
|
||||
};
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function parse(stdout: string): Drive[] {
|
||||
return transform(JSON.parse(stdout));
|
||||
}
|
182
dependencies/drivelist/lib/lsblk/pairs.ts
vendored
Normal file
182
dependencies/drivelist/lib/lsblk/pairs.ts
vendored
Normal file
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
import { Drive, Mountpoint } from '..';
|
||||
|
||||
interface Dict<T> {
|
||||
[K: string]: T;
|
||||
}
|
||||
|
||||
function parseLsblkLine(line: string): Dict<string> {
|
||||
const data: Dict<string> = {};
|
||||
let offset = 0;
|
||||
let key = '';
|
||||
let value = '';
|
||||
|
||||
const keyChar = /[^"=]/;
|
||||
const whitespace = /\s+/;
|
||||
const escape = '\\';
|
||||
let state = 'key';
|
||||
|
||||
while (offset < line.length) {
|
||||
if (state === 'key') {
|
||||
while (keyChar.test(line[offset])) {
|
||||
key += line[offset];
|
||||
offset += 1;
|
||||
}
|
||||
if (line[offset] === '=') {
|
||||
state = 'value';
|
||||
offset += 1;
|
||||
}
|
||||
} else if (state === 'value') {
|
||||
if (line[offset] !== '"') {
|
||||
throw new Error(`Expected '"', saw "${line[offset]}"`);
|
||||
}
|
||||
offset += 1;
|
||||
while (line[offset] !== '"' && line[offset - 1] !== escape) {
|
||||
value += line[offset];
|
||||
offset += 1;
|
||||
}
|
||||
if (line[offset] !== '"') {
|
||||
throw new Error(`Expected '"', saw "${line[offset]}"`);
|
||||
}
|
||||
offset += 1;
|
||||
data[key.toLowerCase()] = value.trim();
|
||||
key = '';
|
||||
value = '';
|
||||
state = 'space';
|
||||
} else if (state === 'space') {
|
||||
while (whitespace.test(line[offset])) {
|
||||
offset += 1;
|
||||
}
|
||||
state = 'key';
|
||||
} else {
|
||||
throw new Error(`Undefined state "${state}"`);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function parseLsblk(output: string): Array<Dict<string>> {
|
||||
return output
|
||||
.trim()
|
||||
.split(/\r?\n/g)
|
||||
.map(parseLsblkLine);
|
||||
}
|
||||
|
||||
function consolidate(
|
||||
devices: Array<Dict<string>>,
|
||||
): Array<Dict<string> & { mountpoints: Mountpoint[] }> {
|
||||
const primaries = devices.filter(device => {
|
||||
return (
|
||||
device.type === 'disk' &&
|
||||
!device.name.startsWith('ram') &&
|
||||
!device.name.startsWith('sr')
|
||||
);
|
||||
});
|
||||
|
||||
return primaries.map(device => {
|
||||
return Object.assign({}, device, {
|
||||
mountpoints: devices
|
||||
.filter(child => {
|
||||
return (
|
||||
['disk', 'part'].includes(child.type) &&
|
||||
child.mountpoint &&
|
||||
child.name.startsWith(device.name)
|
||||
);
|
||||
})
|
||||
.map(
|
||||
(child): Mountpoint => {
|
||||
return {
|
||||
path: child.mountpoint,
|
||||
label: child.label,
|
||||
};
|
||||
},
|
||||
),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getDescription(
|
||||
device: Dict<string> & { mountpoints: Mountpoint[] },
|
||||
): string {
|
||||
const description = [
|
||||
device.label || '',
|
||||
device.vendor || '',
|
||||
device.model || '',
|
||||
];
|
||||
if (device.mountpoints.length) {
|
||||
let subLabels = device.mountpoints
|
||||
.filter(c => {
|
||||
return (c.label && c.label !== device.label) || c.path;
|
||||
})
|
||||
.map(c => {
|
||||
return c.label || c.path;
|
||||
});
|
||||
subLabels = Array.from(new Set(subLabels));
|
||||
if (subLabels.length) {
|
||||
description.push(`(${subLabels.join(', ')})`);
|
||||
}
|
||||
}
|
||||
return description
|
||||
.join(' ')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
}
|
||||
|
||||
export function parse(stdout: string): Drive[] {
|
||||
const devices = consolidate(parseLsblk(stdout));
|
||||
|
||||
return devices.map(
|
||||
(device: Dict<string> & { mountpoints: Mountpoint[] }): Drive => {
|
||||
const isVirtual = device.subsystems
|
||||
? /^block$/i.test(device.subsystems)
|
||||
: null;
|
||||
const isSCSI = device.tran
|
||||
? /^(?:sata|scsi|ata|ide|pci)$/i.test(device.tran)
|
||||
: null;
|
||||
const isUSB = device.tran ? /^usb$/i.test(device.tran) : null;
|
||||
const isReadOnly = Number(device.ro) === 1;
|
||||
const isRemovable =
|
||||
Number(device.rm) === 1 ||
|
||||
Number(device.hotplug) === 1 ||
|
||||
Boolean(isVirtual);
|
||||
|
||||
return {
|
||||
enumerator: 'lsblk:pairs',
|
||||
busType: (device.tran || 'UNKNOWN').toUpperCase(),
|
||||
busVersion: null,
|
||||
device: '/dev/' + device.name,
|
||||
devicePath: null,
|
||||
raw: '/dev/' + device.name,
|
||||
description: getDescription(device) || device.name,
|
||||
error: null,
|
||||
size: Number(device.size) || null,
|
||||
blockSize: Number(device['phy-sec']) || 512,
|
||||
logicalBlockSize: Number(device['log-sec']) || 512,
|
||||
mountpoints: device.mountpoints,
|
||||
isReadOnly,
|
||||
isSystem: !isRemovable && !isVirtual,
|
||||
isVirtual,
|
||||
isRemovable,
|
||||
isCard: null,
|
||||
isSCSI,
|
||||
isUSB,
|
||||
isUAS: null,
|
||||
};
|
||||
},
|
||||
);
|
||||
}
|
66
dependencies/drivelist/package.json
vendored
Normal file
66
dependencies/drivelist/package.json
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
{
|
||||
"name": "drivelist",
|
||||
"version": "8.0.9",
|
||||
"description": "List all connected drives in your computer, in all major operating systems",
|
||||
"main": "js/index.js",
|
||||
"homepage": "https://github.com/balena-io-modules/drivelist",
|
||||
"gypfile": true,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/balena-io-modules/drivelist.git"
|
||||
},
|
||||
"keywords": [
|
||||
"disk",
|
||||
"cross",
|
||||
"platform",
|
||||
"physical",
|
||||
"drive",
|
||||
"list"
|
||||
],
|
||||
"directories": {
|
||||
"test": "tests"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha -r ts-node/register tests/**/*.spec.ts -R spec",
|
||||
"lint": "npm run lint-cpp && npm run lint-ts",
|
||||
"lint-cpp": "cpplint --recursive src",
|
||||
"lint-ts": "resin-lint --typescript lib tests",
|
||||
"prettier": "prettier --config ./node_modules/resin-lint/config/.prettierrc --write \"lib/**/*.ts\" \"tests/**/*.ts\"",
|
||||
"readme": "jsdoc2md --template doc/README.hbs js/index.js > README.md",
|
||||
"configure": "node-gyp configure",
|
||||
"build": "node-gyp rebuild",
|
||||
"build-ts": "tsc",
|
||||
"rebuild": "node-gyp rebuild",
|
||||
"install": "prebuild-install || node-gyp rebuild",
|
||||
"prebuild-release": "prebuild --all --strip",
|
||||
"prepublishOnly": "npm run build-ts && npm run readme"
|
||||
},
|
||||
"author": "Juan Cruz Viotti <juan@balena.io>",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bindings": "^1.3.0",
|
||||
"@types/chai": "^4.1.7",
|
||||
"@types/mocha": "^5.2.6",
|
||||
"@types/mz": "0.0.32",
|
||||
"@types/sinon": "^7.0.6",
|
||||
"chai": "^4.2.0",
|
||||
"eslint": "^4.19.1",
|
||||
"jsdoc-to-markdown": "^4.0.1",
|
||||
"mocha": "^6.0.0",
|
||||
"prebuild": "^8.1.2",
|
||||
"resin-lint": "^3.0.1",
|
||||
"sinon": "^7.2.4",
|
||||
"ts-node": "^8.0.2",
|
||||
"typescript": "^3.2.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"bindings": "^1.3.0",
|
||||
"debug": "^3.1.0",
|
||||
"mz": "^2.7.0",
|
||||
"nan": "^2.14.0",
|
||||
"prebuild-install": "^5.2.4"
|
||||
}
|
||||
}
|
1
dependencies/drivelist/requirements.txt
vendored
Normal file
1
dependencies/drivelist/requirements.txt
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
cpplint==1.3.0
|
41
dependencies/drivelist/src/darwin/REDiskList.h
vendored
Normal file
41
dependencies/drivelist/src/darwin/REDiskList.h
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright 2019 balena.io
|
||||
* Copyright 2018 Robin Andersson <me@robinwassen.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef SRC_DARWIN_REDISKLIST_H_
|
||||
#define SRC_DARWIN_REDISKLIST_H_
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
* Class to return a list of disks synchronously
|
||||
* To use the class, just init an instance of it and
|
||||
* it will populate the disks property with NSStrings
|
||||
*
|
||||
* @author Robin Andersson
|
||||
*/
|
||||
@interface REDiskList : NSObject
|
||||
|
||||
/**
|
||||
* NSArray of disks and partitions
|
||||
* Disks are in the format disk0, disk1 etc
|
||||
* Partitions are in the format disk0s1, disk1s1 etc
|
||||
*/
|
||||
@property(readonly) NSArray *disks;
|
||||
|
||||
@end
|
||||
|
||||
#endif // SRC_DARWIN_REDISKLIST_H_
|
61
dependencies/drivelist/src/darwin/REDiskList.m
vendored
Normal file
61
dependencies/drivelist/src/darwin/REDiskList.m
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright 2019 balena.io
|
||||
* Copyright 2018 Robin Andersson <me@robinwassen.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import "REDiskList.h"
|
||||
#import <DiskArbitration/DiskArbitration.h>
|
||||
|
||||
@implementation REDiskList
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
|
||||
if (self) {
|
||||
_disks = [[NSMutableArray alloc] init];
|
||||
[self populateDisksBlocking];
|
||||
[_disks sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)dealloc {
|
||||
[_disks release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
void appendDisk(DADiskRef disk, void *context) {
|
||||
NSMutableArray *_disks = (__bridge NSMutableArray*)context;
|
||||
const char *bsdName = DADiskGetBSDName(disk);
|
||||
if (bsdName != nil) {
|
||||
[_disks addObject:[NSString stringWithUTF8String:bsdName]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)populateDisksBlocking {
|
||||
DASessionRef session = DASessionCreate(kCFAllocatorDefault);
|
||||
if (session) {
|
||||
DARegisterDiskAppearedCallback(session, NULL, appendDisk, (void*)_disks);
|
||||
CFRunLoopRef runLoop = [[NSRunLoop currentRunLoop] getCFRunLoop];
|
||||
DASessionScheduleWithRunLoop(session, runLoop, kCFRunLoopDefaultMode);
|
||||
CFRunLoopStop(runLoop);
|
||||
CFRunLoopRunInMode((CFStringRef)NSDefaultRunLoopMode, 0.05, NO);
|
||||
DAUnregisterCallback(session, appendDisk, (void*)_disks);
|
||||
CFRelease(session);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
179
dependencies/drivelist/src/darwin/list.mm
vendored
Normal file
179
dependencies/drivelist/src/darwin/list.mm
vendored
Normal file
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Copyright 2019 balena.io
|
||||
* Copyright 2018 Robin Andersson <me@robinwassen.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <nan.h>
|
||||
#include "../drivelist.hpp"
|
||||
|
||||
#import "REDiskList.h"
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <DiskArbitration/DiskArbitration.h>
|
||||
|
||||
namespace Drivelist {
|
||||
bool IsDiskPartition(NSString *disk) {
|
||||
NSPredicate *partitionRegEx = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"disk\\d+s\\d+"];
|
||||
return [partitionRegEx evaluateWithObject:disk];
|
||||
}
|
||||
|
||||
bool IsCard(CFDictionaryRef diskDescription) {
|
||||
CFDictionaryRef mediaIconDict = (CFDictionaryRef)CFDictionaryGetValue(
|
||||
diskDescription,
|
||||
kDADiskDescriptionMediaIconKey
|
||||
);
|
||||
if (mediaIconDict == nil) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CFStringRef iconFileNameKeyRef = CFStringCreateWithCString(NULL, "IOBundleResourceFile", kCFStringEncodingUTF8);
|
||||
CFStringRef iconFileNameRef = (CFStringRef)CFDictionaryGetValue(mediaIconDict, iconFileNameKeyRef);
|
||||
CFRelease(iconFileNameKeyRef);
|
||||
|
||||
if (iconFileNameRef == nil) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// macOS 10.14.3 - External SD card reader provides `Removable.icns`, not `SD.icns`.
|
||||
// But we can't use it to detect SD card, because external drive has `Removable.icns` as well.
|
||||
return [(NSString *)iconFileNameRef isEqualToString:@"SD.icns"];
|
||||
}
|
||||
|
||||
NSNumber *DictionaryGetNumber(CFDictionaryRef dict, const void *key) {
|
||||
return (NSNumber*)CFDictionaryGetValue(dict, key);
|
||||
}
|
||||
|
||||
DeviceDescriptor CreateDeviceDescriptorFromDiskDescription(std::string diskBsdName, CFDictionaryRef diskDescription) {
|
||||
NSString *deviceProtocol = (NSString*)CFDictionaryGetValue(diskDescription, kDADiskDescriptionDeviceProtocolKey);
|
||||
NSNumber *blockSize = DictionaryGetNumber(diskDescription, kDADiskDescriptionMediaBlockSizeKey);
|
||||
bool isInternal = [DictionaryGetNumber(diskDescription, kDADiskDescriptionDeviceInternalKey) boolValue];
|
||||
bool isRemovable = [DictionaryGetNumber(diskDescription, kDADiskDescriptionMediaRemovableKey) boolValue];
|
||||
bool isEjectable = [DictionaryGetNumber(diskDescription, kDADiskDescriptionMediaEjectableKey) boolValue];
|
||||
|
||||
DeviceDescriptor device = DeviceDescriptor();
|
||||
device.enumerator = "DiskArbitration";
|
||||
device.busType = (deviceProtocol != nil) ? [deviceProtocol UTF8String] : "";
|
||||
device.busVersion = "";
|
||||
device.busVersionNull = true;
|
||||
device.device = "/dev/" + diskBsdName;
|
||||
NSString *devicePath = (NSString*)CFDictionaryGetValue(diskDescription, kDADiskDescriptionBusPathKey);
|
||||
device.devicePath = (devicePath != nil) ? [devicePath UTF8String] : "";
|
||||
device.raw = "/dev/r" + diskBsdName;
|
||||
NSString *description = (NSString*)CFDictionaryGetValue(diskDescription, kDADiskDescriptionMediaNameKey);
|
||||
device.description = (description != nil) ? [description UTF8String] : "";
|
||||
device.error = "";
|
||||
// NOTE: Not sure if kDADiskDescriptionMediaBlockSizeKey returns
|
||||
// the physical or logical block size since both values are equal
|
||||
// on my machine
|
||||
//
|
||||
// The can be checked with the following command:
|
||||
// diskutil info / | grep "Block Size"
|
||||
device.blockSize = [blockSize unsignedIntValue];
|
||||
device.logicalBlockSize = [blockSize unsignedIntValue];
|
||||
device.size = [DictionaryGetNumber(diskDescription, kDADiskDescriptionMediaSizeKey) unsignedLongValue];
|
||||
device.isReadOnly = ![DictionaryGetNumber(diskDescription, kDADiskDescriptionMediaWritableKey) boolValue];
|
||||
device.isSystem = isInternal && !isRemovable;
|
||||
device.isVirtual = ((deviceProtocol != nil) && [deviceProtocol isEqualToString:@"Virtual Interface"]);
|
||||
device.isRemovable = isRemovable || isEjectable;
|
||||
device.isCard = IsCard(diskDescription);
|
||||
// NOTE(robin): Not convinced that these bus types should result
|
||||
// in device.isSCSI = true, it is rather "not usb or sd drive" bool
|
||||
// But the old implementation was like this so kept it this way
|
||||
NSArray *scsiTypes = [NSArray arrayWithObjects:@"SATA", @"SCSI", @"ATA", @"IDE", @"PCI", nil];
|
||||
device.isSCSI = ((deviceProtocol != nil) && [scsiTypes containsObject:deviceProtocol]);
|
||||
device.isUSB = ((deviceProtocol != nil) && [deviceProtocol isEqualToString:@"USB"]);
|
||||
device.isUAS = false;
|
||||
device.isUASNull = true;
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
std::vector<DeviceDescriptor> ListStorageDevices() {
|
||||
std::vector<DeviceDescriptor> deviceList;
|
||||
|
||||
DASessionRef session = DASessionCreate(kCFAllocatorDefault);
|
||||
if (session == nil) {
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
REDiskList *dl = [[REDiskList alloc] init];
|
||||
for (NSString* diskBsdName in dl.disks) {
|
||||
if (IsDiskPartition(diskBsdName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string diskBsdNameStr = [diskBsdName UTF8String];
|
||||
DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, diskBsdNameStr.c_str());
|
||||
if (disk == nil) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CFDictionaryRef diskDescription = DADiskCopyDescription(disk);
|
||||
if (diskDescription == nil) {
|
||||
CFRelease(disk);
|
||||
continue;
|
||||
}
|
||||
|
||||
DeviceDescriptor device = CreateDeviceDescriptorFromDiskDescription(diskBsdNameStr, diskDescription);
|
||||
deviceList.push_back(device);
|
||||
|
||||
CFRelease(diskDescription);
|
||||
CFRelease(disk);
|
||||
}
|
||||
[dl release];
|
||||
|
||||
// Add mount points
|
||||
NSArray *volumeKeys = [NSArray arrayWithObjects:NSURLVolumeNameKey, NSURLVolumeLocalizedNameKey, nil];
|
||||
NSArray *volumePaths = [
|
||||
[NSFileManager defaultManager]
|
||||
mountedVolumeURLsIncludingResourceValuesForKeys:volumeKeys
|
||||
options:0
|
||||
];
|
||||
|
||||
for (NSURL *path in volumePaths) {
|
||||
DADiskRef disk = DADiskCreateFromVolumePath(kCFAllocatorDefault, session, (__bridge CFURLRef)path);
|
||||
if (disk == nil) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const char *bsdnameChar = DADiskGetBSDName(disk);
|
||||
if (bsdnameChar == nil) {
|
||||
CFRelease(disk);
|
||||
continue;
|
||||
}
|
||||
|
||||
NSString *volumeName;
|
||||
[path getResourceValue:&volumeName forKey:NSURLVolumeLocalizedNameKey error:nil];
|
||||
|
||||
std::string partitionBsdName = std::string(bsdnameChar);
|
||||
std::string diskBsdName = partitionBsdName.substr(0, partitionBsdName.find("s", 5));
|
||||
|
||||
for(std::vector<int>::size_type i = 0; i != deviceList.size(); i++) {
|
||||
DeviceDescriptor *dd = &deviceList[i];
|
||||
|
||||
if (dd->device == "/dev/" + diskBsdName) {
|
||||
dd->mountpoints.push_back([[path path] UTF8String]);
|
||||
dd->mountpointLabels.push_back([volumeName UTF8String]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(disk);
|
||||
}
|
||||
CFRelease(session);
|
||||
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
} // namespace Drivelist
|
152
dependencies/drivelist/src/device-descriptor.cpp
vendored
Normal file
152
dependencies/drivelist/src/device-descriptor.cpp
vendored
Normal file
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
|
||||
#include <nan.h>
|
||||
#include "drivelist.hpp"
|
||||
|
||||
using v8::String;
|
||||
using v8::Number;
|
||||
using v8::Boolean;
|
||||
using v8::Local;
|
||||
using v8::Value;
|
||||
using Nan::New;
|
||||
|
||||
namespace Drivelist {
|
||||
|
||||
v8::Local<v8::Object> PackDriveDescriptor(const DeviceDescriptor *instance) {
|
||||
v8::Local<v8::Object> object = Nan::New<v8::Object>();
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("enumerator").ToLocalChecked(),
|
||||
New<String>(instance->enumerator).ToLocalChecked());
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("busType").ToLocalChecked(),
|
||||
New<String>(instance->busType).ToLocalChecked());
|
||||
|
||||
Local<Value> busVersion = instance->busVersionNull ?
|
||||
(Local<Value>)Nan::Null() :
|
||||
(Local<Value>)New<String>(instance->busVersion).ToLocalChecked();
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("busVersion").ToLocalChecked(),
|
||||
busVersion);
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("device").ToLocalChecked(),
|
||||
New<String>(instance->device).ToLocalChecked());
|
||||
|
||||
Local<Value> devicePath = instance->devicePathNull ?
|
||||
(Local<Value>)Nan::Null() :
|
||||
(Local<Value>)New<String>(instance->devicePath).ToLocalChecked();
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("devicePath").ToLocalChecked(),
|
||||
devicePath);
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("raw").ToLocalChecked(),
|
||||
New<String>(instance->raw).ToLocalChecked());
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("description").ToLocalChecked(),
|
||||
New<String>(instance->description).ToLocalChecked());
|
||||
|
||||
if (instance->error != "") {
|
||||
Nan::Set(object,
|
||||
New<String>("error").ToLocalChecked(),
|
||||
New<String>(instance->error).ToLocalChecked());
|
||||
} else {
|
||||
Nan::Set(object,
|
||||
New<String>("error").ToLocalChecked(),
|
||||
Nan::Null());
|
||||
}
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("size").ToLocalChecked(),
|
||||
New<Number>(static_cast<double>(instance->size)));
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("blockSize").ToLocalChecked(),
|
||||
New<Number>(static_cast<double>(instance->blockSize)));
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("logicalBlockSize").ToLocalChecked(),
|
||||
New<Number>(static_cast<double>(instance->logicalBlockSize)));
|
||||
|
||||
v8::Local<v8::Object> mountpoints = Nan::New<v8::Array>();
|
||||
|
||||
uint32_t index = 0;
|
||||
for (std::string mountpointPath : instance->mountpoints) {
|
||||
v8::Local<v8::Object> mountpoint = Nan::New<v8::Object>();
|
||||
Nan::Set(mountpoint,
|
||||
New<String>("path").ToLocalChecked(),
|
||||
New<String>(mountpointPath).ToLocalChecked());
|
||||
|
||||
if (index < instance->mountpointLabels.size()) {
|
||||
Nan::Set(mountpoint,
|
||||
New<String>("label").ToLocalChecked(),
|
||||
New<String>(instance->mountpointLabels[index]).ToLocalChecked());
|
||||
}
|
||||
|
||||
Nan::Set(mountpoints, index, mountpoint);
|
||||
index++;
|
||||
}
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("mountpoints").ToLocalChecked(),
|
||||
mountpoints);
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("isReadOnly").ToLocalChecked(),
|
||||
New<Boolean>(instance->isReadOnly));
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("isSystem").ToLocalChecked(),
|
||||
New<Boolean>(instance->isSystem));
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("isVirtual").ToLocalChecked(),
|
||||
New<Boolean>(instance->isVirtual));
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("isRemovable").ToLocalChecked(),
|
||||
New<Boolean>(instance->isRemovable));
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("isCard").ToLocalChecked(),
|
||||
New<Boolean>(instance->isCard));
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("isSCSI").ToLocalChecked(),
|
||||
New<Boolean>(instance->isSCSI));
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("isUSB").ToLocalChecked(),
|
||||
New<Boolean>(instance->isUSB));
|
||||
|
||||
Local<Value> isUAS = instance->isUASNull ?
|
||||
(Local<Value>)Nan::Null() :
|
||||
(Local<Value>)New<Boolean>(instance->isUAS);
|
||||
|
||||
Nan::Set(object,
|
||||
New<String>("isUAS").ToLocalChecked(),
|
||||
isUAS);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
} // namespace Drivelist
|
66
dependencies/drivelist/src/drivelist.cpp
vendored
Normal file
66
dependencies/drivelist/src/drivelist.cpp
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
|
||||
#include <nan.h>
|
||||
#include <vector>
|
||||
#include "drivelist.hpp"
|
||||
|
||||
class DriveListWorker : public Nan::AsyncWorker {
|
||||
public:
|
||||
explicit DriveListWorker(Nan::Callback *callback)
|
||||
: Nan::AsyncWorker(callback), devices() {}
|
||||
|
||||
~DriveListWorker() {}
|
||||
|
||||
void Execute() {
|
||||
devices = Drivelist::ListStorageDevices();
|
||||
}
|
||||
|
||||
void HandleOKCallback() {
|
||||
Nan::HandleScope scope;
|
||||
v8::Local<v8::Object> drives = Nan::New<v8::Array>();
|
||||
|
||||
uint32_t i;
|
||||
uint32_t size = (uint32_t) devices.size();
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
Nan::Set(drives, i, Drivelist::PackDriveDescriptor(&devices[i]));
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> argv[] = { Nan::Null(), drives };
|
||||
callback->Call(2, argv, async_resource);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Drivelist::DeviceDescriptor> devices;
|
||||
};
|
||||
|
||||
NAN_METHOD(list) {
|
||||
if (!info[0]->IsFunction()) {
|
||||
return Nan::ThrowTypeError("Callback must be a function");
|
||||
}
|
||||
|
||||
Nan::Callback *callback = new Nan::Callback(info[0].As<v8::Function>());
|
||||
Nan::AsyncQueueWorker(new DriveListWorker(callback));
|
||||
|
||||
info.GetReturnValue().SetUndefined();
|
||||
}
|
||||
|
||||
NAN_MODULE_INIT(InitAll) {
|
||||
NAN_EXPORT(target, list);
|
||||
}
|
||||
|
||||
NODE_MODULE(DriveList, InitAll);
|
64
dependencies/drivelist/src/drivelist.hpp
vendored
Normal file
64
dependencies/drivelist/src/drivelist.hpp
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef SRC_DRIVELIST_HPP_
|
||||
#define SRC_DRIVELIST_HPP_
|
||||
|
||||
#include <nan.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Drivelist {
|
||||
|
||||
struct MountPoint {
|
||||
std::string path;
|
||||
};
|
||||
|
||||
struct DeviceDescriptor {
|
||||
std::string enumerator;
|
||||
std::string busType;
|
||||
std::string busVersion;
|
||||
bool busVersionNull;
|
||||
std::string device;
|
||||
std::string devicePath;
|
||||
bool devicePathNull;
|
||||
std::string raw;
|
||||
std::string description;
|
||||
std::string error;
|
||||
uint64_t size;
|
||||
uint32_t blockSize = 512;
|
||||
uint32_t logicalBlockSize = 512;
|
||||
std::vector<std::string> mountpoints;
|
||||
std::vector<std::string> mountpointLabels;
|
||||
bool isReadOnly; // Device is read-only
|
||||
bool isSystem; // Device is a system drive
|
||||
bool isVirtual; // Device is a virtual storage device
|
||||
bool isRemovable; // Device is removable from the running system
|
||||
bool isCard; // Device is an SD-card
|
||||
bool isSCSI; // Connected via the Small Computer System Interface (SCSI)
|
||||
bool isUSB; // Connected via Universal Serial Bus (USB)
|
||||
bool isUAS; // Connected via the USB Attached SCSI (UAS)
|
||||
bool isUASNull;
|
||||
};
|
||||
|
||||
std::vector<DeviceDescriptor> ListStorageDevices();
|
||||
v8::Local<v8::Object> PackDriveDescriptor(const DeviceDescriptor *instance);
|
||||
|
||||
} // namespace Drivelist
|
||||
|
||||
NAN_METHOD(list);
|
||||
|
||||
#endif // SRC_DRIVELIST_HPP_
|
28
dependencies/drivelist/src/linux/list.cpp
vendored
Normal file
28
dependencies/drivelist/src/linux/list.cpp
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
|
||||
#include <nan.h>
|
||||
#include "../drivelist.hpp"
|
||||
|
||||
namespace Drivelist {
|
||||
|
||||
// TODO(jhermsmeier): Implement
|
||||
std::vector<DeviceDescriptor> ListStorageDevices() {
|
||||
std::vector<DeviceDescriptor> drivelist;
|
||||
return drivelist;
|
||||
}
|
||||
|
||||
} // namespace Drivelist
|
680
dependencies/drivelist/src/windows/list.cpp
vendored
Normal file
680
dependencies/drivelist/src/windows/list.cpp
vendored
Normal file
|
@ -0,0 +1,680 @@
|
|||
/*
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
|
||||
// See https://support.microsoft.com/en-us/kb/165721
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#define _WIN32_WINNT 0x0601
|
||||
|
||||
#include <windows.h>
|
||||
#include <winioctl.h>
|
||||
#include <cfgmgr32.h>
|
||||
#include <setupapi.h>
|
||||
#include <shlobj.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <nan.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include "../drivelist.hpp"
|
||||
#include "list.hpp"
|
||||
|
||||
#include <devpkey.h>
|
||||
|
||||
// Maxnet edit
|
||||
#ifndef DEVPKEY_Device_EnumeratorName
|
||||
DEFINE_DEVPROPKEY(DEVPKEY_Device_EnumeratorName, 0xa45c254e,0xdf1c,0x4efd,0x80,0x20,0x67,0xd1,0x46,0xa8,0x50,0xe0, 24);
|
||||
#endif
|
||||
//
|
||||
|
||||
namespace Drivelist {
|
||||
|
||||
char* WCharToUtf8(const wchar_t* wstr) {
|
||||
char *str = NULL;
|
||||
size_t size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
|
||||
|
||||
if (size <= 1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((str = reinterpret_cast<char*>(calloc(size, 1))) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t utf8Size = WideCharToMultiByte(
|
||||
CP_UTF8, 0, wstr, -1, str, size, NULL, NULL);
|
||||
|
||||
if (utf8Size != size) {
|
||||
free(str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
char* GetEnumeratorName(HDEVINFO hDeviceInfo, SP_DEVINFO_DATA deviceInfoData) {
|
||||
char buffer[MAX_PATH];
|
||||
|
||||
ZeroMemory(&buffer, sizeof(buffer));
|
||||
|
||||
BOOL hasEnumeratorName = SetupDiGetDeviceRegistryPropertyA(
|
||||
hDeviceInfo, &deviceInfoData, SPDRP_ENUMERATOR_NAME,
|
||||
NULL, (LPBYTE) buffer, sizeof(buffer), NULL);
|
||||
|
||||
/*if (!hasEnumeratorName)
|
||||
{
|
||||
hasEnumeratorName = SetupDiGetDevicePropertyW(hDeviceInfo, &deviceInfoData, &DEVPKEY_Device_EnumeratorName, NULL, (LPBYTE) buffer, sizeof(buffer), NULL, 0);
|
||||
}*/
|
||||
|
||||
return hasEnumeratorName ? buffer : NULL;
|
||||
}
|
||||
|
||||
std::string GetFriendlyName(HDEVINFO hDeviceInfo,
|
||||
SP_DEVINFO_DATA deviceInfoData) {
|
||||
wchar_t wbuffer[MAX_PATH];
|
||||
|
||||
ZeroMemory(&wbuffer, sizeof(wbuffer));
|
||||
|
||||
BOOL hasFriendlyName = SetupDiGetDeviceRegistryPropertyW(
|
||||
hDeviceInfo, &deviceInfoData, SPDRP_FRIENDLYNAME,
|
||||
NULL, (PBYTE) wbuffer, sizeof(wbuffer), NULL);
|
||||
|
||||
return hasFriendlyName ? WCharToUtf8(wbuffer) : std::string("");
|
||||
}
|
||||
|
||||
bool IsSCSIDevice(std::string enumeratorName) {
|
||||
for (std::string driverName : GENERIC_STORAGE_DRIVERS) {
|
||||
if (enumeratorName == driverName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsUSBDevice(std::string enumeratorName) {
|
||||
for (std::string driverName : USB_STORAGE_DRIVERS) {
|
||||
if (enumeratorName == driverName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsRemovableDevice(HDEVINFO hDeviceInfo, SP_DEVINFO_DATA deviceInfoData) {
|
||||
DWORD result = 0;
|
||||
|
||||
BOOL hasRemovalPolicy = SetupDiGetDeviceRegistryProperty(
|
||||
hDeviceInfo, &deviceInfoData, SPDRP_REMOVAL_POLICY,
|
||||
NULL, (PBYTE) &result, sizeof(result), NULL);
|
||||
|
||||
switch (result) {
|
||||
case CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL:
|
||||
case CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsVirtualHardDrive(HDEVINFO hDeviceInfo, SP_DEVINFO_DATA deviceInfoData) {
|
||||
char buffer[MAX_PATH];
|
||||
|
||||
ZeroMemory(&buffer, sizeof(buffer));
|
||||
|
||||
BOOL hasHardwareId = SetupDiGetDeviceRegistryPropertyA(
|
||||
hDeviceInfo, &deviceInfoData, SPDRP_HARDWAREID,
|
||||
NULL, (LPBYTE) buffer, sizeof(buffer), NULL);
|
||||
|
||||
if (!hasHardwareId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// printf("SPDRP_HARDWAREID: %s\n", buffer);
|
||||
|
||||
std::string hardwareId(buffer);
|
||||
|
||||
for (std::string vhdHardwareId : VHD_HARDWARE_IDS) {
|
||||
if (hardwareId.find(vhdHardwareId, 0) != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsSystemDevice(HDEVINFO hDeviceInfo, DeviceDescriptor *device) {
|
||||
PWSTR folderPath = NULL;
|
||||
BOOL isSystem = false;
|
||||
|
||||
for (const GUID folderId : KNOWN_FOLDER_IDS) {
|
||||
HRESULT result = SHGetKnownFolderPath(
|
||||
folderId, 0, NULL, &folderPath);
|
||||
|
||||
if (result == S_OK) {
|
||||
std::string systemPath = WCharToUtf8(folderPath);
|
||||
// printf("systemPath %s\n", systemPath.c_str());
|
||||
for (std::string mountpoint : device->mountpoints) {
|
||||
// printf("%s find %s\n", systemPath.c_str(), mountpoint.c_str());
|
||||
if (systemPath.find(mountpoint, 0) != std::string::npos) {
|
||||
isSystem = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CoTaskMemFree(folderPath);
|
||||
}
|
||||
|
||||
return isSystem;
|
||||
}
|
||||
|
||||
std::vector<std::string> GetAvailableVolumes() {
|
||||
DWORD logicalDrivesMask = GetLogicalDrives();
|
||||
std::vector<std::string> logicalDrives;
|
||||
|
||||
if (logicalDrivesMask == 0) {
|
||||
return logicalDrives;
|
||||
}
|
||||
|
||||
char currentDriveLetter = 'A';
|
||||
|
||||
while (logicalDrivesMask) {
|
||||
if (logicalDrivesMask & 1) {
|
||||
logicalDrives.push_back(std::string(1, currentDriveLetter));
|
||||
}
|
||||
currentDriveLetter++;
|
||||
logicalDrivesMask >>= 1;
|
||||
}
|
||||
|
||||
return logicalDrives;
|
||||
}
|
||||
|
||||
int32_t GetDeviceNumber(HANDLE hDevice) {
|
||||
BOOL result;
|
||||
DWORD size;
|
||||
DWORD errorCode = 0;
|
||||
int32_t diskNumber = -1;
|
||||
|
||||
STORAGE_DEVICE_NUMBER deviceNumber;
|
||||
VOLUME_DISK_EXTENTS diskExtents;
|
||||
|
||||
// Some devices will have the diskNumber exposed through their disk extents,
|
||||
// while most of them will only have one accessible through
|
||||
// `IOCTL_STORAGE_GET_DEVICE_NUMBER`, so we check this one first,
|
||||
// augmenting / overriding it with the latter
|
||||
result = DeviceIoControl(
|
||||
hDevice, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0,
|
||||
&diskExtents, sizeof(VOLUME_DISK_EXTENTS), &size, NULL);
|
||||
|
||||
if (result && diskExtents.NumberOfDiskExtents > 0) {
|
||||
// printf("[INFO] DiskNumber: %i\n", diskExtents.Extents[0].DiskNumber);
|
||||
|
||||
// NOTE: Always ignore RAIDs
|
||||
// TODO(jhermsmeier): Handle RAIDs properly
|
||||
if (diskExtents.NumberOfDiskExtents >= 2) {
|
||||
// printf("[INFO] Possible RAID: %i\n",
|
||||
// diskExtents.Extents[0].DiskNumber);
|
||||
return -1;
|
||||
}
|
||||
diskNumber = diskExtents.Extents[0].DiskNumber;
|
||||
} else {
|
||||
errorCode = GetLastError();
|
||||
// printf("[INFO] VOLUME_GET_VOLUME_DISK_EXTENTS: Error 0x%08lX\n",
|
||||
// errorCode);
|
||||
}
|
||||
|
||||
result = DeviceIoControl(
|
||||
hDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0,
|
||||
&deviceNumber, sizeof(deviceNumber), &size, NULL);
|
||||
|
||||
if (result) {
|
||||
// printf("[INFO] DeviceNumber: %i\n", deviceNumber.DeviceNumber);
|
||||
diskNumber = deviceNumber.DeviceNumber;
|
||||
}
|
||||
|
||||
// errorCode = GetLastError();
|
||||
// printf("[INFO] STORAGE_GET_DEVICE_NUMBER: Error 0x%08lX\n", errorCode);
|
||||
|
||||
return diskNumber;
|
||||
}
|
||||
|
||||
void GetMountpoints(int32_t deviceNumber,
|
||||
std::vector<std::string> *mountpoints) {
|
||||
HANDLE hLogical = INVALID_HANDLE_VALUE;
|
||||
int32_t logicalVolumeDeviceNumber = -1;
|
||||
UINT driveType;
|
||||
|
||||
std::vector<std::string> logicalVolumes = GetAvailableVolumes();
|
||||
|
||||
for (std::string volumeName : logicalVolumes) {
|
||||
if (hLogical != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(hLogical);
|
||||
hLogical = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
// NOTE: Ignore everything that's not a fixed or removable drive,
|
||||
// as device numbers are not unique across storage type drivers (!?),
|
||||
// and this would otherwise cause CD/DVD drive letters to be
|
||||
// attributed to blockdevices
|
||||
driveType = GetDriveTypeA((volumeName + ":\\").c_str());
|
||||
|
||||
// printf("[INFO] Checking %s:/\n", volumeName.c_str());
|
||||
|
||||
if ((driveType != DRIVE_FIXED) && (driveType != DRIVE_REMOVABLE)) {
|
||||
// printf("[INFO] Ignoring volume %s:/ - Not FIXED | REMOVABLE\n",
|
||||
// volumeName.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
hLogical = CreateFileA(
|
||||
("\\\\.\\" + volumeName + ":").c_str(), 0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (hLogical == INVALID_HANDLE_VALUE) {
|
||||
// printf("[INFO] Couldn't open handle to logical volume %s\n",
|
||||
// volumeName.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
logicalVolumeDeviceNumber = GetDeviceNumber(hLogical);
|
||||
|
||||
if (logicalVolumeDeviceNumber == -1) {
|
||||
// printf("[INFO] Couldn't get device number for logical volume %s\n",
|
||||
// volumeName.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (logicalVolumeDeviceNumber == deviceNumber) {
|
||||
// printf("[INFO] Device number for logical volume %s is %i\n",
|
||||
// volumeName.c_str(), logicalVolumeDeviceNumber);
|
||||
mountpoints->push_back(volumeName + ":\\");
|
||||
}
|
||||
}
|
||||
|
||||
if (hLogical != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(hLogical);
|
||||
hLogical = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetBusType(STORAGE_ADAPTER_DESCRIPTOR *adapterDescriptor) {
|
||||
switch (adapterDescriptor->BusType) {
|
||||
case STORAGE_BUS_TYPE::BusTypeUnknown: return "UNKNOWN";
|
||||
case STORAGE_BUS_TYPE::BusTypeScsi: return "SCSI";
|
||||
case STORAGE_BUS_TYPE::BusTypeAtapi: return "ATAPI";
|
||||
case STORAGE_BUS_TYPE::BusTypeAta: return "ATA";
|
||||
case STORAGE_BUS_TYPE::BusType1394: return "1394"; // IEEE 1394
|
||||
case STORAGE_BUS_TYPE::BusTypeSsa: return "SSA";
|
||||
case STORAGE_BUS_TYPE::BusTypeFibre: return "FIBRE";
|
||||
case STORAGE_BUS_TYPE::BusTypeUsb: return "USB";
|
||||
case STORAGE_BUS_TYPE::BusTypeRAID: return "RAID";
|
||||
case STORAGE_BUS_TYPE::BusTypeiScsi: return "iSCSI";
|
||||
case STORAGE_BUS_TYPE::BusTypeSas: return "SAS"; // Serial-Attached SCSI
|
||||
case STORAGE_BUS_TYPE::BusTypeSata: return "SATA";
|
||||
case STORAGE_BUS_TYPE::BusTypeSd: return "SD"; // Secure Digital (SD)
|
||||
case STORAGE_BUS_TYPE::BusTypeMmc: return "MMC"; // Multimedia card
|
||||
case STORAGE_BUS_TYPE::BusTypeVirtual: return "VIRTUAL";
|
||||
case STORAGE_BUS_TYPE::BusTypeFileBackedVirtual: return "FILEBACKEDVIRTUAL";
|
||||
default: return "INVALID";
|
||||
}
|
||||
}
|
||||
|
||||
bool GetAdapterInfo(HANDLE hPhysical, DeviceDescriptor *device) {
|
||||
STORAGE_PROPERTY_QUERY query;
|
||||
STORAGE_ADAPTER_DESCRIPTOR adapterDescriptor;
|
||||
DWORD size = 0;
|
||||
|
||||
ZeroMemory(&query, sizeof(query));
|
||||
|
||||
query.QueryType = STORAGE_QUERY_TYPE::PropertyStandardQuery;
|
||||
query.PropertyId = STORAGE_PROPERTY_ID::StorageAdapterProperty;
|
||||
|
||||
BOOL hasAdapterInfo = DeviceIoControl(
|
||||
hPhysical, IOCTL_STORAGE_QUERY_PROPERTY,
|
||||
&query, sizeof(STORAGE_PROPERTY_QUERY),
|
||||
&adapterDescriptor, sizeof(STORAGE_ADAPTER_DESCRIPTOR), &size, NULL);
|
||||
|
||||
if (hasAdapterInfo) {
|
||||
device->busType = GetBusType(&adapterDescriptor);
|
||||
device->busVersion = std::to_string(adapterDescriptor.BusMajorVersion) +
|
||||
"." + std::to_string(adapterDescriptor.BusMinorVersion);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetDeviceBlockSize(HANDLE hPhysical, DeviceDescriptor *device) {
|
||||
STORAGE_PROPERTY_QUERY query;
|
||||
STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR alignmentDescriptor;
|
||||
DWORD size = 0;
|
||||
|
||||
ZeroMemory(&query, sizeof(query));
|
||||
|
||||
query.QueryType = STORAGE_QUERY_TYPE::PropertyStandardQuery;
|
||||
query.PropertyId = STORAGE_PROPERTY_ID::StorageAccessAlignmentProperty;
|
||||
|
||||
BOOL hasAlignmentDescriptor = DeviceIoControl(
|
||||
hPhysical, IOCTL_STORAGE_QUERY_PROPERTY,
|
||||
&query, sizeof(STORAGE_PROPERTY_QUERY),
|
||||
&alignmentDescriptor, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR),
|
||||
&size, NULL);
|
||||
|
||||
if (hasAlignmentDescriptor) {
|
||||
device->blockSize = alignmentDescriptor.BytesPerPhysicalSector;
|
||||
device->logicalBlockSize = alignmentDescriptor.BytesPerLogicalSector;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetDeviceSize(HANDLE hPhysical, DeviceDescriptor *device) {
|
||||
DISK_GEOMETRY_EX diskGeometry;
|
||||
|
||||
// printf("[INFO] hasDiskGeometry\n");
|
||||
|
||||
BOOL hasDiskGeometry = false;
|
||||
DWORD size = 0;
|
||||
|
||||
hasDiskGeometry = DeviceIoControl(
|
||||
hPhysical, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0,
|
||||
&diskGeometry, sizeof(DISK_GEOMETRY_EX), &size, NULL);
|
||||
|
||||
// printf("[INFO] hasDiskGeometry %i\n", hasDiskGeometry);
|
||||
|
||||
// NOTE: Another way to get the block size would be
|
||||
// `IOCTL_STORAGE_QUERY_PROPERTY` with `STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR`,
|
||||
// which can yield more (or possibly more accurate?) info,
|
||||
// but might not work with external HDDs/SSDs
|
||||
if (hasDiskGeometry) {
|
||||
device->size = diskGeometry.DiskSize.QuadPart;
|
||||
device->blockSize = diskGeometry.Geometry.BytesPerSector;
|
||||
}
|
||||
|
||||
return hasDiskGeometry;
|
||||
}
|
||||
|
||||
bool GetDetailData(DeviceDescriptor* device,
|
||||
HDEVINFO hDeviceInfo, SP_DEVINFO_DATA deviceInfoData) {
|
||||
DWORD index;
|
||||
DWORD size;
|
||||
DWORD errorCode = 0;
|
||||
bool result = true;
|
||||
|
||||
HANDLE hDevice = INVALID_HANDLE_VALUE;
|
||||
HANDLE hPhysical = INVALID_HANDLE_VALUE;
|
||||
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA_W deviceDetailData(NULL);
|
||||
|
||||
for (index = 0; ; index++) {
|
||||
if (hDevice != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(hDevice);
|
||||
hDevice = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (hPhysical != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(hPhysical);
|
||||
hPhysical = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||
|
||||
// printf("[INFO] (%i) SetupDiEnumDeviceInterfaces - isDisk\n", index);
|
||||
|
||||
BOOL isDisk = SetupDiEnumDeviceInterfaces(
|
||||
hDeviceInfo, &deviceInfoData, &GUID_DEVICE_INTERFACE_DISK,
|
||||
index, &deviceInterfaceData);
|
||||
|
||||
if (!isDisk) {
|
||||
errorCode = GetLastError();
|
||||
if (errorCode == ERROR_NO_MORE_ITEMS) {
|
||||
// printf("[INFO] (%i) EnumDeviceInterfaces: No more items 0x%08lX\n",
|
||||
// index, errorCode);
|
||||
result = index != 0;
|
||||
break;
|
||||
} else {
|
||||
device->error = "SetupDiEnumDeviceInterfaces: Error " +
|
||||
std::to_string(errorCode);
|
||||
}
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
BOOL hasDeviceInterfaceData = SetupDiGetDeviceInterfaceDetailW(
|
||||
hDeviceInfo, &deviceInterfaceData, NULL, 0, &size, NULL);
|
||||
|
||||
if (!hasDeviceInterfaceData) {
|
||||
errorCode = GetLastError();
|
||||
if (errorCode == ERROR_INSUFFICIENT_BUFFER) {
|
||||
deviceDetailData = static_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA_W>
|
||||
(malloc(size));
|
||||
if (deviceDetailData == NULL) {
|
||||
device->error = "SetupDiGetDeviceInterfaceDetailW: "
|
||||
"Unable to allocate SP_DEVICE_INTERFACE_DETAIL_DATA_W"
|
||||
"(" + std::to_string(size) + "); "
|
||||
"Error " + std::to_string(errorCode);
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
// printf("Allocated SP_DEVICE_INTERFACE_DETAIL_DATA_W\n");
|
||||
} else {
|
||||
device->error = "SetupDiGetDeviceInterfaceDetailW: "
|
||||
"Couldn't get detail data; Error " + std::to_string(errorCode);
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// printf("[INFO] (%i) Getting SP_DEVICE_INTERFACE_DETAIL_DATA_W\n", index);
|
||||
|
||||
deviceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
|
||||
|
||||
BOOL hasDeviceDetail = SetupDiGetDeviceInterfaceDetailW(
|
||||
hDeviceInfo, &deviceInterfaceData, deviceDetailData, size, &size, NULL);
|
||||
|
||||
if (!hasDeviceDetail) {
|
||||
errorCode = GetLastError();
|
||||
device->error = "Couldn't SetupDiGetDeviceInterfaceDetailW: Error " +
|
||||
std::to_string(errorCode);
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// printf("[INFO] (%i) SetupDiGetDeviceInterfaceDetailW:\n %s\n",
|
||||
// index, WCharToUtf8(deviceDetailData->DevicePath));
|
||||
|
||||
// Passing zero to `CreateFile()` doesn't require permissions to
|
||||
// open the device handle, but only lets you acquire device metadata,
|
||||
// which is all we want
|
||||
hDevice = CreateFileW(
|
||||
deviceDetailData->DevicePath, 0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (hDevice == INVALID_HANDLE_VALUE) {
|
||||
errorCode = GetLastError();
|
||||
// printf("[ERROR] Couldn't open handle to device: Error %i", errorCode);
|
||||
device->error = "Couldn't open handle to device: Error " +
|
||||
std::to_string(errorCode);
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
int32_t deviceNumber = GetDeviceNumber(hDevice);
|
||||
|
||||
if (deviceNumber == -1) {
|
||||
device->error = "Couldn't get device number";
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
device->raw = "\\\\.\\PhysicalDrive" + std::to_string(deviceNumber);
|
||||
device->device = device->raw;
|
||||
|
||||
GetMountpoints(deviceNumber, &device->mountpoints);
|
||||
|
||||
// printf("[INFO] Opening handle to %s\n", device->raw.c_str());
|
||||
|
||||
hPhysical = CreateFileA(
|
||||
device->raw.c_str(), 0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
// printf("[INFO] Opened handle to %s\n", device->raw.c_str());
|
||||
// printf("[INFO] Handle %i (INVALID %i)\n",
|
||||
// hPhysical, INVALID_HANDLE_VALUE);
|
||||
|
||||
if (hPhysical == INVALID_HANDLE_VALUE) {
|
||||
errorCode = GetLastError();
|
||||
// printf("[INFO] Couldn't open handle to %s: Error %i\n",
|
||||
// device->raw.c_str(), errorCode);
|
||||
device->error = "Couldn't open handle to physical device: Error " +
|
||||
std::to_string(errorCode);
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// printf("[INFO] GetDeviceSize( %s )\n", device->raw.c_str());
|
||||
|
||||
if (!GetDeviceSize(hPhysical, device)) {
|
||||
errorCode = GetLastError();
|
||||
// printf("[ERROR] Couldn't get disk geometry: Error %i\n", errorCode);
|
||||
device->error = "Couldn't get disk geometry: Error " +
|
||||
std::to_string(errorCode);
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// printf("[INFO] GetAdapterInfo( %s )\n", device->raw.c_str());
|
||||
|
||||
if (!GetAdapterInfo(hPhysical, device)) {
|
||||
errorCode = GetLastError();
|
||||
// printf("[ERROR] Couldn't get device adapter descriptor: Error %i\n",
|
||||
// errorCode);
|
||||
device->error = "Couldn't get device adapter descriptor: Error " +
|
||||
std::to_string(errorCode);
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// printf("[INFO] GetDeviceBlockSize( %s )\n", device->raw.c_str());
|
||||
|
||||
// NOTE: No need to fail over this one,
|
||||
// as we can safely default to a 512B block size
|
||||
if (!GetDeviceBlockSize(hPhysical, device)) {
|
||||
errorCode = GetLastError();
|
||||
// printf("[INFO] Couldn't get block size: Error %u\n", errorCode);
|
||||
}
|
||||
|
||||
// printf("[INFO] isWritable( %s )\n", device->raw.c_str());
|
||||
|
||||
BOOL isWritable = DeviceIoControl(
|
||||
hPhysical, IOCTL_DISK_IS_WRITABLE, NULL, 0,
|
||||
NULL, 0, &size, NULL);
|
||||
|
||||
device->isReadOnly = !isWritable;
|
||||
} // end for (index = 0; ; index++)
|
||||
|
||||
if (hDevice != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(hDevice);
|
||||
hDevice = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (hPhysical != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(hPhysical);
|
||||
hPhysical = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
free(deviceDetailData);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<DeviceDescriptor> ListStorageDevices() {
|
||||
HDEVINFO hDeviceInfo = NULL;
|
||||
SP_DEVINFO_DATA deviceInfoData;
|
||||
std::vector<DeviceDescriptor> deviceList;
|
||||
|
||||
DWORD i;
|
||||
char *enumeratorName;
|
||||
DeviceDescriptor device;
|
||||
|
||||
hDeviceInfo = SetupDiGetClassDevsA(
|
||||
&GUID_DEVICE_INTERFACE_DISK, NULL, NULL,
|
||||
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
|
||||
if (hDeviceInfo == INVALID_HANDLE_VALUE) {
|
||||
printf("[ERROR] Invalid DeviceInfo handle\n");
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
|
||||
for (i = 0; SetupDiEnumDeviceInfo(hDeviceInfo, i, &deviceInfoData); i++) {
|
||||
enumeratorName = GetEnumeratorName(hDeviceInfo, deviceInfoData);
|
||||
|
||||
printf("[INFO] Enumerating %s\n", enumeratorName);
|
||||
|
||||
// If it failed to get the SPDRP_ENUMERATOR_NAME, skip it
|
||||
//if (enumeratorName == NULL) {
|
||||
// continue;
|
||||
//}
|
||||
|
||||
device = DeviceDescriptor();
|
||||
|
||||
device.enumerator = enumeratorName ? std::string(enumeratorName) : "";
|
||||
device.description = GetFriendlyName(hDeviceInfo, deviceInfoData);
|
||||
device.isRemovable = IsRemovableDevice(hDeviceInfo, deviceInfoData);
|
||||
device.isVirtual = IsVirtualHardDrive(hDeviceInfo, deviceInfoData);
|
||||
device.isSCSI = enumeratorName ? IsSCSIDevice(enumeratorName) : false;
|
||||
device.isUSB = enumeratorName ? IsUSBDevice(enumeratorName) : false;
|
||||
device.isCard = device.enumerator == "SD";
|
||||
device.isSystem = !device.isRemovable &&
|
||||
(device.enumerator == "SCSI" || device.enumerator == "IDE");
|
||||
device.isUAS = device.isSCSI && device.isRemovable &&
|
||||
!device.isVirtual && !device.isCard;
|
||||
device.devicePathNull = true;
|
||||
|
||||
if (GetDetailData(&device, hDeviceInfo, deviceInfoData)) {
|
||||
device.isSystem = device.isSystem || IsSystemDevice(hDeviceInfo, &device);
|
||||
device.isCard = device.busType == "SD" || device.busType == "MMC";
|
||||
device.isUAS = device.enumerator == "SCSI" && device.busType == "USB";
|
||||
device.isVirtual = device.isVirtual ||
|
||||
device.busType == "VIRTUAL" ||
|
||||
device.busType == "FILEBACKEDVIRTUAL";
|
||||
} else if (device.error == "") {
|
||||
device.error = "Couldn't get detail data";
|
||||
}
|
||||
|
||||
deviceList.push_back(device);
|
||||
}
|
||||
|
||||
SetupDiDestroyDeviceInfoList(hDeviceInfo);
|
||||
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
} // namespace Drivelist
|
108
dependencies/drivelist/src/windows/list.hpp
vendored
Normal file
108
dependencies/drivelist/src/windows/list.hpp
vendored
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef SRC_WINDOWS_LIST_HPP_
|
||||
#define SRC_WINDOWS_LIST_HPP_
|
||||
|
||||
#include <knownfolders.h>
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
namespace Drivelist {
|
||||
|
||||
// The <ntddstor.h>, and <usbiodef.h> headers include the following
|
||||
// device interface GUIDs we're interested in;
|
||||
// @see https://docs.microsoft.com/en-us/windows-hardware/drivers/install/install-reference
|
||||
// @see https://msdn.microsoft.com/en-us/library/windows/hardware/ff541389(v=vs.85).aspx
|
||||
// To avoid cluttering the global namespace,
|
||||
// we'll just define here what we need:
|
||||
//
|
||||
// - GUID_DEVINTERFACE_DISK { 53F56307-B6BF-11D0-94F2-00A0C91EFB8B }
|
||||
// - GUID_DEVINTERFACE_CDROM { 53F56308-B6BF-11D0-94F2-00A0C91EFB8B }
|
||||
// - GUID_DEVINTERFACE_USB_HUB { F18A0E88-C30C-11D0-8815-00A0C906BED8 }
|
||||
// - GUID_DEVINTERFACE_FLOPPY { 53F56311-B6BF-11D0-94F2-00A0C91EFB8B }
|
||||
// - GUID_DEVINTERFACE_WRITEONCEDISK { 53F5630C-B6BF-11D0-94F2-00A0C91EFB8B }
|
||||
// - GUID_DEVINTERFACE_TAPE { 53F5630B-B6BF-11D0-94F2-00A0C91EFB8B }
|
||||
// - GUID_DEVINTERFACE_USB_DEVICE { A5DCBF10-6530-11D2-901F-00C04FB951ED }
|
||||
// - GUID_DEVINTERFACE_VOLUME { 53F5630D-B6BF-11D0-94F2-00A0C91EFB8B }
|
||||
// - GUID_DEVINTERFACE_STORAGEPORT { 2ACCFE60-C130-11D2-B082-00A0C91EFB8B }
|
||||
//
|
||||
const GUID GUID_DEVICE_INTERFACE_DISK = {
|
||||
0x53F56307L, 0xB6BF, 0x11D0, { 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B }
|
||||
};
|
||||
|
||||
const GUID GUID_DEVICE_INTERFACE_CDROM = {
|
||||
0x53F56308L, 0xB6BF, 0x11D0, { 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B }
|
||||
};
|
||||
|
||||
const GUID GUID_DEVICE_INTERFACE_USB_HUB = {
|
||||
0xF18A0E88L, 0xC30C, 0x11D0, { 0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8 }
|
||||
};
|
||||
|
||||
const GUID GUID_DEVICE_INTERFACE_FLOPPY = {
|
||||
0x53F56311L, 0xB6BF, 0x11D0, { 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B }
|
||||
};
|
||||
|
||||
const GUID GUID_DEVICE_INTERFACE_WRITEONCEDISK = {
|
||||
0x53F5630CL, 0xB6BF, 0x11D0, { 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B }
|
||||
};
|
||||
|
||||
const GUID GUID_DEVICE_INTERFACE_TAPE = {
|
||||
0x53F5630BL, 0xB6BF, 0x11D0, { 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B }
|
||||
};
|
||||
|
||||
const GUID GUID_DEVICE_INTERFACE_USB_DEVICE = {
|
||||
0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED }
|
||||
};
|
||||
|
||||
const GUID GUID_DEVICE_INTERFACE_VOLUME = {
|
||||
0x53F5630DL, 0xB6BF, 0x11D0, { 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B }
|
||||
};
|
||||
|
||||
const GUID GUID_DEVICE_INTERFACE_STORAGEPORT = {
|
||||
0x2ACCFE60L, 0xC130, 0x11D2, { 0xB0, 0x82, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B }
|
||||
};
|
||||
|
||||
const std::set<std::string> USB_STORAGE_DRIVERS {
|
||||
"USBSTOR", "UASPSTOR", "VUSBSTOR",
|
||||
"RTUSER", "CMIUCR", "EUCR",
|
||||
"ETRONSTOR", "ASUSSTPT"
|
||||
};
|
||||
|
||||
const std::set<std::string> GENERIC_STORAGE_DRIVERS {
|
||||
"SCSI", "SD", "PCISTOR",
|
||||
"RTSOR", "JMCR", "JMCF", "RIMMPTSK", "RIMSPTSK", "RIXDPTSK",
|
||||
"TI21SONY", "ESD7SK", "ESM7SK", "O2MD", "O2SD", "VIACR"
|
||||
};
|
||||
|
||||
// List of known virtual disk hardware IDs
|
||||
const std::set<std::string> VHD_HARDWARE_IDS {
|
||||
"Arsenal_________Virtual_",
|
||||
"KernSafeVirtual_________",
|
||||
"Msft____Virtual_Disk____",
|
||||
"VMware__VMware_Virtual_S"
|
||||
};
|
||||
|
||||
const GUID KNOWN_FOLDER_IDS[] {
|
||||
FOLDERID_Windows,
|
||||
FOLDERID_Profile,
|
||||
FOLDERID_ProgramFiles,
|
||||
FOLDERID_ProgramFilesX86
|
||||
};
|
||||
|
||||
} // namespace Drivelist
|
||||
|
||||
#endif // SRC_WINDOWS_LIST_HPP_
|
44
dependencies/drivelist/tests/data/lsblk/no-children-mountpoints.json
vendored
Normal file
44
dependencies/drivelist/tests/data/lsblk/no-children-mountpoints.json
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"blockdevices": [{
|
||||
"name": "sda",
|
||||
"maj:min": "8:0",
|
||||
"rm": "1",
|
||||
"size": "14.3G",
|
||||
"ro": "0",
|
||||
"type": "disk",
|
||||
"mountpoint": "/media/jwentz/Temp"
|
||||
}, {
|
||||
"name": "nvme0n1",
|
||||
"maj:min": "259:0",
|
||||
"rm": "0",
|
||||
"size": "477G",
|
||||
"ro": "0",
|
||||
"type": "disk",
|
||||
"mountpoint": null,
|
||||
"children": [{
|
||||
"name": "nvme0n1p3",
|
||||
"maj:min": "259:3",
|
||||
"rm": "0",
|
||||
"size": "15.8G",
|
||||
"ro": "0",
|
||||
"type": "part",
|
||||
"mountpoint": "[SWAP]"
|
||||
}, {
|
||||
"name": "nvme0n1p1",
|
||||
"maj:min": "259:1",
|
||||
"rm": "0",
|
||||
"size": "512M",
|
||||
"ro": "0",
|
||||
"type": "part",
|
||||
"mountpoint": "/boot/efi"
|
||||
}, {
|
||||
"name": "nvme0n1p2",
|
||||
"maj:min": "259:2",
|
||||
"rm": "0",
|
||||
"size": "460.7G",
|
||||
"ro": "0",
|
||||
"type": "part",
|
||||
"mountpoint": "/"
|
||||
}]
|
||||
}]
|
||||
}
|
9
dependencies/drivelist/tests/data/lsblk/no-partition-table.txt
vendored
Normal file
9
dependencies/drivelist/tests/data/lsblk/no-partition-table.txt
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
NAME="sda" MAJ:MIN="8:0" RM="0" SIZE="240065183744" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="sda1" MAJ:MIN="8:1" RM="0" SIZE="209715200" RO="0" TYPE="part" MOUNTPOINT="/boot/efi"
|
||||
NAME="sda2" MAJ:MIN="8:2" RM="0" SIZE="1073741824" RO="0" TYPE="part" MOUNTPOINT="/boot"
|
||||
NAME="sda3" MAJ:MIN="8:3" RM="0" SIZE="115835142144" RO="0" TYPE="part" MOUNTPOINT=""
|
||||
NAME="centos-root" MAJ:MIN="253:0" RM="0" SIZE="53687091200" RO="0" TYPE="lvm" MOUNTPOINT="/"
|
||||
NAME="centos-swap" MAJ:MIN="253:1" RM="0" SIZE="8455716864" RO="0" TYPE="lvm" MOUNTPOINT="[SWAP]"
|
||||
NAME="centos-home" MAJ:MIN="253:2" RM="0" SIZE="53687091200" RO="0" TYPE="lvm" MOUNTPOINT="/home"
|
||||
NAME="sdb" MAJ:MIN="8:16" RM="1" SIZE="" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="sdc" MAJ:MIN="8:32" RM="1" SIZE="31457280000" RO="0" TYPE="disk" MOUNTPOINT="/run/media/DA2E4172/BUILD"
|
32
dependencies/drivelist/tests/data/lsblk/ubuntu-14.04-1.txt
vendored
Normal file
32
dependencies/drivelist/tests/data/lsblk/ubuntu-14.04-1.txt
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
NAME="sda" MAJ:MIN="8:0" RM="0" SIZE="1024209543168" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="sda1" MAJ:MIN="8:1" RM="0" SIZE="524288000" RO="0" TYPE="part" MOUNTPOINT="/boot/efi"
|
||||
NAME="sda2" MAJ:MIN="8:2" RM="0" SIZE="41943040" RO="0" TYPE="part" MOUNTPOINT=""
|
||||
NAME="sda3" MAJ:MIN="8:3" RM="0" SIZE="3221225472" RO="0" TYPE="part" MOUNTPOINT=""
|
||||
NAME="sda4" MAJ:MIN="8:4" RM="0" SIZE="235291017216" RO="0" TYPE="part" MOUNTPOINT="/"
|
||||
NAME="sda5" MAJ:MIN="8:5" RM="0" SIZE="16980639744" RO="0" TYPE="part" MOUNTPOINT="[SWAP]"
|
||||
NAME="sda6" MAJ:MIN="8:6" RM="0" SIZE="549755813888" RO="0" TYPE="part" MOUNTPOINT="/home"
|
||||
NAME="sda7" MAJ:MIN="8:7" RM="0" SIZE="218392166400" RO="0" TYPE="part" MOUNTPOINT=""
|
||||
NAME="ram0" MAJ:MIN="1:0" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram1" MAJ:MIN="1:1" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram2" MAJ:MIN="1:2" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram3" MAJ:MIN="1:3" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram4" MAJ:MIN="1:4" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram5" MAJ:MIN="1:5" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram6" MAJ:MIN="1:6" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram7" MAJ:MIN="1:7" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram8" MAJ:MIN="1:8" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram9" MAJ:MIN="1:9" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="loop0" MAJ:MIN="7:0" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop1" MAJ:MIN="7:1" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop2" MAJ:MIN="7:2" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop3" MAJ:MIN="7:3" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop4" MAJ:MIN="7:4" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop5" MAJ:MIN="7:5" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop6" MAJ:MIN="7:6" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop7" MAJ:MIN="7:7" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="ram10" MAJ:MIN="1:10" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram11" MAJ:MIN="1:11" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram12" MAJ:MIN="1:12" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram13" MAJ:MIN="1:13" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram14" MAJ:MIN="1:14" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram15" MAJ:MIN="1:15" RM="0" SIZE="67108864" RO="0" TYPE="disk" MOUNTPOINT=""
|
30
dependencies/drivelist/tests/data/lsblk/ubuntu-14.04-2.txt
vendored
Normal file
30
dependencies/drivelist/tests/data/lsblk/ubuntu-14.04-2.txt
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
NAME="fd0" MAJ:MIN="2:0" RM="1" SIZE="" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="sda" MAJ:MIN="8:0" RM="0" SIZE="32G" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="sda1" MAJ:MIN="8:1" RM="0" SIZE="30G" RO="0" TYPE="part" MOUNTPOINT="/"
|
||||
NAME="sda2" MAJ:MIN="8:2" RM="0" SIZE="1K" RO="0" TYPE="part" MOUNTPOINT=""
|
||||
NAME="sda5" MAJ:MIN="8:5" RM="0" SIZE="2G" RO="0" TYPE="part" MOUNTPOINT="[SWAP]"
|
||||
NAME="sr0" MAJ:MIN="11:0" RM="1" SIZE="1024M" RO="0" TYPE="rom" MOUNTPOINT=""
|
||||
NAME="ram0" MAJ:MIN="1:0" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram1" MAJ:MIN="1:1" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram2" MAJ:MIN="1:2" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram3" MAJ:MIN="1:3" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram4" MAJ:MIN="1:4" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram5" MAJ:MIN="1:5" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram6" MAJ:MIN="1:6" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram7" MAJ:MIN="1:7" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram8" MAJ:MIN="1:8" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram9" MAJ:MIN="1:9" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="loop0" MAJ:MIN="7:0" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop1" MAJ:MIN="7:1" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop2" MAJ:MIN="7:2" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop3" MAJ:MIN="7:3" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop4" MAJ:MIN="7:4" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop5" MAJ:MIN="7:5" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop6" MAJ:MIN="7:6" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop7" MAJ:MIN="7:7" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="ram10" MAJ:MIN="1:10" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram11" MAJ:MIN="1:11" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram12" MAJ:MIN="1:12" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram13" MAJ:MIN="1:13" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram14" MAJ:MIN="1:14" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="ram15" MAJ:MIN="1:15" RM="0" SIZE="64M" RO="0" TYPE="disk" MOUNTPOINT=""
|
23
dependencies/drivelist/tests/data/lsblk/ubuntu-14.04-3.txt
vendored
Normal file
23
dependencies/drivelist/tests/data/lsblk/ubuntu-14.04-3.txt
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
NAME="sda" MAJ:MIN="8:0" RM="0" SIZE="931.5G" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="sda1" MAJ:MIN="8:1" RM="0" SIZE="1K" RO="0" TYPE="part" MOUNTPOINT=""
|
||||
NAME="sda2" MAJ:MIN="8:2" RM="0" SIZE="488.3G" RO="0" TYPE="part" MOUNTPOINT=""
|
||||
NAME="sda5" MAJ:MIN="8:5" RM="0" SIZE="14.9G" RO="0" TYPE="part" MOUNTPOINT=""
|
||||
NAME="sda6" MAJ:MIN="8:6" RM="0" SIZE="335.2G" RO="0" TYPE="part" MOUNTPOINT=""
|
||||
NAME="sdb" MAJ:MIN="8:16" RM="1" SIZE="" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="sdc" MAJ:MIN="8:32" RM="1" SIZE="" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="sdd" MAJ:MIN="8:48" RM="1" SIZE="7.4G" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="sdd1" MAJ:MIN="8:49" RM="1" SIZE="7.4G" RO="0" TYPE="part" MOUNTPOINT="/media/<username>/85CA-6700"
|
||||
NAME="sr0" MAJ:MIN="11:0" RM="1" SIZE="1024M" RO="0" TYPE="rom" MOUNTPOINT=""
|
||||
NAME="loop0" MAJ:MIN="7:0" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop1" MAJ:MIN="7:1" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop2" MAJ:MIN="7:2" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop3" MAJ:MIN="7:3" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop4" MAJ:MIN="7:4" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop5" MAJ:MIN="7:5" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop6" MAJ:MIN="7:6" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="loop7" MAJ:MIN="7:7" RM="0" SIZE="" RO="0" TYPE="loop" MOUNTPOINT=""
|
||||
NAME="nvme0n1" MAJ:MIN="259:0" RM="0" SIZE="238.5G" RO="0" TYPE="disk" MOUNTPOINT=""
|
||||
NAME="nvme0n1p1" MAJ:MIN="259:1" RM="0" SIZE="499M" RO="0" TYPE="part" MOUNTPOINT=""
|
||||
NAME="nvme0n1p2" MAJ:MIN="259:2" RM="0" SIZE="116.6G" RO="0" TYPE="part" MOUNTPOINT=""
|
||||
NAME="nvme0n1p3" MAJ:MIN="259:3" RM="0" SIZE="4.9G" RO="0" TYPE="part" MOUNTPOINT=""
|
||||
NAME="nvme0n1p4" MAJ:MIN="259:4" RM="0" SIZE="116.5G" RO="0" TYPE="part" MOUNTPOINT="/"
|
114
dependencies/drivelist/tests/drivelist.spec.ts
vendored
Normal file
114
dependencies/drivelist/tests/drivelist.spec.ts
vendored
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright 2016 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.
|
||||
*/
|
||||
|
||||
import { ok } from 'assert';
|
||||
import { expect } from 'chai';
|
||||
import * as os from 'os';
|
||||
import { stub } from 'sinon';
|
||||
|
||||
import { list } from '../lib';
|
||||
|
||||
describe('Drivelist', () => {
|
||||
describe('.list()', () => {
|
||||
it('should yield results', async () => {
|
||||
const devices = await list();
|
||||
devices.forEach(device => {
|
||||
ok(device.enumerator, `Invalid enumerator: ${device.enumerator}`);
|
||||
ok(device.busType, `Invalid busType: ${device.busType}`);
|
||||
ok(device.device, `Invalid device: ${device.device}`);
|
||||
ok(device.raw, `Invalid raw: ${device.raw}`);
|
||||
ok(device.description, `Invalid description: ${device.description}`);
|
||||
ok(device.error === null, `Invalid error: ${device.error}`);
|
||||
ok(
|
||||
device.size === null || Number.isFinite(device.size),
|
||||
`Invalid size: ${device.size}`,
|
||||
);
|
||||
ok(
|
||||
Number.isFinite(device.blockSize),
|
||||
`Invalid blockSize: ${device.blockSize}`,
|
||||
);
|
||||
ok(
|
||||
Number.isFinite(device.logicalBlockSize),
|
||||
`Invalid logicalBlockSize: ${device.logicalBlockSize}`,
|
||||
);
|
||||
ok(
|
||||
Array.isArray(device.mountpoints),
|
||||
`Invalid mountpoints: ${device.mountpoints}`,
|
||||
);
|
||||
ok(
|
||||
device.isReadOnly === null || typeof device.isReadOnly === 'boolean',
|
||||
`Invalid isReadOnly flag: ${device.isReadOnly}`,
|
||||
);
|
||||
ok(
|
||||
device.isSystem === null || typeof device.isSystem === 'boolean',
|
||||
`Invalid isSystem flag: ${device.isSystem}`,
|
||||
);
|
||||
ok(
|
||||
device.isVirtual === null || typeof device.isVirtual === 'boolean',
|
||||
`Invalid isVirtual flag: ${device.isVirtual}`,
|
||||
);
|
||||
ok(
|
||||
device.isRemovable === null ||
|
||||
typeof device.isRemovable === 'boolean',
|
||||
`Invalid isRemovable flag: ${device.isRemovable}`,
|
||||
);
|
||||
ok(
|
||||
device.isCard === null || typeof device.isCard === 'boolean',
|
||||
`Invalid isCard flag: ${device.isCard}`,
|
||||
);
|
||||
ok(
|
||||
device.isSCSI === null || typeof device.isSCSI === 'boolean',
|
||||
`Invalid isSCSI flag: ${device.isSCSI}`,
|
||||
);
|
||||
ok(
|
||||
device.isUSB === null || typeof device.isUSB === 'boolean',
|
||||
`Invalid isUSB flag: ${device.isUSB}`,
|
||||
);
|
||||
ok(
|
||||
device.isUAS === null || typeof device.isUAS === 'boolean',
|
||||
`Invalid isUAS flag: ${device.isUAS}`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('given an unsupported os', () => {
|
||||
beforeEach(() => {
|
||||
// @ts-ignore
|
||||
this.osPlatformStub = stub(os, 'platform');
|
||||
// @ts-ignore
|
||||
this.osPlatformStub.returns('foobar');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// @ts-ignore
|
||||
this.osPlatformStub.restore();
|
||||
});
|
||||
|
||||
it('should yield an unsupported error', async () => {
|
||||
try {
|
||||
await list();
|
||||
} catch (error) {
|
||||
expect(error).to.be.an.instanceof(Error);
|
||||
expect(error.message).to.equal(
|
||||
'Your OS is not supported by this module: foobar',
|
||||
);
|
||||
return;
|
||||
}
|
||||
ok(false, 'Expected error not thrown');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
461
dependencies/drivelist/tests/lsblk.spec.ts
vendored
Normal file
461
dependencies/drivelist/tests/lsblk.spec.ts
vendored
Normal file
|
@ -0,0 +1,461 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { expect } from 'chai';
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import * as util from 'util';
|
||||
|
||||
import { transform as transformJSON } from '../lib/lsblk/json';
|
||||
import { parse as parsePairs } from '../lib/lsblk/pairs';
|
||||
|
||||
function inspect(value: any) {
|
||||
console.log(
|
||||
util.inspect(value, {
|
||||
colors: true,
|
||||
depth: null,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
describe('Drivelist', () => {
|
||||
context('lsblk', () => {
|
||||
it('can handle --pairs output on Ubuntu 14.04', () => {
|
||||
const listData = readFileSync(
|
||||
join(__dirname, 'data', 'lsblk', 'ubuntu-14.04-1.txt'),
|
||||
'utf8',
|
||||
);
|
||||
const devices = parsePairs(listData);
|
||||
|
||||
const expected = [
|
||||
{
|
||||
enumerator: 'lsblk:pairs',
|
||||
busType: 'UNKNOWN',
|
||||
busVersion: null,
|
||||
device: '/dev/sda',
|
||||
devicePath: null,
|
||||
raw: '/dev/sda',
|
||||
description: '(/boot/efi, /, [SWAP], /home)',
|
||||
error: null,
|
||||
size: 1024209543168,
|
||||
blockSize: 512,
|
||||
logicalBlockSize: 512,
|
||||
mountpoints: [
|
||||
{
|
||||
path: '/boot/efi',
|
||||
label: undefined,
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
label: undefined,
|
||||
},
|
||||
{
|
||||
path: '[SWAP]',
|
||||
label: undefined,
|
||||
},
|
||||
{
|
||||
path: '/home',
|
||||
label: undefined,
|
||||
},
|
||||
],
|
||||
isReadOnly: false,
|
||||
isSystem: true,
|
||||
isVirtual: null,
|
||||
isRemovable: false,
|
||||
isCard: null,
|
||||
isSCSI: null,
|
||||
isUSB: null,
|
||||
isUAS: null,
|
||||
},
|
||||
];
|
||||
|
||||
inspect(parsePairs(listData));
|
||||
|
||||
expect(devices).to.deep.equal(expected);
|
||||
});
|
||||
|
||||
it('can handle --pairs output on Ubuntu 14.04, sample 2', () => {
|
||||
const listData = readFileSync(
|
||||
join(__dirname, 'data', 'lsblk', 'ubuntu-14.04-2.txt'),
|
||||
'utf8',
|
||||
);
|
||||
const devices = parsePairs(listData);
|
||||
|
||||
const expected = [
|
||||
{
|
||||
enumerator: 'lsblk:pairs',
|
||||
busType: 'UNKNOWN',
|
||||
busVersion: null,
|
||||
device: '/dev/fd0',
|
||||
devicePath: null,
|
||||
raw: '/dev/fd0',
|
||||
description: 'fd0',
|
||||
error: null,
|
||||
size: null,
|
||||
blockSize: 512,
|
||||
logicalBlockSize: 512,
|
||||
mountpoints: [],
|
||||
isReadOnly: false,
|
||||
isSystem: false,
|
||||
isVirtual: null,
|
||||
isRemovable: true,
|
||||
isCard: null,
|
||||
isSCSI: null,
|
||||
isUSB: null,
|
||||
isUAS: null,
|
||||
},
|
||||
{
|
||||
enumerator: 'lsblk:pairs',
|
||||
busType: 'UNKNOWN',
|
||||
busVersion: null,
|
||||
device: '/dev/sda',
|
||||
devicePath: null,
|
||||
raw: '/dev/sda',
|
||||
description: '(/, [SWAP])',
|
||||
error: null,
|
||||
size: null,
|
||||
blockSize: 512,
|
||||
logicalBlockSize: 512,
|
||||
mountpoints: [
|
||||
{
|
||||
path: '/',
|
||||
label: undefined,
|
||||
},
|
||||
{
|
||||
path: '[SWAP]',
|
||||
label: undefined,
|
||||
},
|
||||
],
|
||||
isReadOnly: false,
|
||||
isSystem: true,
|
||||
isVirtual: null,
|
||||
isRemovable: false,
|
||||
isCard: null,
|
||||
isSCSI: null,
|
||||
isUSB: null,
|
||||
isUAS: null,
|
||||
},
|
||||
];
|
||||
|
||||
inspect(parsePairs(listData));
|
||||
|
||||
expect(devices).to.deep.equal(expected);
|
||||
});
|
||||
|
||||
it('can handle mountpoints on root devices', () => {
|
||||
const listData = require('./data/lsblk/no-children-mountpoints.json');
|
||||
const actual = transformJSON(listData);
|
||||
|
||||
const expected = [
|
||||
{
|
||||
enumerator: 'lsblk:json',
|
||||
busType: 'UNKNOWN',
|
||||
busVersion: null,
|
||||
device: '/dev/sda',
|
||||
devicePath: null,
|
||||
raw: '/dev/sda',
|
||||
description: '',
|
||||
error: null,
|
||||
size: null,
|
||||
blockSize: 512,
|
||||
logicalBlockSize: 512,
|
||||
mountpoints: [
|
||||
{
|
||||
path: '/media/jwentz/Temp',
|
||||
label: undefined,
|
||||
},
|
||||
],
|
||||
isReadOnly: false,
|
||||
isSystem: false,
|
||||
isVirtual: null,
|
||||
isRemovable: true,
|
||||
isCard: null,
|
||||
isSCSI: null,
|
||||
isUSB: null,
|
||||
isUAS: null,
|
||||
},
|
||||
{
|
||||
enumerator: 'lsblk:json',
|
||||
busType: 'UNKNOWN',
|
||||
busVersion: null,
|
||||
device: '/dev/nvme0n1',
|
||||
devicePath: null,
|
||||
raw: '/dev/nvme0n1',
|
||||
description: '([SWAP], /boot/efi, /)',
|
||||
error: null,
|
||||
size: null,
|
||||
blockSize: 512,
|
||||
logicalBlockSize: 512,
|
||||
mountpoints: [
|
||||
{
|
||||
path: '[SWAP]',
|
||||
label: undefined,
|
||||
},
|
||||
{
|
||||
path: '/boot/efi',
|
||||
label: undefined,
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
label: undefined,
|
||||
},
|
||||
],
|
||||
isReadOnly: false,
|
||||
isSystem: true,
|
||||
isVirtual: null,
|
||||
isRemovable: false,
|
||||
isCard: null,
|
||||
isSCSI: null,
|
||||
isUSB: null,
|
||||
isUAS: null,
|
||||
},
|
||||
];
|
||||
|
||||
inspect(actual);
|
||||
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
|
||||
it('can handle empty mountpoints in lsblk --pairs output', () => {
|
||||
const listData = readFileSync(
|
||||
join(__dirname, 'data', 'lsblk', 'ubuntu-14.04-3.txt'),
|
||||
'utf8',
|
||||
);
|
||||
const actual = parsePairs(listData);
|
||||
const expected = [
|
||||
{
|
||||
enumerator: 'lsblk:pairs',
|
||||
busType: 'UNKNOWN',
|
||||
busVersion: null,
|
||||
device: '/dev/sda',
|
||||
devicePath: null,
|
||||
raw: '/dev/sda',
|
||||
description: 'sda',
|
||||
error: null,
|
||||
size: null,
|
||||
blockSize: 512,
|
||||
logicalBlockSize: 512,
|
||||
mountpoints: [],
|
||||
isReadOnly: false,
|
||||
isSystem: true,
|
||||
isVirtual: null,
|
||||
isRemovable: false,
|
||||
isCard: null,
|
||||
isSCSI: null,
|
||||
isUSB: null,
|
||||
isUAS: null,
|
||||
},
|
||||
{
|
||||
enumerator: 'lsblk:pairs',
|
||||
busType: 'UNKNOWN',
|
||||
busVersion: null,
|
||||
device: '/dev/sdb',
|
||||
devicePath: null,
|
||||
raw: '/dev/sdb',
|
||||
description: 'sdb',
|
||||
error: null,
|
||||
size: null,
|
||||
blockSize: 512,
|
||||
logicalBlockSize: 512,
|
||||
mountpoints: [],
|
||||
isReadOnly: false,
|
||||
isSystem: false,
|
||||
isVirtual: null,
|
||||
isRemovable: true,
|
||||
isCard: null,
|
||||
isSCSI: null,
|
||||
isUSB: null,
|
||||
isUAS: null,
|
||||
},
|
||||
{
|
||||
enumerator: 'lsblk:pairs',
|
||||
busType: 'UNKNOWN',
|
||||
busVersion: null,
|
||||
device: '/dev/sdc',
|
||||
devicePath: null,
|
||||
raw: '/dev/sdc',
|
||||
description: 'sdc',
|
||||
error: null,
|
||||
size: null,
|
||||
blockSize: 512,
|
||||
logicalBlockSize: 512,
|
||||
mountpoints: [],
|
||||
isReadOnly: false,
|
||||
isSystem: false,
|
||||
isVirtual: null,
|
||||
isRemovable: true,
|
||||
isCard: null,
|
||||
isSCSI: null,
|
||||
isUSB: null,
|
||||
isUAS: null,
|
||||
},
|
||||
{
|
||||
enumerator: 'lsblk:pairs',
|
||||
busType: 'UNKNOWN',
|
||||
busVersion: null,
|
||||
device: '/dev/sdd',
|
||||
devicePath: null,
|
||||
raw: '/dev/sdd',
|
||||
description: '(/media/<username>/85CA-6700)',
|
||||
error: null,
|
||||
size: null,
|
||||
blockSize: 512,
|
||||
logicalBlockSize: 512,
|
||||
mountpoints: [
|
||||
{
|
||||
path: '/media/<username>/85CA-6700',
|
||||
label: undefined,
|
||||
},
|
||||
],
|
||||
isReadOnly: false,
|
||||
isSystem: false,
|
||||
isVirtual: null,
|
||||
isRemovable: true,
|
||||
isCard: null,
|
||||
isSCSI: null,
|
||||
isUSB: null,
|
||||
isUAS: null,
|
||||
},
|
||||
{
|
||||
enumerator: 'lsblk:pairs',
|
||||
busType: 'UNKNOWN',
|
||||
busVersion: null,
|
||||
device: '/dev/nvme0n1',
|
||||
devicePath: null,
|
||||
raw: '/dev/nvme0n1',
|
||||
description: '(/)',
|
||||
error: null,
|
||||
size: null,
|
||||
blockSize: 512,
|
||||
logicalBlockSize: 512,
|
||||
mountpoints: [
|
||||
{
|
||||
path: '/',
|
||||
label: undefined,
|
||||
},
|
||||
],
|
||||
isReadOnly: false,
|
||||
isSystem: true,
|
||||
isVirtual: null,
|
||||
isRemovable: false,
|
||||
isCard: null,
|
||||
isSCSI: null,
|
||||
isUSB: null,
|
||||
isUAS: null,
|
||||
},
|
||||
];
|
||||
|
||||
inspect(actual);
|
||||
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
|
||||
it('can handle mountpoints on root devices in --pairs output', () => {
|
||||
const listData = readFileSync(
|
||||
join(__dirname, 'data', 'lsblk', 'no-partition-table.txt'),
|
||||
'utf8',
|
||||
);
|
||||
const devices = parsePairs(listData);
|
||||
|
||||
const expected = [
|
||||
{
|
||||
blockSize: 512,
|
||||
busType: 'UNKNOWN',
|
||||
busVersion: null,
|
||||
description: '(/boot/efi, /boot)',
|
||||
device: '/dev/sda',
|
||||
devicePath: null,
|
||||
enumerator: 'lsblk:pairs',
|
||||
error: null,
|
||||
isCard: null,
|
||||
isReadOnly: false,
|
||||
isRemovable: false,
|
||||
isSCSI: null,
|
||||
isSystem: true,
|
||||
isUAS: null,
|
||||
isUSB: null,
|
||||
isVirtual: null,
|
||||
logicalBlockSize: 512,
|
||||
mountpoints: [
|
||||
{
|
||||
label: undefined,
|
||||
path: '/boot/efi',
|
||||
},
|
||||
{
|
||||
label: undefined,
|
||||
path: '/boot',
|
||||
},
|
||||
],
|
||||
raw: '/dev/sda',
|
||||
size: 240065183744,
|
||||
},
|
||||
{
|
||||
blockSize: 512,
|
||||
busType: 'UNKNOWN',
|
||||
busVersion: null,
|
||||
description: 'sdb',
|
||||
device: '/dev/sdb',
|
||||
devicePath: null,
|
||||
enumerator: 'lsblk:pairs',
|
||||
error: null,
|
||||
isCard: null,
|
||||
isReadOnly: false,
|
||||
isRemovable: true,
|
||||
isSCSI: null,
|
||||
isSystem: false,
|
||||
isUAS: null,
|
||||
isUSB: null,
|
||||
isVirtual: null,
|
||||
logicalBlockSize: 512,
|
||||
mountpoints: [],
|
||||
raw: '/dev/sdb',
|
||||
size: null,
|
||||
},
|
||||
{
|
||||
blockSize: 512,
|
||||
busType: 'UNKNOWN',
|
||||
busVersion: null,
|
||||
description: '(/run/media/DA2E4172/BUILD)',
|
||||
device: '/dev/sdc',
|
||||
devicePath: null,
|
||||
enumerator: 'lsblk:pairs',
|
||||
error: null,
|
||||
isCard: null,
|
||||
isReadOnly: false,
|
||||
isRemovable: true,
|
||||
isSCSI: null,
|
||||
isSystem: false,
|
||||
isUAS: null,
|
||||
isUSB: null,
|
||||
isVirtual: null,
|
||||
logicalBlockSize: 512,
|
||||
mountpoints: [
|
||||
{
|
||||
label: undefined,
|
||||
path: '/run/media/DA2E4172/BUILD',
|
||||
},
|
||||
],
|
||||
raw: '/dev/sdc',
|
||||
size: 31457280000,
|
||||
},
|
||||
];
|
||||
|
||||
inspect(parsePairs(listData));
|
||||
|
||||
expect(devices).to.deep.equal(expected);
|
||||
});
|
||||
});
|
||||
});
|
16
dependencies/drivelist/tsconfig.json
vendored
Normal file
16
dependencies/drivelist/tsconfig.json
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"outDir": "js",
|
||||
"sourceMap": true,
|
||||
"declaration": true,
|
||||
"target": "es6",
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true
|
||||
},
|
||||
"include": [
|
||||
"lib"
|
||||
]
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue