gopkg.in/hugelgupf/u-root.v2@v2.0.0-20180831055005-3f8fdb0ce09d/cmds/free/free_linux.go (about) 1 // Copyright 2018 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 package main 6 7 import ( 8 "bytes" 9 "fmt" 10 "io/ioutil" 11 "strconv" 12 ) 13 14 const meminfoFile = "/proc/meminfo" 15 16 // meminfo returns a mapping that represents the fields contained in 17 // /proc/meminfo 18 func meminfo() (meminfomap, error) { 19 buf, err := ioutil.ReadFile(meminfoFile) 20 if err != nil { 21 return nil, err 22 } 23 return meminfoFromBytes(buf) 24 } 25 26 // meminfoFromBytes returns a mapping that represents the fields contained in a 27 // byte stream with a content compatible with /proc/meminfo 28 func meminfoFromBytes(buf []byte) (meminfomap, error) { 29 ret := make(meminfomap, 0) 30 for _, line := range bytes.Split(buf, []byte{'\n'}) { 31 kv := bytes.SplitN(line, []byte{':'}, 2) 32 if len(kv) != 2 { 33 // invalid line? 34 continue 35 } 36 key := string(kv[0]) 37 tokens := bytes.SplitN(bytes.TrimSpace(kv[1]), []byte{' '}, 2) 38 if len(tokens) > 0 { 39 value, err := strconv.ParseUint(string(tokens[0]), 10, 64) 40 if err != nil { 41 return nil, err 42 } 43 ret[key] = value 44 } 45 } 46 return ret, nil 47 } 48 49 // getMainMemInfo prints the physical memory information in the specified units. Only 50 // the relevant fields will be used from the input map. 51 func getMainMemInfo(m meminfomap, config *FreeConfig) (*mainMemInfo, error) { 52 fields := []string{ 53 "MemTotal", 54 "MemFree", 55 "Buffers", 56 "Cached", 57 "Shmem", 58 "SReclaimable", 59 "MemAvailable", 60 } 61 if missingRequiredFields(m, fields) { 62 return nil, fmt.Errorf("Missing required fields from meminfo") 63 } 64 65 // These values are expressed in kibibytes, convert to the desired unit 66 memTotal := m["MemTotal"] << KB 67 memFree := m["MemFree"] << KB 68 memShared := m["Shmem"] << KB 69 memCached := (m["Cached"] + m["SReclaimable"]) << KB 70 memBuffers := (m["Buffers"]) << KB 71 memUsed := memTotal - memFree - memCached - memBuffers 72 if memUsed < 0 { 73 memUsed = memTotal - memFree 74 } 75 memAvailable := m["MemAvailable"] << KB 76 77 mmi := mainMemInfo{ 78 Total: memTotal, 79 Used: memUsed, 80 Free: memFree, 81 Shared: memShared, 82 Cached: memCached, 83 Buffers: memBuffers, 84 Available: memAvailable, 85 } 86 return &mmi, nil 87 } 88 89 // getSwapInfo prints the swap space information in the specified units. Only the 90 // relevant fields will be used from the input map. 91 func getSwapInfo(m meminfomap, config *FreeConfig) (*swapInfo, error) { 92 fields := []string{ 93 "SwapTotal", 94 "SwapFree", 95 } 96 if missingRequiredFields(m, fields) { 97 return nil, fmt.Errorf("Missing required fields from meminfo") 98 } 99 // These values are expressed in kibibytes, convert to the desired unit 100 swapTotal := m["SwapTotal"] << KB 101 swapUsed := (m["SwapTotal"] - m["SwapFree"]) << KB 102 swapFree := m["SwapFree"] << KB 103 104 si := swapInfo{ 105 Total: swapTotal, 106 Used: swapUsed, 107 Free: swapFree, 108 } 109 return &si, nil 110 }