github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/disk/stat_windows.go (about)

     1  //go:build windows
     2  // +build windows
     3  
     4  // Copyright (c) 2015-2021 MinIO, Inc.
     5  //
     6  // This file is part of MinIO Object Storage stack
     7  //
     8  // This program is free software: you can redistribute it and/or modify
     9  // it under the terms of the GNU Affero General Public License as published by
    10  // the Free Software Foundation, either version 3 of the License, or
    11  // (at your option) any later version.
    12  //
    13  // This program is distributed in the hope that it will be useful
    14  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  // GNU Affero General Public License for more details.
    17  //
    18  // You should have received a copy of the GNU Affero General Public License
    19  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    20  
    21  package disk
    22  
    23  import (
    24  	"errors"
    25  	"fmt"
    26  	"os"
    27  	"syscall"
    28  	"unsafe"
    29  
    30  	"golang.org/x/sys/windows"
    31  )
    32  
    33  var (
    34  	kernel32 = windows.NewLazySystemDLL("kernel32.dll")
    35  
    36  	// GetDiskFreeSpaceEx - https://msdn.microsoft.com/en-us/library/windows/desktop/aa364937(v=vs.85).aspx
    37  	// Retrieves information about the amount of space that is available on a disk volume,
    38  	// which is the total amount of space, the total amount of free space, and the total
    39  	// amount of free space available to the user that is associated with the calling thread.
    40  	GetDiskFreeSpaceEx = kernel32.NewProc("GetDiskFreeSpaceExW")
    41  
    42  	// GetDiskFreeSpace - https://msdn.microsoft.com/en-us/library/windows/desktop/aa364935(v=vs.85).aspx
    43  	// Retrieves information about the specified disk, including the amount of free space on the disk.
    44  	GetDiskFreeSpace = kernel32.NewProc("GetDiskFreeSpaceW")
    45  )
    46  
    47  // GetInfo returns total and free bytes available in a directory, e.g. `C:\`.
    48  // It returns free space available to the user (including quota limitations)
    49  //
    50  // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364937(v=vs.85).aspx
    51  func GetInfo(path string, _ bool) (info Info, err error) {
    52  	// Stat to know if the path exists.
    53  	if _, err = os.Stat(path); err != nil {
    54  		return Info{}, err
    55  	}
    56  
    57  	lpFreeBytesAvailable := int64(0)
    58  	lpTotalNumberOfBytes := int64(0)
    59  	lpTotalNumberOfFreeBytes := int64(0)
    60  
    61  	// Extract values safely
    62  	// BOOL WINAPI GetDiskFreeSpaceEx(
    63  	// _In_opt_  LPCTSTR         lpDirectoryName,
    64  	// _Out_opt_ PULARGE_INTEGER lpFreeBytesAvailable,
    65  	// _Out_opt_ PULARGE_INTEGER lpTotalNumberOfBytes,
    66  	// _Out_opt_ PULARGE_INTEGER lpTotalNumberOfFreeBytes
    67  	// );
    68  	_, _, _ = GetDiskFreeSpaceEx.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))),
    69  		uintptr(unsafe.Pointer(&lpFreeBytesAvailable)),
    70  		uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)),
    71  		uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes)))
    72  
    73  	if uint64(lpTotalNumberOfFreeBytes) > uint64(lpTotalNumberOfBytes) {
    74  		return info, fmt.Errorf("detected free space (%d) > total drive space (%d), fs corruption at (%s). please run 'fsck'",
    75  			uint64(lpTotalNumberOfFreeBytes), uint64(lpTotalNumberOfBytes), path)
    76  	}
    77  
    78  	info = Info{
    79  		Total:  uint64(lpTotalNumberOfBytes),
    80  		Free:   uint64(lpTotalNumberOfFreeBytes),
    81  		Used:   uint64(lpTotalNumberOfBytes) - uint64(lpTotalNumberOfFreeBytes),
    82  		FSType: getFSType(path),
    83  	}
    84  
    85  	// Return values of GetDiskFreeSpace()
    86  	lpSectorsPerCluster := uint32(0)
    87  	lpBytesPerSector := uint32(0)
    88  	lpNumberOfFreeClusters := uint32(0)
    89  	lpTotalNumberOfClusters := uint32(0)
    90  
    91  	// Extract values safely
    92  	// BOOL WINAPI GetDiskFreeSpace(
    93  	//   _In_  LPCTSTR lpRootPathName,
    94  	//   _Out_ LPDWORD lpSectorsPerCluster,
    95  	//   _Out_ LPDWORD lpBytesPerSector,
    96  	//   _Out_ LPDWORD lpNumberOfFreeClusters,
    97  	//   _Out_ LPDWORD lpTotalNumberOfClusters
    98  	// );
    99  	_, _, _ = GetDiskFreeSpace.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))),
   100  		uintptr(unsafe.Pointer(&lpSectorsPerCluster)),
   101  		uintptr(unsafe.Pointer(&lpBytesPerSector)),
   102  		uintptr(unsafe.Pointer(&lpNumberOfFreeClusters)),
   103  		uintptr(unsafe.Pointer(&lpTotalNumberOfClusters)))
   104  
   105  	info.Files = uint64(lpTotalNumberOfClusters)
   106  	info.Ffree = uint64(lpNumberOfFreeClusters)
   107  
   108  	return info, nil
   109  }
   110  
   111  // GetDriveStats returns IO stats of the drive by its major:minor
   112  func GetDriveStats(major, minor uint32) (iostats IOStats, err error) {
   113  	return IOStats{}, errors.New("operation unsupported")
   114  }