package smart import ( "errors" "fmt" "os" "path/filepath" "strings" "github.com/anatol/smart.go" ) // SMART data structure for SATA disks type SATAAttrData struct { Id uint8 Name string Type int RawVal uint64 Current uint8 Worst uint8 } type SMARTData struct { ModelNumber string SerialNumber string Size uint64 Temperature int /* NVME specific fields */ NameSpaceUtilizations []uint64 PowerOnHours uint64 PowerCycles uint64 UnsafeShutdowns uint64 MediaErrors uint64 /* SATA specific fields */ SATAAttrs []*SATAAttrData } // Get SMART data of a particular disk / device func GetSMARTData(disk string) (*SMARTData, error) { if !strings.HasPrefix(disk, "/dev/") { disk = filepath.Join("/dev", disk) } //Check if the disk exists if _, err := os.Stat(disk); os.IsNotExist(err) { return nil, fmt.Errorf("disk %s does not exist", disk) } // Check if the disk is NVMe or SATA isNVMe := strings.HasPrefix(disk, "/dev/nvme") isSATA := strings.HasPrefix(disk, "/dev/sd") // If the disk is not NVMe or SATA, return an error if !isNVMe && !isSATA { return nil, fmt.Errorf("disk %s is not an NVMe or SATA disk", disk) } if isNVMe { return getNVMESMART(disk) } else if isSATA { return getSATASMART(disk) } return nil, errors.New("unsupported disk type") } // Check if the path is the disk path instead of partition path func IsRootDisk(deviceFilePath string) bool { deviceFilename := filepath.Base(deviceFilePath) if !(strings.HasPrefix(deviceFilename, "sd") || strings.HasPrefix(deviceFilename, "nvme")) { return false } if strings.HasPrefix(deviceFilename, "sd") && len(deviceFilename) > 3 { return false } if strings.HasPrefix(deviceFilename, "nvme") && len(deviceFilename) > 5 { return false } return true } // Check if this SMART implementation supports the disk type func IsDiskSupportedType(disk string) bool { return IsNVMeDevice(disk) || IsSATADevice(disk) } // Check if the disk is a SATA device func IsSATADevice(disk string) bool { if !strings.HasPrefix(disk, "/dev/") { disk = filepath.Join("/dev", disk) } _, err := smart.OpenSata(disk) return err == nil } // Check if the disk is a NVMe device func IsNVMeDevice(disk string) bool { if !strings.HasPrefix(disk, "/dev/") { disk = filepath.Join("/dev", disk) } _, err := smart.OpenNVMe(disk) return err == nil }