github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/client/fingerprint/storage_unix.go (about) 1 //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris 2 // +build darwin dragonfly freebsd linux netbsd openbsd solaris 3 4 package fingerprint 5 6 import ( 7 "fmt" 8 "os/exec" 9 "path/filepath" 10 "runtime" 11 "strconv" 12 "strings" 13 ) 14 15 // diskFree inspects the filesystem for path and returns the volume name and 16 // the total and free bytes available on the file system. 17 func (f *StorageFingerprint) diskFree(path string) (volume string, total, free uint64, err error) { 18 absPath, err := filepath.Abs(path) 19 if err != nil { 20 return "", 0, 0, fmt.Errorf("failed to determine absolute path for %s", path) 21 } 22 23 // Use -k to standardize the output values between darwin and linux 24 var dfArgs string 25 if runtime.GOOS == "linux" { 26 // df on linux needs the -P option to prevent linebreaks on long filesystem paths 27 dfArgs = "-kP" 28 } else { 29 dfArgs = "-k" 30 } 31 32 mountOutput, err := exec.Command("df", dfArgs, absPath).Output() 33 if err != nil { 34 return "", 0, 0, fmt.Errorf("failed to determine mount point for %s", absPath) 35 } 36 // Output looks something like: 37 // Filesystem 1024-blocks Used Available Capacity iused ifree %iused Mounted on 38 // /dev/disk1 487385240 423722532 63406708 87% 105994631 15851677 87% / 39 // [0] volume [1] capacity [2] SKIP [3] free 40 lines := strings.Split(string(mountOutput), "\n") 41 if len(lines) < 2 { 42 return "", 0, 0, fmt.Errorf("failed to parse `df` output; expected at least 2 lines") 43 } 44 fields := strings.Fields(lines[1]) 45 if len(fields) < 4 { 46 return "", 0, 0, fmt.Errorf("failed to parse `df` output; expected at least 4 columns") 47 } 48 volume = fields[0] 49 50 total, err = strconv.ParseUint(fields[1], 10, 64) 51 if err != nil { 52 return "", 0, 0, fmt.Errorf("failed to parse storage.bytestotal size in kilobytes") 53 } 54 // convert to bytes 55 total *= 1024 56 57 free, err = strconv.ParseUint(fields[3], 10, 64) 58 if err != nil { 59 return "", 0, 0, fmt.Errorf("failed to parse storage.bytesfree size in kilobytes") 60 } 61 // convert to bytes 62 free *= 1024 63 64 return volume, total, free, nil 65 }