...

Source file src/github.com/shirou/gopsutil/disk/disk_freebsd.go

Documentation: github.com/shirou/gopsutil/disk

     1  // +build freebsd
     2  
     3  package disk
     4  
     5  import (
     6  	"bytes"
     7  	"context"
     8  	"encoding/binary"
     9  	"strconv"
    10  
    11  	"golang.org/x/sys/unix"
    12  
    13  	"github.com/shirou/gopsutil/internal/common"
    14  )
    15  
    16  // PartitionsWithContext returns disk partition.
    17  // 'all' argument is ignored, see: https://github.com/giampaolo/psutil/issues/906
    18  func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
    19  	var ret []PartitionStat
    20  
    21  	// get length
    22  	count, err := unix.Getfsstat(nil, unix.MNT_WAIT)
    23  	if err != nil {
    24  		return ret, err
    25  	}
    26  
    27  	fs := make([]unix.Statfs_t, count)
    28  	if _, err = unix.Getfsstat(fs, unix.MNT_WAIT); err != nil {
    29  		return ret, err
    30  	}
    31  
    32  	for _, stat := range fs {
    33  		opts := "rw"
    34  		if stat.Flags&unix.MNT_RDONLY != 0 {
    35  			opts = "ro"
    36  		}
    37  		if stat.Flags&unix.MNT_SYNCHRONOUS != 0 {
    38  			opts += ",sync"
    39  		}
    40  		if stat.Flags&unix.MNT_NOEXEC != 0 {
    41  			opts += ",noexec"
    42  		}
    43  		if stat.Flags&unix.MNT_NOSUID != 0 {
    44  			opts += ",nosuid"
    45  		}
    46  		if stat.Flags&unix.MNT_UNION != 0 {
    47  			opts += ",union"
    48  		}
    49  		if stat.Flags&unix.MNT_ASYNC != 0 {
    50  			opts += ",async"
    51  		}
    52  		if stat.Flags&unix.MNT_SUIDDIR != 0 {
    53  			opts += ",suiddir"
    54  		}
    55  		if stat.Flags&unix.MNT_SOFTDEP != 0 {
    56  			opts += ",softdep"
    57  		}
    58  		if stat.Flags&unix.MNT_NOSYMFOLLOW != 0 {
    59  			opts += ",nosymfollow"
    60  		}
    61  		if stat.Flags&unix.MNT_GJOURNAL != 0 {
    62  			opts += ",gjournal"
    63  		}
    64  		if stat.Flags&unix.MNT_MULTILABEL != 0 {
    65  			opts += ",multilabel"
    66  		}
    67  		if stat.Flags&unix.MNT_ACLS != 0 {
    68  			opts += ",acls"
    69  		}
    70  		if stat.Flags&unix.MNT_NOATIME != 0 {
    71  			opts += ",noatime"
    72  		}
    73  		if stat.Flags&unix.MNT_NOCLUSTERR != 0 {
    74  			opts += ",noclusterr"
    75  		}
    76  		if stat.Flags&unix.MNT_NOCLUSTERW != 0 {
    77  			opts += ",noclusterw"
    78  		}
    79  		if stat.Flags&unix.MNT_NFS4ACLS != 0 {
    80  			opts += ",nfsv4acls"
    81  		}
    82  
    83  		d := PartitionStat{
    84  			Device:     common.ByteToString(stat.Mntfromname[:]),
    85  			Mountpoint: common.ByteToString(stat.Mntonname[:]),
    86  			Fstype:     common.ByteToString(stat.Fstypename[:]),
    87  			Opts:       opts,
    88  		}
    89  
    90  		ret = append(ret, d)
    91  	}
    92  
    93  	return ret, nil
    94  }
    95  
    96  func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
    97  	// statinfo->devinfo->devstat
    98  	// /usr/include/devinfo.h
    99  	ret := make(map[string]IOCountersStat)
   100  
   101  	r, err := unix.Sysctl("kern.devstat.all")
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  	buf := []byte(r)
   106  	length := len(buf)
   107  
   108  	count := int(uint64(length) / uint64(sizeOfDevstat))
   109  
   110  	buf = buf[8:] // devstat.all has version in the head.
   111  	// parse buf to Devstat
   112  	for i := 0; i < count; i++ {
   113  		b := buf[i*sizeOfDevstat : i*sizeOfDevstat+sizeOfDevstat]
   114  		d, err := parseDevstat(b)
   115  		if err != nil {
   116  			continue
   117  		}
   118  		un := strconv.Itoa(int(d.Unit_number))
   119  		name := common.IntToString(d.Device_name[:]) + un
   120  
   121  		if len(names) > 0 && !common.StringsHas(names, name) {
   122  			continue
   123  		}
   124  
   125  		ds := IOCountersStat{
   126  			ReadCount:  d.Operations[DEVSTAT_READ],
   127  			WriteCount: d.Operations[DEVSTAT_WRITE],
   128  			ReadBytes:  d.Bytes[DEVSTAT_READ],
   129  			WriteBytes: d.Bytes[DEVSTAT_WRITE],
   130  			ReadTime:   uint64(d.Duration[DEVSTAT_READ].Compute() * 1000),
   131  			WriteTime:  uint64(d.Duration[DEVSTAT_WRITE].Compute() * 1000),
   132  			IoTime:     uint64(d.Busy_time.Compute() * 1000),
   133  			Name:       name,
   134  		}
   135  		ret[name] = ds
   136  	}
   137  
   138  	return ret, nil
   139  }
   140  
   141  func (b Bintime) Compute() float64 {
   142  	BINTIME_SCALE := 5.42101086242752217003726400434970855712890625e-20
   143  	return float64(b.Sec) + float64(b.Frac)*BINTIME_SCALE
   144  }
   145  
   146  // BT2LD(time)     ((long double)(time).sec + (time).frac * BINTIME_SCALE)
   147  
   148  func parseDevstat(buf []byte) (Devstat, error) {
   149  	var ds Devstat
   150  	br := bytes.NewReader(buf)
   151  	//	err := binary.Read(br, binary.LittleEndian, &ds)
   152  	err := common.Read(br, binary.LittleEndian, &ds)
   153  	if err != nil {
   154  		return ds, err
   155  	}
   156  
   157  	return ds, nil
   158  }
   159  
   160  func getFsType(stat unix.Statfs_t) string {
   161  	return common.ByteToString(stat.Fstypename[:])
   162  }
   163  

View as plain text