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  }