233 lines
7.5 KiB
Go
233 lines
7.5 KiB
Go
// Use and distribution licensed under the Apache license version 2.
|
|
//
|
|
// See the COPYING file in the root project directory for full text.
|
|
//
|
|
|
|
package ghw
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/StackExchange/wmi"
|
|
)
|
|
|
|
const wqlDiskDrive = "SELECT Caption, CreationClassName, DefaultBlockSize, Description, DeviceID, Index, InterfaceType, Manufacturer, MediaType, Model, Name, Partitions, SerialNumber, Size, TotalCylinders, TotalHeads, TotalSectors, TotalTracks, TracksPerCylinder FROM Win32_DiskDrive"
|
|
|
|
type win32DiskDrive struct {
|
|
Caption *string
|
|
CreationClassName *string
|
|
DefaultBlockSize *uint64
|
|
Description *string
|
|
DeviceID *string
|
|
Index *uint32 // Used to link with partition
|
|
InterfaceType *string
|
|
Manufacturer *string
|
|
MediaType *string
|
|
Model *string
|
|
Name *string
|
|
Partitions *int32
|
|
SerialNumber *string
|
|
Size *uint64
|
|
TotalCylinders *int64
|
|
TotalHeads *int32
|
|
TotalSectors *int64
|
|
TotalTracks *int64
|
|
TracksPerCylinder *int32
|
|
}
|
|
|
|
const wqlDiskPartition = "SELECT Access, BlockSize, Caption, CreationClassName, Description, DeviceID, DiskIndex, Index, Name, Size, SystemName, Type FROM Win32_DiskPartition"
|
|
|
|
type win32DiskPartition struct {
|
|
Access *uint16
|
|
BlockSize *uint64
|
|
Caption *string
|
|
CreationClassName *string
|
|
Description *string
|
|
DeviceID *string
|
|
DiskIndex *uint32 // Used to link with Disk Drive
|
|
Index *uint32
|
|
Name *string
|
|
Size *int64
|
|
SystemName *string
|
|
Type *string
|
|
}
|
|
|
|
const wqlLogicalDiskToPartition = "SELECT Antecedent, Dependent FROM Win32_LogicalDiskToPartition"
|
|
|
|
type win32LogicalDiskToPartition struct {
|
|
Antecedent *string
|
|
Dependent *string
|
|
}
|
|
|
|
const wqlLogicalDisk = "SELECT Caption, CreationClassName, Description, DeviceID, FileSystem, FreeSpace, Name, Size, SystemName FROM Win32_LogicalDisk"
|
|
|
|
type win32LogicalDisk struct {
|
|
Caption *string
|
|
CreationClassName *string
|
|
Description *string
|
|
DeviceID *string
|
|
FileSystem *string
|
|
FreeSpace *uint64
|
|
Name *string
|
|
Size *uint64
|
|
SystemName *string
|
|
}
|
|
|
|
func (ctx *context) blockFillInfo(info *BlockInfo) error {
|
|
win32DiskDriveDescriptions, err := getDiskDrives()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
win32DiskPartitionDescriptions, err := getDiskPartitions()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
win32LogicalDiskToPartitionDescriptions, err := getLogicalDisksToPartitions()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
win32LogicalDiskDescriptions, err := getLogicalDisks()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Converting into standard structures
|
|
disks := make([]*Disk, 0)
|
|
for _, diskdrive := range win32DiskDriveDescriptions {
|
|
disk := &Disk{
|
|
Name: strings.TrimSpace(*diskdrive.DeviceID),
|
|
SizeBytes: *diskdrive.Size,
|
|
PhysicalBlockSizeBytes: *diskdrive.DefaultBlockSize,
|
|
DriveType: toDriveType(*diskdrive.MediaType, *diskdrive.Caption),
|
|
StorageController: toStorageController(*diskdrive.InterfaceType),
|
|
BusType: toBusType(*diskdrive.InterfaceType),
|
|
BusPath: UNKNOWN, // TODO: add information
|
|
NUMANodeID: -1,
|
|
Vendor: strings.TrimSpace(*diskdrive.Manufacturer),
|
|
Model: strings.TrimSpace(*diskdrive.Caption),
|
|
SerialNumber: strings.TrimSpace(*diskdrive.SerialNumber),
|
|
WWN: UNKNOWN, // TODO: add information
|
|
Partitions: make([]*Partition, 0),
|
|
}
|
|
for _, diskpartition := range win32DiskPartitionDescriptions {
|
|
// Finding disk partition linked to current disk drive
|
|
if diskdrive.Index == diskpartition.DiskIndex {
|
|
disk.PhysicalBlockSizeBytes = *diskpartition.BlockSize
|
|
// Finding logical partition linked to current disk partition
|
|
for _, logicaldisk := range win32LogicalDiskDescriptions {
|
|
for _, logicaldisktodiskpartition := range win32LogicalDiskToPartitionDescriptions {
|
|
var desiredAntecedent = "\\\\" + *diskpartition.SystemName + "\\root\\cimv2:" + *diskpartition.CreationClassName + ".DeviceID=\"" + *diskpartition.DeviceID + "\""
|
|
var desiredDependent = "\\\\" + *logicaldisk.SystemName + "\\root\\cimv2:" + *logicaldisk.CreationClassName + ".DeviceID=\"" + *logicaldisk.DeviceID + "\""
|
|
if *logicaldisktodiskpartition.Antecedent == desiredAntecedent && *logicaldisktodiskpartition.Dependent == desiredDependent {
|
|
// Appending Partition
|
|
p := &Partition{
|
|
Name: strings.TrimSpace(*logicaldisk.Caption),
|
|
Label: strings.TrimSpace(*logicaldisk.Caption),
|
|
SizeBytes: *logicaldisk.Size,
|
|
MountPoint: *logicaldisk.DeviceID,
|
|
Type: *diskpartition.Type,
|
|
IsReadOnly: toReadOnly(*diskpartition.Access),
|
|
}
|
|
disk.Partitions = append(disk.Partitions, p)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
disks = append(disks, disk)
|
|
}
|
|
|
|
info.Disks = disks
|
|
var tpb uint64
|
|
for _, d := range info.Disks {
|
|
tpb += d.SizeBytes
|
|
}
|
|
info.TotalPhysicalBytes = tpb
|
|
return nil
|
|
}
|
|
|
|
func getDiskDrives() ([]win32DiskDrive, error) {
|
|
// Getting disks drives data from WMI
|
|
var win3232DiskDriveDescriptions []win32DiskDrive
|
|
if err := wmi.Query(wqlDiskDrive, &win3232DiskDriveDescriptions); err != nil {
|
|
return nil, err
|
|
}
|
|
return win3232DiskDriveDescriptions, nil
|
|
}
|
|
|
|
func getDiskPartitions() ([]win32DiskPartition, error) {
|
|
// Getting disk partitions from WMI
|
|
var win32DiskPartitionDescriptions []win32DiskPartition
|
|
if err := wmi.Query(wqlDiskPartition, &win32DiskPartitionDescriptions); err != nil {
|
|
return nil, err
|
|
}
|
|
return win32DiskPartitionDescriptions, nil
|
|
}
|
|
|
|
func getLogicalDisksToPartitions() ([]win32LogicalDiskToPartition, error) {
|
|
// Getting links between logical disks and partitions from WMI
|
|
var win32LogicalDiskToPartitionDescriptions []win32LogicalDiskToPartition
|
|
if err := wmi.Query(wqlLogicalDiskToPartition, &win32LogicalDiskToPartitionDescriptions); err != nil {
|
|
return nil, err
|
|
}
|
|
return win32LogicalDiskToPartitionDescriptions, nil
|
|
}
|
|
|
|
func getLogicalDisks() ([]win32LogicalDisk, error) {
|
|
// Getting logical disks from WMI
|
|
var win32LogicalDiskDescriptions []win32LogicalDisk
|
|
if err := wmi.Query(wqlLogicalDisk, &win32LogicalDiskDescriptions); err != nil {
|
|
return nil, err
|
|
}
|
|
return win32LogicalDiskDescriptions, nil
|
|
}
|
|
|
|
func toDriveType(mediaType string, caption string) DriveType {
|
|
mediaType = strings.ToLower(mediaType)
|
|
caption = strings.ToLower(caption)
|
|
if strings.Contains(mediaType, "fixed") || strings.Contains(mediaType, "ssd") || strings.Contains(caption, "ssd") {
|
|
return DRIVE_TYPE_SSD
|
|
} else if strings.ContainsAny(mediaType, "hdd") {
|
|
return DRIVE_TYPE_HDD
|
|
}
|
|
return DRIVE_TYPE_UNKNOWN
|
|
}
|
|
|
|
// TODO: improve
|
|
func toStorageController(interfaceType string) StorageController {
|
|
var storageController StorageController
|
|
switch interfaceType {
|
|
case "SCSI":
|
|
storageController = STORAGE_CONTROLLER_SCSI
|
|
case "IDE":
|
|
storageController = STORAGE_CONTROLLER_IDE
|
|
default:
|
|
storageController = STORAGE_CONTROLLER_UNKNOWN
|
|
}
|
|
return storageController
|
|
}
|
|
|
|
// TODO: improve
|
|
func toBusType(interfaceType string) BusType {
|
|
var busType BusType
|
|
switch interfaceType {
|
|
case "SCSI":
|
|
busType = BUS_TYPE_SCSI
|
|
case "IDE":
|
|
busType = BUS_TYPE_IDE
|
|
default:
|
|
busType = BUS_TYPE_UNKNOWN
|
|
}
|
|
return busType
|
|
}
|
|
|
|
// TODO: improve
|
|
func toReadOnly(access uint16) bool {
|
|
// See Access property from: https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-diskpartition
|
|
return access == 0x1
|
|
}
|