1
0
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:
Lomanic 2018-06-05 09:51:35 +02:00 committed by GitHub
commit bc5d02c9ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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 ""
}