forked from linuxdeepin/dde-daemon
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lsblk_disk.go
151 lines (127 loc) · 2.84 KB
/
lsblk_disk.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package systeminfo
import (
"fmt"
"crypto/sha256"
"encoding/json"
"os/exec"
"strconv"
"strings"
)
const (
uuidDelim = "+"
)
// Disk store disk info
type Disk struct {
Name string
Model string
Serial string // if empty, use children uuid's sha256 replace
Vendor string
Size int64 // byte
RootMounted bool
}
// DiskList multi disk
type DiskList []*Disk
type lsblkDevice struct {
Name string `json:"name"`
Serial string `json:"serial"`
Type string `json:"type"`
Vendor string `json:"vendor"`
Model string `json:"model"`
UUID string `json:"uuid"`
MountPoint string `json:"mountpoint"`
Size interface{} `json:"size"`
Children lsblkDeviceList `json:"children"`
}
type lsblkDeviceList []*lsblkDevice
type lsblkOutput struct {
Blockdevices lsblkDeviceList `json:"blockdevices"`
}
func GetDiskList() (DiskList, error) {
out, err := execLsblk()
if err != nil {
return nil, err
}
return newDiskListFromOutput(out)
}
func (list DiskList) GetRoot() *Disk {
for _, d := range list {
if d.RootMounted {
return d
}
}
return nil
}
func newDiskListFromOutput(out []byte) (DiskList, error) {
lsblk, err := parseLsblkOutput(out)
if err != nil {
return nil, err
}
var disks DiskList
for _, info := range lsblk.Blockdevices {
disks = append(disks, newDiskFromDevice(info))
}
return disks, nil
}
func newDiskFromDevice(dev *lsblkDevice) *Disk {
var info = Disk{
Name: dev.Name,
Model: dev.Model,
Serial: dev.Serial,
Vendor: dev.Vendor,
RootMounted: dev.RootMounted(),
}
if v, ok := dev.Size.(string); ok {
info.Size, _ = strconv.ParseInt(v, 10, 64)
} else if v, ok := dev.Size.(float64); ok {
info.Size = int64(v)
}
if len(info.Serial) == 0 {
// using children uuid list's sha256 as serial
info.Serial = genSerialByUUIDList(dev.GetUUIDList())
}
return &info
}
func genSerialByUUIDList(list []string) string {
if len(list) == 0 {
return ""
}
str := strings.Join(list, uuidDelim)
return sha256Sum([]byte(str))
}
func (dev *lsblkDevice) RootMounted() bool {
for _, child := range dev.Children {
if child.MountPoint == "/" {
return true
}
}
return false
}
func (dev *lsblkDevice) GetUUIDList() []string {
var list []string
for _, child := range dev.Children {
if len(child.UUID) == 0 {
continue
}
list = append(list, child.UUID)
}
return list
}
// SHA256Sum sum data by sha256
func sha256Sum(data []byte) string {
if len(data) == 0 {
return ""
}
return fmt.Sprintf("%x", sha256.Sum256(data))
}
func parseLsblkOutput(out []byte) (*lsblkOutput, error) {
var info lsblkOutput
err := json.Unmarshal(out, &info)
if err != nil {
return nil, err
}
return &info, nil
}
func execLsblk() ([]byte, error) {
lsblk := "lsblk -J -bno NAME,SERIAL,TYPE,SIZE,VENDOR,MODEL,MOUNTPOINT,UUID"
return exec.Command("/bin/sh", "-c", lsblk).CombinedOutput()
}