/
crit.go
167 lines (152 loc) · 4.19 KB
/
crit.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package crit
import (
"encoding/json"
"errors"
"fmt"
"io"
"os"
)
// CritSvc is the interface that wraps all CRIT operations.
// To create a CRIT service instance, use New().
type CritSvc interface {
// Read binary image file into Go struct (decode.go)
Decode() (*CriuImage, error)
// Read only counts of image file entries into Go struct
Info() (*CriuImage, error)
// Read JSON into Go struct
Parse() (*CriuImage, error)
// Write JSON to binary image file (encode.go)
Encode(*CriuImage) error
// Explore process information (explore.go)
ExplorePs() (*PsTree, error)
ExploreFds() ([]*Fd, error)
ExploreMems() ([]*MemMap, error)
ExploreRss() ([]*RssMap, error)
}
// crit implements the CritSvc interface. It contains:
// * Path of the input file
// * Path of the output file
// * Path of the input directory (for `crit explore`)
// * Boolean to format and indent JSON output
// * Boolean to skip payload data
// * Boolean to indicate CLI usage
type crit struct {
inputFilePath string
outputFilePath string
// Directory path is required only for exploring
inputDirPath string
pretty bool
noPayload bool
cli bool
}
// New creates a CRIT service to use in a Go program
func New(
inputFilePath, outputFilePath,
inputDirPath string,
pretty, noPayload bool,
) CritSvc {
return &crit{
inputFilePath: inputFilePath,
outputFilePath: outputFilePath,
inputDirPath: inputDirPath,
pretty: pretty,
noPayload: noPayload,
cli: false,
}
}
// NewCli creates a CRIT service to use in a CLI app.
// All functions called by this service will wait for
// input from stdin if an input path is not provided.
func NewCli(
inputFilePath, outputFilePath,
inputDirPath string,
pretty, noPayload bool,
) CritSvc {
return &crit{
inputFilePath: inputFilePath,
outputFilePath: outputFilePath,
inputDirPath: inputDirPath,
pretty: pretty,
noPayload: noPayload,
cli: true,
}
}
// Decode loads a binary image file into a CriuImage object
func (c *crit) Decode() (*CriuImage, error) {
// If no input path is provided in the CLI, read
// from stdin (pipe, redirection, or keyboard)
if c.inputFilePath == "" {
if c.cli {
return decodeImg(os.Stdin, c.noPayload)
}
}
imgFile, err := os.Open(c.inputFilePath)
if err != nil {
return nil,
errors.New(fmt.Sprint("Error opening image file: ", err))
}
defer imgFile.Close()
// Convert binary image to Go struct
return decodeImg(imgFile, c.noPayload)
}
// Info loads a binary image file into a CriuImage object
// with a single entry - the number of entries in the file.
// No payload data is present in the returned object.
func (c *crit) Info() (*CriuImage, error) {
// If no input path is provided in the CLI, read
// from stdin (pipe, redirection, or keyboard)
if c.inputFilePath == "" {
if c.cli {
return countImg(os.Stdin)
}
}
imgFile, err := os.Open(c.inputFilePath)
if err != nil {
return nil,
errors.New(fmt.Sprint("Error opening image file: ", err))
}
defer imgFile.Close()
// Convert binary image to Go struct
return countImg(imgFile)
}
// Parse is the JSON equivalent of Decode.
// It loads a JSON file into a CriuImage object.
func (c *crit) Parse() (*CriuImage, error) {
var (
jsonData []byte
err error
)
// If no input path is provided in the CLI, read
// from stdin (pipe, redirection, or keyboard)
if c.inputFilePath == "" {
if c.cli {
jsonData, err = io.ReadAll(os.Stdin)
}
} else {
jsonData, err = os.ReadFile(c.inputFilePath)
}
if err != nil {
return nil, errors.New(fmt.Sprint("Error reading JSON: ", err))
}
img := CriuImage{}
if err = json.Unmarshal(jsonData, &img); err != nil {
return nil, errors.New(fmt.Sprint("Error processing JSON: ", err))
}
return &img, nil
}
// Encode dumps a CriuImage object into a binary image file
func (c *crit) Encode(img *CriuImage) error {
// If no output path is provided in the CLI, print to stdout
if c.outputFilePath == "" {
if c.cli {
return encodeImg(img, os.Stdout)
}
}
imgFile, err := os.Create(c.outputFilePath)
if err != nil {
return errors.New(fmt.Sprint("Error opening destination file: ", err))
}
defer imgFile.Close()
// Convert JSON to Go struct
return encodeImg(img, imgFile)
}