gopkg.in/hugelgupf/u-root.v9@v9.0.0-20180831063832-3f6f1057f09b/cmds/df/df.go (about) 1 // Copyright 2015-2017 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 // 5 // df reports details of mounted filesystems 6 // 7 // Synopsis 8 // df [-k] [-m] 9 // 10 // Description 11 // read mount information from /proc/mounts and 12 // statfs syscall and display summary information for all 13 // mount points that have a non-zero block count. 14 // Users can choose to see the diplay in KB or MB. 15 // 16 // Options 17 // -k: display values in KB (default) 18 // -m: dispaly values in MB 19 // 20 package main 21 22 import ( 23 "bytes" 24 "flag" 25 "fmt" 26 "io/ioutil" 27 "log" 28 "math" 29 "syscall" 30 ) 31 32 var ( 33 inKB = flag.Bool("k", false, "Express the values in kilobytes (default)") 34 inMB = flag.Bool("m", false, "Express the values in megabytes") 35 units uint64 36 ) 37 38 const procmountsFile = "/proc/mounts" 39 40 const ( 41 // B is Bytes 42 B = 1 43 // KB is kilobytes 44 KB = 1024 * B 45 // MB is megabytes 46 MB = 1024 * KB 47 ) 48 49 // Mount is a structure used to contain mount point data 50 type Mount struct { 51 Device string 52 MountPoint string 53 FileSystemType string 54 Flags string 55 Bsize int64 56 Blocks uint64 57 Total uint64 58 Used uint64 59 Avail uint64 60 PCT uint8 61 } 62 63 type mountinfomap map[string]Mount 64 65 // mountinfo returns a map of mounts representing 66 // the data in /proc/mounts 67 func mountinfo() (mountinfomap, error) { 68 buf, err := ioutil.ReadFile(procmountsFile) 69 if err != nil { 70 return nil, err 71 } 72 return mountinfoFromBytes(buf) 73 } 74 75 // returns a map generated from the bytestream returned 76 // from /proc/mounts 77 // for tidiness, we decide to ignore filesystems of size 0 78 // to exclude cgroup, procfs and sysfs types 79 func mountinfoFromBytes(buf []byte) (mountinfomap, error) { 80 ret := make(mountinfomap, 0) 81 for _, line := range bytes.Split(buf, []byte{'\n'}) { 82 kv := bytes.SplitN(line, []byte{' '}, 6) 83 if len(kv) != 6 { 84 // can't interpret this 85 continue 86 } 87 key := string(kv[1]) 88 var mnt Mount 89 mnt.Device = string(kv[0]) 90 mnt.MountPoint = string(kv[1]) 91 mnt.FileSystemType = string(kv[2]) 92 mnt.Flags = string(kv[3]) 93 DiskUsage(&mnt) 94 if mnt.Blocks == 0 { 95 continue 96 } else { 97 ret[key] = mnt 98 } 99 } 100 return ret, nil 101 } 102 103 // DiskUsage calculates the usage statistics of a mount point 104 // note: arm7 Bsize is int32; all others are int64 105 func DiskUsage(mnt *Mount) { 106 fs := syscall.Statfs_t{} 107 err := syscall.Statfs(mnt.MountPoint, &fs) 108 if err != nil { 109 return 110 } 111 mnt.Blocks = fs.Blocks * uint64(fs.Bsize) / units 112 mnt.Bsize = int64(fs.Bsize) 113 mnt.Total = fs.Blocks * uint64(fs.Bsize) / units 114 mnt.Avail = fs.Bavail * uint64(fs.Bsize) / units 115 mnt.Used = (fs.Blocks - fs.Bfree) * uint64(fs.Bsize) / units 116 pct := float64((fs.Blocks - fs.Bfree)) * 100 / float64(fs.Blocks) 117 mnt.PCT = uint8(math.Ceil(pct)) 118 return 119 } 120 121 // SetUnits takes the command line flags and configures 122 // the correct units used to calculate display values 123 func SetUnits() { 124 if *inKB && *inMB { 125 log.Fatal("options -k and -m are mutually exclusive") 126 } 127 if *inMB { 128 units = MB 129 } else { 130 units = KB 131 } 132 } 133 134 func df() { 135 SetUnits() 136 mounts, _ := mountinfo() 137 var blocksize = "1K" 138 if *inMB { 139 blocksize = "1M" 140 } 141 fmt.Printf("Filesystem Type %v-blocks Used Available Use%% Mounted on\n", blocksize) 142 for _, mnt := range mounts { 143 fmt.Printf("%-20v %-9v %12v %10v %12v %4v%% %-13v\n", 144 mnt.Device, 145 mnt.FileSystemType, 146 mnt.Blocks, 147 mnt.Used, 148 mnt.Avail, 149 mnt.PCT, 150 mnt.MountPoint) 151 } 152 } 153 154 func main() { 155 flag.Parse() 156 df() 157 }