mirror of
https://github.com/shirou/gopsutil.git
synced 2025-04-26 13:48:59 +08:00
Merge pull request #532 from jsoriano/serial-number-without-udevadm
Read disk model and serial from udev data or sysfs on Linux
This commit is contained in:
commit
bc5d02c9ac
@ -3,10 +3,11 @@
|
||||
package disk
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -385,26 +386,33 @@ func GetDiskSerialNumber(name string) string {
|
||||
}
|
||||
|
||||
func GetDiskSerialNumberWithContext(ctx context.Context, name string) string {
|
||||
n := fmt.Sprintf("--name=%s", name)
|
||||
udevadm, err := exec.LookPath("/sbin/udevadm")
|
||||
var stat unix.Stat_t
|
||||
err := unix.Stat(name, &stat)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
major := unix.Major(stat.Rdev)
|
||||
minor := unix.Minor(stat.Rdev)
|
||||
|
||||
out, err := invoke.CommandWithContext(ctx, udevadm, "info", "--query=property", n)
|
||||
|
||||
// does not return error, just an empty string
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
lines := strings.Split(string(out), "\n")
|
||||
for _, line := range lines {
|
||||
values := strings.Split(line, "=")
|
||||
if len(values) < 2 || values[0] != "ID_SERIAL" {
|
||||
// only get ID_SERIAL, not ID_SERIAL_SHORT
|
||||
continue
|
||||
// Try to get the serial from udev data
|
||||
udevDataPath := fmt.Sprintf("/run/udev/data/b%d:%d", major, minor)
|
||||
if udevdata, err := ioutil.ReadFile(udevDataPath); err == nil {
|
||||
scanner := bufio.NewScanner(bytes.NewReader(udevdata))
|
||||
for scanner.Scan() {
|
||||
values := strings.Split(scanner.Text(), "=")
|
||||
if len(values) == 2 && values[0] == "E:ID_SERIAL" {
|
||||
return values[1]
|
||||
}
|
||||
}
|
||||
return values[1]
|
||||
}
|
||||
|
||||
// Try to get the serial from sysfs, look at the disk device (minor 0) directly
|
||||
// because if it is a partition it is not going to contain any device information
|
||||
devicePath := fmt.Sprintf("/sys/dev/block/%d:0/device", major)
|
||||
model, _ := ioutil.ReadFile(filepath.Join(devicePath, "model"))
|
||||
serial, _ := ioutil.ReadFile(filepath.Join(devicePath, "serial"))
|
||||
if len(model) > 0 && len(serial) > 0 {
|
||||
return fmt.Sprintf("%s_%s", string(model), string(serial))
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user