Add lib/diskusage to measure used/free on disks

This commit is contained in:
Nick Craig-Wood 2023-09-05 10:29:05 +01:00
parent 8c25a15a40
commit 0fb36562dd
7 changed files with 145 additions and 0 deletions

View File

@ -0,0 +1,15 @@
// Package diskusage provides a cross platform version of the statfs
// system call to read disk space usage.
package diskusage
import "errors"
// Info is returned from New showing details about the disk.
type Info struct {
Free uint64 // total free bytes
Available uint64 // free bytes available to the current user
Total uint64 // total bytes on disk
}
// ErrUnsupported is returned if this platform doesn't support disk usage.
var ErrUnsupported = errors.New("disk usage unsupported on this platform")

View File

@ -0,0 +1,27 @@
//go:build netbsd
package diskusage
import (
"golang.org/x/sys/unix"
)
// New returns the disk status for dir.
//
// May return Unsupported error if it doesn't work on this platform.
func New(dir string) (info Info, err error) {
var statfs unix.Statvfs_t
err = unix.Statvfs(dir, &statfs)
if err != nil {
return info, err
}
// Note that these can be different sizes on different OSes so
// we upcast them all to uint64
//nolint:unconvert
info.Free = uint64(statfs.Bfree) * uint64(statfs.Bsize)
//nolint:unconvert
info.Available = uint64(statfs.Bavail) * uint64(statfs.Bsize)
//nolint:unconvert
info.Total = uint64(statfs.Blocks) * uint64(statfs.Bsize)
return info, nil
}

View File

@ -0,0 +1,27 @@
//go:build openbsd
package diskusage
import (
"golang.org/x/sys/unix"
)
// New returns the disk status for dir.
//
// May return Unsupported error if it doesn't work on this platform.
func New(dir string) (info Info, err error) {
var statfs unix.Statfs_t
err = unix.Statfs(dir, &statfs)
if err != nil {
return info, err
}
// Note that these can be different sizes on different OSes so
// we upcast them all to uint64
//nolint:unconvert
info.Free = uint64(statfs.F_bfree) * uint64(statfs.F_bsize)
//nolint:unconvert
info.Available = uint64(statfs.F_bavail) * uint64(statfs.F_bsize)
//nolint:unconvert
info.Total = uint64(statfs.F_blocks) * uint64(statfs.F_bsize)
return info, nil
}

View File

@ -0,0 +1,23 @@
package diskusage
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNew(t *testing.T) {
info, err := New(".")
if err == ErrUnsupported {
t.Skip(err)
}
require.NoError(t, err)
t.Logf("Free %16d", info.Free)
t.Logf("Available %16d", info.Available)
t.Logf("Total %16d", info.Total)
assert.True(t, info.Total != 0)
assert.True(t, info.Total > info.Free)
assert.True(t, info.Total > info.Available)
assert.True(t, info.Free >= info.Available)
}

View File

@ -0,0 +1,27 @@
//go:build aix || android || darwin || dragonfly || freebsd || ios || linux
package diskusage
import (
"golang.org/x/sys/unix"
)
// New returns the disk status for dir.
//
// May return Unsupported error if it doesn't work on this platform.
func New(dir string) (info Info, err error) {
var statfs unix.Statfs_t
err = unix.Statfs(dir, &statfs)
if err != nil {
return info, err
}
// Note that these can be different sizes on different OSes so
// we upcast them all to uint64
//nolint:unconvert
info.Free = uint64(statfs.Bfree) * uint64(statfs.Bsize)
//nolint:unconvert
info.Available = uint64(statfs.Bavail) * uint64(statfs.Bsize)
//nolint:unconvert
info.Total = uint64(statfs.Blocks) * uint64(statfs.Bsize)
return info, nil
}

View File

@ -0,0 +1,10 @@
//go:build illumos || js || plan9 || solaris
package diskusage
// New returns the disk status for dir.
//
// May return Unsupported error if it doesn't work on this platform.
func New(dir string) (info Info, err error) {
return info, ErrUnsupported
}

View File

@ -0,0 +1,16 @@
//go:build windows
package diskusage
import (
"golang.org/x/sys/windows"
)
// New returns the disk status for dir.
//
// May return Unsupported error if it doesn't work on this platform.
func New(dir string) (info Info, err error) {
dir16 := windows.StringToUTF16Ptr(dir)
err = windows.GetDiskFreeSpaceEx(dir16, &info.Available, &info.Total, &info.Free)
return info, err
}