1// Copyright 2019 The Prometheus Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package procfs
15
16import (
17	"bufio"
18	"bytes"
19	"fmt"
20	"strconv"
21	"strings"
22
23	"github.com/prometheus/procfs/internal/util"
24)
25
26// Swap represents an entry in /proc/swaps.
27type Swap struct {
28	Filename string
29	Type     string
30	Size     int
31	Used     int
32	Priority int
33}
34
35// Swaps returns a slice of all configured swap devices on the system.
36func (fs FS) Swaps() ([]*Swap, error) {
37	data, err := util.ReadFileNoStat(fs.proc.Path("swaps"))
38	if err != nil {
39		return nil, err
40	}
41	return parseSwaps(data)
42}
43
44func parseSwaps(info []byte) ([]*Swap, error) {
45	swaps := []*Swap{}
46	scanner := bufio.NewScanner(bytes.NewReader(info))
47	scanner.Scan() // ignore header line
48	for scanner.Scan() {
49		swapString := scanner.Text()
50		parsedSwap, err := parseSwapString(swapString)
51		if err != nil {
52			return nil, err
53		}
54		swaps = append(swaps, parsedSwap)
55	}
56
57	err := scanner.Err()
58	return swaps, err
59}
60
61func parseSwapString(swapString string) (*Swap, error) {
62	var err error
63
64	swapFields := strings.Fields(swapString)
65	swapLength := len(swapFields)
66	if swapLength < 5 {
67		return nil, fmt.Errorf("too few fields in swap string: %s", swapString)
68	}
69
70	swap := &Swap{
71		Filename: swapFields[0],
72		Type:     swapFields[1],
73	}
74
75	swap.Size, err = strconv.Atoi(swapFields[2])
76	if err != nil {
77		return nil, fmt.Errorf("invalid swap size: %s", swapFields[2])
78	}
79	swap.Used, err = strconv.Atoi(swapFields[3])
80	if err != nil {
81		return nil, fmt.Errorf("invalid swap used: %s", swapFields[3])
82	}
83	swap.Priority, err = strconv.Atoi(swapFields[4])
84	if err != nil {
85		return nil, fmt.Errorf("invalid swap priority: %s", swapFields[4])
86	}
87
88	return swap, nil
89}
90