4

I want to get total size of a drive in Go on windows using standard windows api call;

I found this to get the free space.

Now I want to total space size of special drive for example

C:\

icza
  • 389,944
  • 63
  • 907
  • 827
Zola Man
  • 113
  • 9

3 Answers3

4

Your linked question+answer shows how to get the free space. The solution uses the GetDiskFreeSpaceExW() windows API function from the kernel32.dll to obtain it.

The same function can be used to get total size too. Signature of the GetDiskFreeSpaceExW() function:

BOOL GetDiskFreeSpaceExW(
  LPCWSTR         lpDirectoryName,
  PULARGE_INTEGER lpFreeBytesAvailableToCaller,
  PULARGE_INTEGER lpTotalNumberOfBytes,
  PULARGE_INTEGER lpTotalNumberOfFreeBytes
);

It has an in-parameter, the path, and it has 3 out-parameters, namely the free bytes (available to caller), the total bytes (disk size) and the total free bytes.

So simply when you call it, provide variables (pointers) for all info you want to get out of it.

For example:

kernelDLL := syscall.MustLoadDLL("kernel32.dll")
GetDiskFreeSpaceExW := kernelDLL.MustFindProc("GetDiskFreeSpaceExW")

var free, total, avail int64

path := "c:\\"
r1, r2, lastErr := GetDiskFreeSpaceExW.Call(
    uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))),
    uintptr(unsafe.Pointer(&free)),
    uintptr(unsafe.Pointer(&total)),
    uintptr(unsafe.Pointer(&avail)),
)

fmt.Println(r1, r2, lastErr)
fmt.Println("Free:", free, "Total:", total, "Available:", avail)

Running it, an example output:

1 0 Success.
Free: 16795295744 Total: 145545281536 Available: 16795295744
icza
  • 389,944
  • 63
  • 907
  • 827
3

Other replies are outdated since syscall is deprecated.

You must use golang.org/x/sys/windows now (adapting icza answer):

import (
    "fmt"
    "golang.org/x/sys/windows"

)

// print disk usage of path/disk
func DiskUsage(path string) bool {

    var free, total, avail uint64

    path = "c:\\"
    pathPtr, err := windows.UTF16PtrFromString(path)
    if err != nil{
        panic(err)
    }
    err = windows.GetDiskFreeSpaceEx(pathPtr, &free, &total, &avail)


    fmt.Println("Free:", free, "Total:", total, "Available:", avail)
}
Gourgandine
  • 189
  • 6
2

In the docs for GetDiskFreeSpraceExW the function is declared as:

BOOL GetDiskFreeSpaceExW(
  LPCWSTR         lpDirectoryName,
  PULARGE_INTEGER lpFreeBytesAvailableToCaller,
  PULARGE_INTEGER lpTotalNumberOfBytes,
  PULARGE_INTEGER lpTotalNumberOfFreeBytes
);

So you get the total size and available size in one call:

import "syscall"
import "os"

func main() {
    wd := os.Getwd()

    h := syscall.MustLoadDLL("kernel32.dll")
    c := h.MustFindProc("GetDiskFreeSpaceExW")

    var freeBytesAvailableToCaller int64
    var totalNumberOfBytes int64
    var totalNumberOfFreeBytes int64

    c.Call(
        uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(wd))),
        uintptr(unsafe.Pointer(&freeBytesAvailableToCaller)), 
        uintptr(unsafe.Pointer(&totalNumberOfBytes)), 
        uintptr(unsafe.Pointer(&totalNumberOfFreeBytes))
    )

    print(freeBytesAvailableToCaller, totalNumberOfBytes, totalNumberOfBytes)
}
Kevin Sandow
  • 4,003
  • 1
  • 20
  • 33