1// +build openbsd
2
3package disk
4
5import (
6	"bytes"
7	"context"
8	"encoding/binary"
9
10	"github.com/shirou/gopsutil/v3/internal/common"
11	"golang.org/x/sys/unix"
12)
13
14func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
15	var ret []PartitionStat
16
17	// get length
18	count, err := unix.Getfsstat(nil, unix.MNT_WAIT)
19	if err != nil {
20		return ret, err
21	}
22
23	fs := make([]unix.Statfs_t, count)
24	if _, err = unix.Getfsstat(fs, unix.MNT_WAIT); err != nil {
25		return ret, err
26	}
27
28	for _, stat := range fs {
29		opts := []string{"rw"}
30		if stat.F_flags&unix.MNT_RDONLY != 0 {
31			opts = []string{"rw"}
32		}
33		if stat.F_flags&unix.MNT_SYNCHRONOUS != 0 {
34			opts = append(opts, "sync")
35		}
36		if stat.F_flags&unix.MNT_NOEXEC != 0 {
37			opts = append(opts, "noexec")
38		}
39		if stat.F_flags&unix.MNT_NOSUID != 0 {
40			opts = append(opts, "nosuid")
41		}
42		if stat.F_flags&unix.MNT_NODEV != 0 {
43			opts = append(opts, "nodev")
44		}
45		if stat.F_flags&unix.MNT_ASYNC != 0 {
46			opts = append(opts, "async")
47		}
48		if stat.F_flags&unix.MNT_SOFTDEP != 0 {
49			opts = append(opts, "softdep")
50		}
51		if stat.F_flags&unix.MNT_NOATIME != 0 {
52			opts = append(opts, "noatime")
53		}
54		if stat.F_flags&unix.MNT_WXALLOWED != 0 {
55			opts = append(opts, "wxallowed")
56		}
57
58		d := PartitionStat{
59			Device:     common.IntToString(stat.F_mntfromname[:]),
60			Mountpoint: common.IntToString(stat.F_mntonname[:]),
61			Fstype:     common.IntToString(stat.F_fstypename[:]),
62			Opts:       opts,
63		}
64
65		ret = append(ret, d)
66	}
67
68	return ret, nil
69}
70
71func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
72	ret := make(map[string]IOCountersStat)
73
74	r, err := unix.SysctlRaw("hw.diskstats")
75	if err != nil {
76		return nil, err
77	}
78	buf := []byte(r)
79	length := len(buf)
80
81	count := int(uint64(length) / uint64(sizeOfDiskstats))
82
83	// parse buf to Diskstats
84	for i := 0; i < count; i++ {
85		b := buf[i*sizeOfDiskstats : i*sizeOfDiskstats+sizeOfDiskstats]
86		d, err := parseDiskstats(b)
87		if err != nil {
88			continue
89		}
90		name := common.IntToString(d.Name[:])
91
92		if len(names) > 0 && !common.StringsHas(names, name) {
93			continue
94		}
95
96		ds := IOCountersStat{
97			ReadCount:  d.Rxfer,
98			WriteCount: d.Wxfer,
99			ReadBytes:  d.Rbytes,
100			WriteBytes: d.Wbytes,
101			Name:       name,
102		}
103		ret[name] = ds
104	}
105
106	return ret, nil
107}
108
109// BT2LD(time)     ((long double)(time).sec + (time).frac * BINTIME_SCALE)
110
111func parseDiskstats(buf []byte) (Diskstats, error) {
112	var ds Diskstats
113	br := bytes.NewReader(buf)
114	//	err := binary.Read(br, binary.LittleEndian, &ds)
115	err := common.Read(br, binary.LittleEndian, &ds)
116	if err != nil {
117		return ds, err
118	}
119
120	return ds, nil
121}
122
123func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
124	stat := unix.Statfs_t{}
125	err := unix.Statfs(path, &stat)
126	if err != nil {
127		return nil, err
128	}
129	bsize := stat.F_bsize
130
131	ret := &UsageStat{
132		Path:        path,
133		Fstype:      getFsType(stat),
134		Total:       (uint64(stat.F_blocks) * uint64(bsize)),
135		Free:        (uint64(stat.F_bavail) * uint64(bsize)),
136		InodesTotal: (uint64(stat.F_files)),
137		InodesFree:  (uint64(stat.F_ffree)),
138	}
139
140	ret.InodesUsed = (ret.InodesTotal - ret.InodesFree)
141	ret.InodesUsedPercent = (float64(ret.InodesUsed) / float64(ret.InodesTotal)) * 100.0
142	ret.Used = (uint64(stat.F_blocks) - uint64(stat.F_bfree)) * uint64(bsize)
143	ret.UsedPercent = (float64(ret.Used) / float64(ret.Total)) * 100.0
144
145	return ret, nil
146}
147
148func getFsType(stat unix.Statfs_t) string {
149	return common.IntToString(stat.F_fstypename[:])
150}
151
152func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
153	return "", common.ErrNotImplementedError
154}
155
156func LabelWithContext(ctx context.Context, name string) (string, error) {
157	return "", common.ErrNotImplementedError
158}
159