From 72476915da7d82fced012b335b9c904d6a3977a4 Mon Sep 17 00:00:00 2001 From: teeoo Date: Mon, 15 May 2023 10:49:43 +0800 Subject: [PATCH 1/3] :sparkles: feature: realize mac \& win to obtain the disk model --- disk/disk.go | 4 ++++ disk/disk_darwin.go | 46 +++++++++++++++++++++++++++++++++++++++++++ disk/disk_linux.go | 4 ++++ disk/disk_test.go | 47 ++++++++++++++++++++++++++++++++++++++++++++ disk/disk_windows.go | 27 +++++++++++++++++++++++++ 5 files changed, 128 insertions(+) diff --git a/disk/disk.go b/disk/disk.go index 0d4b25345..992f2f692 100644 --- a/disk/disk.go +++ b/disk/disk.go @@ -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) +} \ No newline at end of file diff --git a/disk/disk_darwin.go b/disk/disk_darwin.go index 933cb0454..4bc9c63dc 100644 --- a/disk/disk_darwin.go +++ b/disk/disk_darwin.go @@ -5,6 +5,9 @@ package disk import ( "context" + "errors" + "os/exec" + "strings" "github.com/shirou/gopsutil/v3/internal/common" "golang.org/x/sys/unix" @@ -91,3 +94,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 +} diff --git a/disk/disk_linux.go b/disk/disk_linux.go index 14712f9ea..a2b88c9a3 100644 --- a/disk/disk_linux.go +++ b/disk/disk_linux.go @@ -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 +} diff --git a/disk/disk_test.go b/disk/disk_test.go index 5adae5ca3..ca8eef1cd 100644 --- a/disk/disk_test.go +++ b/disk/disk_test.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "runtime" + "strings" "sync" "testing" @@ -130,3 +131,49 @@ 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 "windows": + diskName = "Fixed" + 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 + } + if len(diskMap) == 0 { + t.Errorf("no disk found") + 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) + } + } +} diff --git a/disk/disk_windows.go b/disk/disk_windows.go index 8a1a28d69..34f6bcacf 100644 --- a/disk/disk_windows.go +++ b/disk/disk_windows.go @@ -235,3 +235,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 +} From 5fdaa7a0bcd79d529380ec69e1dadc39221bd50d Mon Sep 17 00:00:00 2001 From: teeoo Date: Tue, 30 May 2023 10:07:19 +0800 Subject: [PATCH 2/3] :bug: fix: lint --- disk/disk_darwin.go | 5 ++--- disk/disk_freebsd.go | 4 ++++ disk/disk_test.go | 6 ------ 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/disk/disk_darwin.go b/disk/disk_darwin.go index 4bc9c63dc..7e875d0e4 100644 --- a/disk/disk_darwin.go +++ b/disk/disk_darwin.go @@ -6,11 +6,10 @@ package disk import ( "context" "errors" - "os/exec" - "strings" - "github.com/shirou/gopsutil/v3/internal/common" "golang.org/x/sys/unix" + "os/exec" + "strings" ) // PartitionsWithContext returns disk partition. diff --git a/disk/disk_freebsd.go b/disk/disk_freebsd.go index 9b53106c2..e36423c06 100644 --- a/disk/disk_freebsd.go +++ b/disk/disk_freebsd.go @@ -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 +} \ No newline at end of file diff --git a/disk/disk_test.go b/disk/disk_test.go index ca8eef1cd..cd1ce0978 100644 --- a/disk/disk_test.go +++ b/disk/disk_test.go @@ -147,8 +147,6 @@ func TestModel(t *testing.T) { } var diskName string switch runtime.GOOS { - case "windows": - diskName = "Fixed" case "darwin": diskName = "Macintosh HD" default: @@ -160,10 +158,6 @@ func TestModel(t *testing.T) { t.Errorf("failed to get disk model: %v", err) return } - if len(diskMap) == 0 { - t.Errorf("no disk found") - return - } for name, model := range diskMap { if !strings.Contains(name, diskName) { t.Errorf("expected disk name containing '%s', got '%s'", diskName, name) From 4010867514247fcb887aab1a6067e07aebb65198 Mon Sep 17 00:00:00 2001 From: Teeoo Date: Tue, 30 May 2023 10:51:43 +0800 Subject: [PATCH 3/3] :bug: fix: The package import under the win platform is incorrect --- disk/disk_windows.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/disk/disk_windows.go b/disk/disk_windows.go index 34f6bcacf..c6724d0b4 100644 --- a/disk/disk_windows.go +++ b/disk/disk_windows.go @@ -6,7 +6,10 @@ package disk import ( "bytes" "context" + "errors" "fmt" + "os/exec" + "strings" "sync" "syscall" "unsafe"