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