Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ feature: realize mac \& win to obtain the disk model #1465

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions disk/disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,7 @@ func SerialNumber(name string) (string, error) {
func Label(name string) (string, error) {
return LabelWithContext(context.Background(), name)
}

func Model(name string) (map[string]string, error) {
return ModelWithContext(context.Background(), name)
}
47 changes: 46 additions & 1 deletion disk/disk_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ package disk

import (
"context"

"errors"
"github.com/shirou/gopsutil/v3/internal/common"
"golang.org/x/sys/unix"
"os/exec"
"strings"
)

// PartitionsWithContext returns disk partition.
Expand Down Expand Up @@ -91,3 +93,46 @@ func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
func LabelWithContext(ctx context.Context, name string) (string, error) {
return "", common.ErrNotImplementedError
}

func ModelWithContext(ctx context.Context, name string) (map[string]string, error) {
out, err := exec.Command("diskutil", "list").Output()
if err != nil {
return nil, errors.New("failed to execute 'diskutil list' command: " + err.Error())
}
outStr := string(out)
lines := strings.Split(outStr, "\n")
diskMap := make(map[string]string)
for _, line := range lines {
if strings.HasPrefix(line, "/dev/") {
fields := strings.Fields(line)
if len(fields) >= 1 {
partitionPath := fields[0]
if name != "" && !strings.Contains(partitionPath, name) {
continue
}
infoOut, err := exec.Command("diskutil", "info", partitionPath).Output()
if err != nil {
return nil, errors.New("failed to execute 'diskutil info' command: " + err.Error())
}
infoOutStr := string(infoOut)
infoLines := strings.Split(infoOutStr, "\n")
var diskName, model string
for _, infoLine := range infoLines {
if strings.HasPrefix(infoLine, " Device Node:") {
diskName = strings.TrimSpace(strings.TrimPrefix(infoLine, " Device Node:"))
}
if strings.HasPrefix(infoLine, " Device / Media Name:") {
model = strings.TrimSpace(strings.TrimPrefix(infoLine, " Device / Media Name:"))
}
}
if diskName != "" && model != "" {
diskMap[diskName] = model
if name != "" {
return diskMap, nil
}
}
}
}
}
return diskMap, nil
}
4 changes: 4 additions & 0 deletions disk/disk_freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,7 @@ func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
func LabelWithContext(ctx context.Context, name string) (string, error) {
return "", common.ErrNotImplementedError
}

func ModelWithContext(ctx context.Context, name string) (map[string]string, error) {
return nil, common.ErrNotImplementedError
}
4 changes: 4 additions & 0 deletions disk/disk_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,3 +537,7 @@ func getFsType(stat unix.Statfs_t) string {
}
return ret
}

func ModelWithContext(ctx context.Context, name string) (map[string]string, error) {
return nil, common.ErrNotImplementedError
}
41 changes: 41 additions & 0 deletions disk/disk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"runtime"
"strings"
"sync"
"testing"

Expand Down Expand Up @@ -130,3 +131,43 @@ func TestDiskIOCountersStat_String(t *testing.T) {
t.Errorf("DiskUsageStat string is invalid: %v", v)
}
}

func TestModel(t *testing.T) {
diskMap, err := Model("")
if err != nil {
t.Errorf("failed to get disk models: %v", err)
return
}
if len(diskMap) == 0 {
t.Errorf("no disk found")
return
}
for name, model := range diskMap {
t.Logf("%s: %s", name, model)
}
var diskName string
switch runtime.GOOS {
case "darwin":
diskName = "Macintosh HD"
default:
diskName = ""
}
if diskName != "" {
diskMap, err = Model(diskName)
if err != nil {
t.Errorf("failed to get disk model: %v", err)
return
}
for name, model := range diskMap {
if !strings.Contains(name, diskName) {
t.Errorf("expected disk name containing '%s', got '%s'", diskName, name)
return
}
if model == "" {
t.Errorf("expected non-empty disk model, got empty string")
return
}
t.Logf("%s: %s", name, model)
}
}
}
30 changes: 30 additions & 0 deletions disk/disk_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ package disk
import (
"bytes"
"context"
"errors"
"fmt"
"os/exec"
"strings"
"sync"
"syscall"
"unsafe"
Expand Down Expand Up @@ -235,3 +238,30 @@ func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
func LabelWithContext(ctx context.Context, name string) (string, error) {
return "", common.ErrNotImplementedError
}

func ModelWithContext(ctx context.Context, name string) (map[string]string, error) {
out, err := exec.Command("wmic", "diskdrive", "get", "model,name").Output()
if err != nil {
return nil, errors.New("failed to execute 'wmic diskdrive' command: " + err.Error())
}
outStr := string(out)
lines := strings.Split(outStr, "\r\n")
diskMap := make(map[string]string)
for _, line := range lines {
if strings.Contains(line, "Model") && strings.Contains(line, "Name") {
fields := strings.Fields(line)
if len(fields) >= 3 {
diskName := strings.Join(fields[2:], " ")
model := fields[1]
if name != "" && !strings.Contains(diskName, name) {
continue
}
diskMap[diskName] = model
if name != "" {
return diskMap, nil
}
}
}
}
return diskMap, nil
}