1// +build solaris 2 3package disk 4 5import ( 6 "bufio" 7 "context" 8 "fmt" 9 "math" 10 "os" 11 "strings" 12 13 "github.com/shirou/gopsutil/v3/internal/common" 14 "golang.org/x/sys/unix" 15) 16 17const ( 18 // _DEFAULT_NUM_MOUNTS is set to `cat /etc/mnttab | wc -l` rounded up to the 19 // nearest power of two. 20 _DEFAULT_NUM_MOUNTS = 32 21 22 // _MNTTAB default place to read mount information 23 _MNTTAB = "/etc/mnttab" 24) 25 26var ( 27 // A blacklist of read-only virtual filesystems. Writable filesystems are of 28 // operational concern and must not be included in this list. 29 fsTypeBlacklist = map[string]struct{}{ 30 "ctfs": struct{}{}, 31 "dev": struct{}{}, 32 "fd": struct{}{}, 33 "lofs": struct{}{}, 34 "lxproc": struct{}{}, 35 "mntfs": struct{}{}, 36 "objfs": struct{}{}, 37 "proc": struct{}{}, 38 } 39) 40 41func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) { 42 ret := make([]PartitionStat, 0, _DEFAULT_NUM_MOUNTS) 43 44 // Scan mnttab(4) 45 f, err := os.Open(_MNTTAB) 46 if err != nil { 47 } 48 defer func() { 49 if err == nil { 50 err = f.Close() 51 } else { 52 f.Close() 53 } 54 }() 55 56 scanner := bufio.NewScanner(f) 57 for scanner.Scan() { 58 fields := strings.Split(scanner.Text(), "\t") 59 60 if _, found := fsTypeBlacklist[fields[2]]; found { 61 continue 62 } 63 64 ret = append(ret, PartitionStat{ 65 // NOTE(seanc@): Device isn't exactly accurate: from mnttab(4): "The name 66 // of the resource that has been mounted." Ideally this value would come 67 // from Statvfs_t.Fsid but I'm leaving it to the caller to traverse 68 // unix.Statvfs(). 69 Device: fields[0], 70 Mountpoint: fields[1], 71 Fstype: fields[2], 72 Opts: strings.Split(fields[3], ","), 73 }) 74 } 75 if err := scanner.Err(); err != nil { 76 return nil, fmt.Errorf("unable to scan %q: %v", _MNTTAB, err) 77 } 78 79 return ret, err 80} 81 82func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) { 83 return nil, common.ErrNotImplementedError 84} 85 86func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) { 87 statvfs := unix.Statvfs_t{} 88 if err := unix.Statvfs(path, &statvfs); err != nil { 89 return nil, fmt.Errorf("unable to call statvfs(2) on %q: %v", path, err) 90 } 91 92 usageStat := &UsageStat{ 93 Path: path, 94 Fstype: common.IntToString(statvfs.Basetype[:]), 95 Total: statvfs.Blocks * statvfs.Frsize, 96 Free: statvfs.Bfree * statvfs.Frsize, 97 Used: (statvfs.Blocks - statvfs.Bfree) * statvfs.Frsize, 98 99 // NOTE: ZFS (and FreeBZSD's UFS2) use dynamic inode/dnode allocation. 100 // Explicitly return a near-zero value for InodesUsedPercent so that nothing 101 // attempts to garbage collect based on a lack of available inodes/dnodes. 102 // Similarly, don't use the zero value to prevent divide-by-zero situations 103 // and inject a faux near-zero value. Filesystems evolve. Has your 104 // filesystem evolved? Probably not if you care about the number of 105 // available inodes. 106 InodesTotal: 1024.0 * 1024.0, 107 InodesUsed: 1024.0, 108 InodesFree: math.MaxUint64, 109 InodesUsedPercent: (1024.0 / (1024.0 * 1024.0)) * 100.0, 110 } 111 112 usageStat.UsedPercent = (float64(usageStat.Used) / float64(usageStat.Total)) * 100.0 113 114 return usageStat, nil 115} 116func SerialNumberWithContext(ctx context.Context, name string) (string, error) { 117 return "", common.ErrNotImplementedError 118} 119 120func LabelWithContext(ctx context.Context, name string) (string, error) { 121 return "", common.ErrNotImplementedError 122} 123