package diskspace import ( "errors" "fmt" "math" "syscall" ) var ErrInsufficientSpace = errors.New("not enough free disk space") func Available(path string) (int64, error) { var stats syscall.Statfs_t if err := syscall.Statfs(path, &stats); err != nil { return 0, err } available := stats.Bavail * uint64(stats.Bsize) if available > math.MaxInt64 { return math.MaxInt64, nil } return int64(available), nil } func EnsureFree(path string, requiredBytes, reservedBytes int64) error { available, err := Available(path) if err != nil { return err } if available-reservedBytes < requiredBytes { return fmt.Errorf("%w: %.1f GiB needed, %.1f GiB usable after keeping %.1f GiB free", ErrInsufficientSpace, toGiB(requiredBytes), toGiB(available-reservedBytes), toGiB(reservedBytes)) } return nil } func toGiB(bytes int64) float64 { return float64(bytes) / float64(1<<30) }