mirror of
https://github.com/shirou/gopsutil.git
synced 2025-04-26 13:48:59 +08:00

Executing the command does the lookup if needed and returns the same error when not found, no need to do it separately.
148 lines
3.8 KiB
Go
148 lines
3.8 KiB
Go
//go:build solaris
|
|
// +build solaris
|
|
|
|
package disk
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"math"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/shirou/gopsutil/v3/internal/common"
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
const (
|
|
// _DEFAULT_NUM_MOUNTS is set to `cat /etc/mnttab | wc -l` rounded up to the
|
|
// nearest power of two.
|
|
_DEFAULT_NUM_MOUNTS = 32
|
|
|
|
// _MNTTAB default place to read mount information
|
|
_MNTTAB = "/etc/mnttab"
|
|
)
|
|
|
|
// A blacklist of read-only virtual filesystems. Writable filesystems are of
|
|
// operational concern and must not be included in this list.
|
|
var fsTypeBlacklist = map[string]struct{}{
|
|
"ctfs": {},
|
|
"dev": {},
|
|
"fd": {},
|
|
"lofs": {},
|
|
"lxproc": {},
|
|
"mntfs": {},
|
|
"objfs": {},
|
|
"proc": {},
|
|
}
|
|
|
|
func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
|
|
ret := make([]PartitionStat, 0, _DEFAULT_NUM_MOUNTS)
|
|
|
|
// Scan mnttab(4)
|
|
f, err := os.Open(_MNTTAB)
|
|
if err != nil {
|
|
}
|
|
defer func() {
|
|
if err == nil {
|
|
err = f.Close()
|
|
} else {
|
|
f.Close()
|
|
}
|
|
}()
|
|
|
|
scanner := bufio.NewScanner(f)
|
|
for scanner.Scan() {
|
|
fields := strings.Split(scanner.Text(), "\t")
|
|
|
|
if _, found := fsTypeBlacklist[fields[2]]; found {
|
|
continue
|
|
}
|
|
|
|
ret = append(ret, PartitionStat{
|
|
// NOTE(seanc@): Device isn't exactly accurate: from mnttab(4): "The name
|
|
// of the resource that has been mounted." Ideally this value would come
|
|
// from Statvfs_t.Fsid but I'm leaving it to the caller to traverse
|
|
// unix.Statvfs().
|
|
Device: fields[0],
|
|
Mountpoint: fields[1],
|
|
Fstype: fields[2],
|
|
Opts: strings.Split(fields[3], ","),
|
|
})
|
|
}
|
|
if err := scanner.Err(); err != nil {
|
|
return nil, fmt.Errorf("unable to scan %q: %v", _MNTTAB, err)
|
|
}
|
|
|
|
return ret, err
|
|
}
|
|
|
|
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
|
|
return nil, common.ErrNotImplementedError
|
|
}
|
|
|
|
func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
|
|
statvfs := unix.Statvfs_t{}
|
|
if err := unix.Statvfs(path, &statvfs); err != nil {
|
|
return nil, fmt.Errorf("unable to call statvfs(2) on %q: %v", path, err)
|
|
}
|
|
|
|
usageStat := &UsageStat{
|
|
Path: path,
|
|
Fstype: common.IntToString(statvfs.Basetype[:]),
|
|
Total: statvfs.Blocks * statvfs.Frsize,
|
|
Free: statvfs.Bfree * statvfs.Frsize,
|
|
Used: (statvfs.Blocks - statvfs.Bfree) * statvfs.Frsize,
|
|
|
|
// NOTE: ZFS (and FreeBZSD's UFS2) use dynamic inode/dnode allocation.
|
|
// Explicitly return a near-zero value for InodesUsedPercent so that nothing
|
|
// attempts to garbage collect based on a lack of available inodes/dnodes.
|
|
// Similarly, don't use the zero value to prevent divide-by-zero situations
|
|
// and inject a faux near-zero value. Filesystems evolve. Has your
|
|
// filesystem evolved? Probably not if you care about the number of
|
|
// available inodes.
|
|
InodesTotal: 1024.0 * 1024.0,
|
|
InodesUsed: 1024.0,
|
|
InodesFree: math.MaxUint64,
|
|
InodesUsedPercent: (1024.0 / (1024.0 * 1024.0)) * 100.0,
|
|
}
|
|
|
|
usageStat.UsedPercent = (float64(usageStat.Used) / float64(usageStat.Total)) * 100.0
|
|
|
|
return usageStat, nil
|
|
}
|
|
|
|
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
|
|
out, err := invoke.CommandWithContext(ctx, "cfgadm", "-ls", "select=type(disk),cols=ap_id:info,cols2=,noheadings")
|
|
if err != nil {
|
|
return "", fmt.Errorf("exec cfgadm: %w", err)
|
|
}
|
|
|
|
suf := "::" + strings.TrimPrefix(name, "/dev/")
|
|
s := bufio.NewScanner(bytes.NewReader(out))
|
|
for s.Scan() {
|
|
flds := strings.Fields(s.Text())
|
|
if strings.HasSuffix(flds[0], suf) {
|
|
flen := len(flds)
|
|
if flen >= 3 {
|
|
for i, f := range flds {
|
|
if i > 0 && i < flen-1 && f == "SN:" {
|
|
return flds[i+1], nil
|
|
}
|
|
}
|
|
}
|
|
return "", nil
|
|
}
|
|
}
|
|
if err := s.Err(); err != nil {
|
|
return "", err
|
|
}
|
|
return "", nil
|
|
}
|
|
|
|
func LabelWithContext(ctx context.Context, name string) (string, error) {
|
|
return "", common.ErrNotImplementedError
|
|
}
|