github.com/kaydxh/golang@v0.0.131/go/syscall/disk.go (about)

     1  /*
     2   *Copyright (c) 2022, kaydxh
     3   *
     4   *Permission is hereby granted, free of charge, to any person obtaining a copy
     5   *of this software and associated documentation files (the "Software"), to deal
     6   *in the Software without restriction, including without limitation the rights
     7   *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     8   *copies of the Software, and to permit persons to whom the Software is
     9   *furnished to do so, subject to the following conditions:
    10   *
    11   *The above copyright notice and this permission notice shall be included in all
    12   *copies or substantial portions of the Software.
    13   *
    14   *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    15   *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    16   *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    17   *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    18   *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19   *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    20   *SOFTWARE.
    21   */
    22  package syscall
    23  
    24  import (
    25  	"syscall"
    26  
    27  	filesystem_ "github.com/kaydxh/golang/go/filesystem"
    28  )
    29  
    30  type DiskUsage struct {
    31  	stat *syscall.Statfs_t
    32  }
    33  
    34  func NewDiskUsage(path string) (*DiskUsage, error) {
    35  	var stat syscall.Statfs_t
    36  	mount, err := filesystem_.FindMount(path)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  
    41  	err = syscall.Statfs(mount.Path, &stat)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  
    46  	return &DiskUsage{&stat}, nil
    47  }
    48  
    49  // Free returns total free bytes on file system
    50  func (du *DiskUsage) Free() uint64 {
    51  	return du.stat.Bfree * uint64(du.stat.Bsize)
    52  }
    53  
    54  //  Avail returns total avail bytes on file system
    55  func (du *DiskUsage) Avail() uint64 {
    56  	return du.stat.Bavail * uint64(du.stat.Bsize)
    57  }
    58  
    59  // Size returns total size of the file system
    60  func (du *DiskUsage) Size() uint64 {
    61  	return uint64(du.stat.Blocks) * uint64(du.stat.Bsize)
    62  }
    63  
    64  // Size returns total used bytes on the file system
    65  func (du *DiskUsage) Used() uint64 {
    66  	return du.Size() - du.Free()
    67  }
    68  
    69  // Usage returns percentage of used on the file system
    70  /*
    71  https://github.com/coreutils/coreutils/blob/master/src/df.c#:~:text=pct%20%3D%20u100%20/%20nonroot_total%20%2B%20(u100%20%25%20nonroot_total%20!%3D%200)%3B
    72  By default, ext2/3/4 filesystems reserve 5% of the space to be useable only by root. This is to avoid a normal user completely filling the disk which would
    73  then cause system components to fail whenever they next needed to write to the disk
    74  */
    75  func (du *DiskUsage) Usage() float32 {
    76  	var deta float32
    77  	u100 := du.Used() * 100
    78  	nonrootTotal := du.Used() + du.Avail()
    79  	if u100%nonrootTotal != 0 {
    80  		deta = 1.0
    81  	}
    82  	return float32(u100)/float32(nonrootTotal) + deta
    83  }