Skip to content

Commit 22b4c5c

Browse files
committed
Fix disk manager display
1 parent 0d4461c commit 22b4c5c

20 files changed

Lines changed: 100 additions & 36 deletions

File tree

internal/graph/storage_blockdev.go

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,61 @@ func readSysRotational(devName string) (bool, bool) {
3232
return s == "1", true
3333
}
3434

35+
func readSysRemovable(devName string) (bool, bool) {
36+
data, err := os.ReadFile("/sys/class/block/" + devName + "/removable")
37+
if err != nil {
38+
return false, false
39+
}
40+
s := strings.TrimSpace(string(data))
41+
return s == "1", true
42+
}
43+
44+
func sysDevicePathContains(devName string, needle string) bool {
45+
devName = strings.TrimSpace(devName)
46+
if devName == "" {
47+
return false
48+
}
49+
// /sys/class/block/<dev>/device is a symlink into the bus topology (usb, pci, mmc, ...)
50+
resolved, err := filepath.EvalSymlinks("/sys/class/block/" + devName + "/device")
51+
if err != nil || strings.TrimSpace(resolved) == "" {
52+
return false
53+
}
54+
return strings.Contains(resolved, needle)
55+
}
56+
3557
func baseBlockDeviceName(name string) string {
36-
if strings.HasPrefix(name, "nvme") || strings.HasPrefix(name, "mmcblk") || strings.HasPrefix(name, "md") {
58+
// Keep whole-disk names for these Linux devices (they naturally contain digits).
59+
// Examples: mmcblk1, md0, nvme0n1
60+
if strings.HasPrefix(name, "mmcblk") {
61+
// mmcblk<disk> (disk) or mmcblk<disk>p<part> (partition)
62+
if i := strings.LastIndex(name, "p"); i > 0 && allDigits(name[i+1:]) {
63+
return name[:i]
64+
}
65+
if allDigits(strings.TrimPrefix(name, "mmcblk")) {
66+
return name
67+
}
68+
}
69+
if strings.HasPrefix(name, "md") {
3770
if i := strings.LastIndex(name, "p"); i > 0 && allDigits(name[i+1:]) {
3871
return name[:i]
3972
}
73+
if allDigits(strings.TrimPrefix(name, "md")) {
74+
return name
75+
}
76+
}
77+
if strings.HasPrefix(name, "nvme") {
78+
// nvme<ctrl>n<ns> (disk) or nvme<ctrl>n<ns>p<part> (partition)
79+
if i := strings.LastIndex(name, "p"); i > 0 && allDigits(name[i+1:]) {
80+
return name[:i]
81+
}
82+
// If it has an 'n' suffix like nvme0n1, keep it intact.
83+
if i := strings.LastIndex(name, "n"); i > 0 {
84+
left := strings.TrimPrefix(name[:i], "nvme")
85+
right := name[i+1:]
86+
if allDigits(left) && allDigits(right) {
87+
return name
88+
}
89+
}
4090
}
4191
j := len(name) - 1
4292
for j >= 0 {
@@ -65,7 +115,7 @@ func allDigits(s string) bool {
65115
}
66116

67117
// getDriveType determines the high-level drive technology for the given source.
68-
// Returns one of: "Remote", "HDD", "SSD", or "Unknown".
118+
// Returns one of: "Remote", "HDD", "SSD", "USB", or "Unknown".
69119
func getDriveType(src string, isRemote bool) string {
70120
if isRemote {
71121
return "Remote"
@@ -113,16 +163,37 @@ func getDriveType(src string, isRemote bool) string {
113163
return "Unknown"
114164
}
115165

116-
// Regular block or partition device
166+
// Regular block or partition device.
167+
// Prefer parent device when name refers to a partition.
168+
parent := baseBlockDeviceName(name)
169+
if parent == "" {
170+
parent = name
171+
}
172+
173+
// If this is a removable USB mass-storage device, label as USB.
174+
// This avoids showing "HDD" for thumb drives where rotational reporting is unreliable.
175+
if sysDevicePathContains(parent, "/usb") {
176+
if rm, ok := readSysRemovable(parent); ok && rm {
177+
return "USB"
178+
}
179+
}
180+
181+
if rot, ok := readSysRotational(parent); ok {
182+
if rot {
183+
return "HDD"
184+
}
185+
return "SSD"
186+
}
187+
188+
// Try the leaf node as fallback.
117189
if rot, ok := readSysRotational(name); ok {
118190
if rot {
119191
return "HDD"
120192
}
121193
return "SSD"
122194
}
123195

124-
// Try parent device when name refers to a partition
125-
parent := baseBlockDeviceName(name)
196+
// Try parent device when name refers to a partition (already computed).
126197
if parent != name {
127198
if rot, ok := readSysRotational(parent); ok {
128199
if rot {

web/src/components/storage/DiskManagerModal.vue

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
<div class="browser-volumes dm-volumes">
5757
<div class="volumes">
5858
<VolumeCard v-for="v in diskVolumes(disk)" :key="v.id" :data="v"
59-
:title="getStorageVolumeTitle(v, t)" :drive-type="v.driveType"
59+
:title="getStorageVolumeTitle(v, t)" :drive-type="String(v.driveType || '').trim()"
6060
:used-percent="volumeUsedPercent(v)" :count="volumeCount(v)" :show-progress="true" />
6161
</div>
6262
</div>
@@ -208,9 +208,7 @@ function isSystemDisk(d: IStorageDisk) {
208208
const rootVol = (mounts.value || []).find((v) => !String(v?.path ?? '').trim() && String(v.mountPoint || '').trim() === '/')
209209
if (!rootVol) return false
210210
211-
const rootDiskID = String(rootVol.diskID || '').trim()
212-
if (!rootDiskID) return false
213-
return rootDiskID === String(d.id || '').trim()
211+
return String(rootVol.diskID || '').trim() === String(d.id || '').trim()
214212
}
215213
216214
function canFormatDisk(d: IStorageDisk) {

web/src/locales/bn.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ export default {
327327
efi_partition: 'EFI পার্টিশন',
328328
root_partition: 'সিস্টেম পার্টিশন',
329329
partition_x: 'পার্টিশন {n}',
330-
partition_count_x: 'মোট {n}টি পার্টিশন',
330+
volume_count_x: 'মোট {n}টি ভলিউম',
331331
unpartitioned_disk: 'এখনও সেট আপ করা হয়নি',
332332
whole_disk_volume: 'একটি একক ভলিউম হিসেবে ব্যবহৃত',
333333
show_technical_details: 'প্রযুক্তিগত বিস্তারিত দেখান',

web/src/locales/de.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ export default {
327327
efi_partition: 'EFI-Partition',
328328
root_partition: 'Systempartition',
329329
partition_x: 'Partition {n}',
330-
partition_count_x: 'Hat {n} Partition(en)',
330+
volume_count_x: 'Hat {n} Volume(s)',
331331
unpartitioned_disk: 'Noch nicht eingerichtet',
332332
whole_disk_volume: 'Als einzelnes Volume verwendet',
333333
show_technical_details: 'Technische Details anzeigen',

web/src/locales/en-US.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ export default {
334334
efi_partition: 'EFI partition',
335335
root_partition: 'System partition',
336336
partition_x: 'Partition {n}',
337-
partition_count_x: 'Has {n} partition(s)',
337+
volume_count_x: 'Has {n} volume(s)',
338338
unpartitioned_disk: 'Not set up yet',
339339
whole_disk_volume: 'Used as a single volume',
340340
show_technical_details: 'Show technical details',

web/src/locales/es.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ export default {
420420
efi_partition: 'Partición EFI',
421421
root_partition: 'Partición del sistema',
422422
partition_x: 'Partición {n}',
423-
partition_count_x: 'Tiene {n} partición(es)',
423+
volume_count_x: 'Tiene {n} volumen(es)',
424424
unpartitioned_disk: 'No configurado',
425425
whole_disk_volume: 'Usado como un solo volumen',
426426
show_technical_details: 'Mostrar detalles técnicos',

web/src/locales/fr.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ export default {
420420
efi_partition: 'Partition EFI',
421421
root_partition: 'Partition système',
422422
partition_x: 'Partition {n}',
423-
partition_count_x: '{n} partition(s)',
423+
volume_count_x: '{n} volume(s)',
424424
unpartitioned_disk: 'Non configuré',
425425
whole_disk_volume: 'Utilisé comme volume unique',
426426
show_technical_details: 'Afficher les détails techniques',

web/src/locales/hi.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ export default {
331331
efi_partition: 'EFI पार्टिशन',
332332
root_partition: 'सिस्टम पार्टिशन',
333333
partition_x: 'पार्टिशन {n}',
334-
partition_count_x: 'कुल {n} पार्टिशन',
334+
volume_count_x: 'कुल {n} वॉल्यूम',
335335
unpartitioned_disk: 'अभी सेट अप नहीं है',
336336
whole_disk_volume: 'एकल वॉल्यूम के रूप में उपयोग',
337337
show_technical_details: 'तकनीकी विवरण दिखाएँ',

web/src/locales/it.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ export default {
420420
efi_partition: 'Partizione EFI',
421421
root_partition: 'Partizione di sistema',
422422
partition_x: 'Partizione {n}',
423-
partition_count_x: '{n} partizione(i)',
423+
volume_count_x: '{n} volume(i)',
424424
unpartitioned_disk: 'Non configurato',
425425
whole_disk_volume: 'Usato come volume singolo',
426426
show_technical_details: 'Mostra dettagli tecnici',

web/src/locales/ja.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ export default {
420420
efi_partition: 'EFIパーティション',
421421
root_partition: 'システムパーティション',
422422
partition_x: 'パーティション {n}',
423-
partition_count_x: '{n}個のパーティション',
423+
volume_count_x: '{n}個のボリューム',
424424
unpartitioned_disk: '未設定',
425425
whole_disk_volume: '単一ボリュームとして使用',
426426
show_technical_details: '技術詳細を表示',

0 commit comments

Comments
 (0)