Skip to content

Commit

Permalink
fix: support for non-ASCII chars in drive names
Browse files Browse the repository at this point in the history
Fixes #34
  • Loading branch information
aleksey-hoffman committed Sep 1, 2021
1 parent 40adf4e commit 4b3dd1b
Show file tree
Hide file tree
Showing 3 changed files with 276 additions and 38 deletions.
2 changes: 1 addition & 1 deletion src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { Walk } from './utils/driveWalker.js'
import GlobalSearchWorker from 'worker-loader!./workers/globalSearchWorker.js'
import DirWatcherWorker from 'worker-loader!./workers/dirWatcherWorker.js'
import TimeUtils from './utils/timeUtils.js'
import getStorageDevices from './utils/storageInfo.js'
import {getStorageDevices} from './utils/storageInfo.js'
import idleJs from 'idle-js'
const electron = require('electron')
const PATH = require('path')
Expand Down
87 changes: 79 additions & 8 deletions src/utils/fsManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,25 +44,65 @@ async function initCliProcess () {
params.shell = '/bin/sh'
params.args = []
}

reusableCli.init(
params,
(spawnedCliProcess) => {
state.cliProcess = spawnedCliProcess
if (process.platform === 'win32') {
setUTF8encoding()
}
}
)
}

function getCommand (params) {
if (process.platform === 'win32') {
// Format path
if (params.path) {
params.path = params.path.replace(/\//g, '\\')
}
// Get command
if (params.command === 'sudo') {
if (params.adminPrompt === 'built-in') {
// return `echo -e "${params.sudoPassword}\n" | sudo -S`
return `echo ${params.sudoPassword} | sudo -S`
}
else if (params.adminPrompt === 'pkexec') {
return 'pkexec'
}
return '-Verb RunAs'
}
if (params.command === 'set-utf-8-encoding') {
return '[System.Console]::OutputEncoding = [System.Console]::InputEncoding = [System.Text.Encoding]::UTF8'
}
if (params.command === 'drive-info') {
return [
'get-ciminstance -ClassName Win32_LogicalDisk',
'| convertTo-csv | convertFrom-csv | convertTo-json'
].join(' ')
}
if (params.command === 'extra-drive-info') {
return `(Get-CimInstance Win32_Diskdrive -Filter "Partitions>0" | ForEach-Object {
$disk = Get-CimInstance
-ClassName MSFT_PhysicalDisk
-Namespace root\\Microsoft\\Windows\\Storage
-Filter "SerialNumber='$($_.SerialNumber.trim())'";
foreach ($partition in $_ | Get-CimAssociatedInstance -ResultClassName Win32_DiskPartition) {
foreach ($logicaldisk in $partition | Get-CimAssociatedInstance -ResultClassName Win32_LogicalDisk) {
[PSCustomObject]@{
Disk = $_.DeviceID;
DiskModel = $_.Model;
DiskSize = $_.Size;
HealthStatus = $disk.HealthStatus;
BusType = $disk.BusType;
DiskType = $_.MediaType;
MediaType = $disk.MediaType;
Partition = $partition.Name;
PartitionSize = $partition.Size;
VolumeName = $logicaldisk.VolumeName;
DriveLetter = $logicaldisk.DeviceID;
VolumeSize = $logicaldisk.Size;
FreeSpace = $logicaldisk.FreeSpace;
}
}
}
}) | convertTo-csv | convertFrom-csv | convertTo-json
`.replace(/\n/g, ' ')
}
// Note: all commands on win32 are executed with powershell.
// it doesn't have support for operators like &&.
Expand Down Expand Up @@ -235,6 +275,35 @@ function execCommand (params) {
})
}

/**
* @returns void
*/
async function setUTF8encoding () {
execCommand({
command: getCommand({command: 'set-utf-8-encoding'})
})
}

/**
* @returns {array}
*/
async function getDriveInfo () {
let data = await execCommand({
command: getCommand({command: 'drive-info'})
})
return JSON.parse(data.join(''))
}

/**
* @returns {array}
*/
async function getExtraDriveInfo () {
let data = await execCommand({
command: getCommand({command: 'extra-drive-info'})
})
return JSON.parse(data.join(''))
}

/**
* @param {string} params.path
* @returns void
Expand Down Expand Up @@ -522,6 +591,8 @@ function changeMode (params) {
export {
initCliProcess,
changeMode,
getDriveInfo,
getExtraDriveInfo,
resetPermissions,
getDirItemOwner,
isDirItemImmutable,
Expand Down
225 changes: 196 additions & 29 deletions src/utils/storageInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,189 @@
// Copyright © 2021 - present Aleksey Hoffman. All rights reserved.

// TODO: (?) Move to the main process
// TODO: If systeminformation.fsSize() ever becomes faster,
// replace "node-diskuage" with the "sysInfo.fsSize()""
// and then remove "app.allowRendererProcessReuse = false" from the main.
// Currently it's 1000 times slower (0.1 ms vs 100 ms)

import utils from './utils'
import * as fsManager from './fsManager.js'

const PATH = require('path')
const sysInfo = require('systeminformation')
const diskusage = require('diskusage')
const PATH = require('path')

export default async function getStorageDevices () {
let drives = await sysInfo.blockDevices()
drives = formatDrivesData(drives)
drives = processDrivesData(drives)
drives = await addPropertiesToDrivesData(drives)
return drives
let state = {
extraDeviceData: [],
driveList: [],
previousDriveList: [],
driveTypes: {
'1': '',
'2': 'removable',
'3': 'fixed',
'4': 'network',
'5': 'cd',
'6': 'RAM'
},
driveMemoryTypes: {
'1': '',
'3': 'HDD',
'4': 'SSD',
'5': 'SCM'
}
}

export async function getStorageDevices () {
try {
let blockDevices = await getBlockDevices()
let storageDevices = [
...blockDevices,
]
state.previousDriveList = [...state.driveList]
state.driveList = blockDevices
handleDriveListChange()
return storageDevices
}
catch (error) {
console.error(error)
return []
}
}

function handleDriveListChange () {
let driveListChanged = state.previousDriveList.length !== state.driveList.length
if (driveListChanged) {
fetchBlockDevicesExtraData()
}
}

export async function fetchBlockDevicesExtraData () {
try {
getBlockDevicesExtraData()
.then((data) => {
const extraDeviceDataFormatted = data
.map(drive => {
drive.MediaType = state.driveMemoryTypes[drive.MediaType]
return drive
})
state.extraDeviceData = extraDeviceDataFormatted
})
}
catch (error) {}
}

export async function getBlockDevicesExtraData () {
return new Promise((resolve, reject) => {
if (process.platform === 'win32') {
fsManager.getExtraDriveInfo().then((data) => resolve(data))
}
else {
return []
}
})
}

async function getBlockDevicesData () {
try {
if (process.platform === 'win32') {
return await fsManager.getDriveInfo()
}
else if (process.platform === 'linux') {
return await sysInfo.blockDevices()
}
else if (process.platform === 'darwin') {
return await sysInfo.blockDevices()
}
}
catch (error) {
return []
}
}

async function getBlockDevices () {
let blockDevices = await getBlockDevicesData()
blockDevices = formatBlockDevicesProperties(blockDevices)
blockDevices = formatDrivesData(blockDevices)
blockDevices = processDrivesData(blockDevices)
blockDevices = await addPropertiesToDrivesData(blockDevices)
return blockDevices
}

function formatBlockDevicesProperties (blockDevices) {
if (process.platform === 'win32') {
blockDevices.forEach(device => {
device.mount = device.Caption
device.path = device.Caption
device.name = device.Caption
device.label = device.ProviderName ? device.ProviderName : device.VolumeName
device.fsType = device.FileSystem
device.type = getDriveType(device)
device.memoryType = getDriveMemoryType(device)
})
}
else if (process.platform === 'linux') {
blockDevices.forEach(device => {
device.type = getDriveType(device)
})
}
else if (process.platform === 'darwin') {
blockDevices.forEach(device => {
device.type = getDriveType(device)
})
}
return blockDevices
}

function getDriveType (device) {
if (process.platform === 'win32') {
return state.driveTypes[device.driveType] || ''
}
else if (process.platform === 'linux') {
if (device.removable && device.type === 'rom') {
return 'rom'
}
else {
return device.removable ? 'removable' : device.type
}
}
else if (process.platform === 'darwin') {
if (device.removable && device.type === 'rom') {
return 'rom'
}
else {
return device.removable ? 'removable' : device.type
}
}
else {
return ''
}
}

function getDriveMemoryType (device) {
if (process.platform === 'win32') {
let extraData = state.extraDeviceData.find(drive => drive.DriveLetter === device.Caption)
if (extraData) {
return extraData.MediaType
}
else {
return ''
}
}
else {
return ''
}
}

async function addPropertiesToDrivesData (drives) {
for (let index = 0; index < drives.length; index++) {
const drive = drives[index]

let size
let percentUsed
let size = {available: 0, free: 0, total: 0}
let percentUsed = 0

try {
size = await diskusage.check(drive.mount)
percentUsed = Math.floor((1 - (size.free / size.total)) * 100)
}
catch (e) {
// Drive couldn't be checked by diskusage, likely because it isn't readable
size = { available: 0, free: 0, total: 0 }
percentUsed = 0
percentUsed = Math.floor((1 - (size.free / size.total)) * 100) || 0
}
catch (error) {}

drive.size = size
drive.path = drive.mount
drive.percentUsed = percentUsed
drive.titleSummary = getDriveTitleSummary(drive)
drive.infoSummary = getDriveInfoSummary(drive, percentUsed)
Expand All @@ -48,17 +195,26 @@ async function addPropertiesToDrivesData (drives) {
}

function processDrivesData (drives) {
if (process.platform === 'linux') {
// Filter out unneeded mount points
if (process.platform === 'win32') {
drives = drives.filter(drive => {
const allowedTypes = ['part', 'rom'].includes(drive.type)
return drive.fsType !== ''
})
}
else if (process.platform === 'linux') {
drives = drives.filter(drive => {
const incudesAllowedTypes = ['disk', 'part', 'rom', 'removable'].includes(drive.type)
const includesDisallowedMounts = ['/boot/efi/'].includes(drive.mount)
const isSwap = drive.fsType === 'swap'
return allowedTypes && !isSwap
return drive.fsType !== '' && incudesAllowedTypes && !includesDisallowedMounts && !isSwap
})
}
else if (process.platform === 'win32') {
// Filter out drives with empty 'fsType' property (likely RAW drives or CD/DVD Drives)
drives = drives.filter(drive => drive.fsType !== '')
else if (process.platform === 'darwin') {
drives = drives.filter(drive => {
const disallowedMountEntryPoints = ['/System']
const isRootEntryPoint = drive.mount === '/'
const isDisallowedEntryPoint = disallowedMountEntryPoints.some(entryPoint => drive.mount.startsWith(entryPoint))
return drive.fsType !== '' && !isDisallowedEntryPoint && !isRootEntryPoint
})
}
return drives
}
Expand All @@ -73,10 +229,21 @@ function formatDrivesData (drives) {

function getDriveTitleSummary (drive) {
if (process.platform === 'win32') {
return `${drive.mount.replace(':/', ':')}${drive.label}`
let mount = drive.mount.replace(':/', ':')
if (drive.memoryType) {
return `${mount}${drive.label}${drive.memoryType}`
}
else {
return `${mount}${drive.label}`
}
}
else {
return `${drive.name}${drive.mount}`
if (drive.label) {
return `${drive.label}`
}
else {
return `${drive.mount}`
}
}
}

Expand Down

0 comments on commit 4b3dd1b

Please sign in to comment.