/
load.go
115 lines (100 loc) · 2.51 KB
/
load.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
package mod
import (
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/klauspost/compress/zstd"
"github.com/klauspost/pgzip"
"github.com/ulikunitz/xz"
"golang.org/x/sys/unix"
)
var (
ErrModuleInfoNotFound = errors.New("module info not found")
ErrCircularDependency = errors.New("circular dependency")
)
func initDependencies(path string, modulesInfo map[string]moduleInfo) (err error) {
info, ok := modulesInfo[path]
if !ok {
return fmt.Errorf("%w: %s", ErrModuleInfoNotFound, path)
}
switch info.state {
case unloaded:
case loaded, builtin:
return nil
case loading:
return fmt.Errorf("%w: %s is already in the loading state",
ErrCircularDependency, path)
}
info.state = loading
modulesInfo[path] = info
for _, dependencyPath := range info.dependencyPaths {
err = initDependencies(dependencyPath, modulesInfo)
if err != nil {
return fmt.Errorf("init dependencies for %s: %w", path, err)
}
}
err = initModule(path)
if err != nil {
return fmt.Errorf("loading module: %w", err)
}
info.state = loaded
modulesInfo[path] = info
return nil
}
func initModule(path string) (err error) {
file, err := os.Open(path)
if err != nil {
return fmt.Errorf("opening module file: %w", err)
}
defer func() {
_ = file.Close()
}()
var reader io.Reader
switch filepath.Ext(file.Name()) {
case ".xz":
reader, err = xz.NewReader(file)
case ".gz":
reader, err = pgzip.NewReader(file)
case ".zst":
reader, err = zstd.NewReader(file)
default:
const moduleParams = ""
const flags = 0
err = unix.FinitModule(int(file.Fd()), moduleParams, flags)
switch {
case err == nil, err == unix.EEXIST: //nolint:goerr113
return nil
case err != unix.ENOSYS: //nolint:goerr113
if strings.HasSuffix(err.Error(), "operation not permitted") {
err = fmt.Errorf("%w; did you set the SYS_MODULE capability to your container?", err)
}
return fmt.Errorf("finit module %s: %w", path, err)
case flags != 0:
return err // unix.ENOSYS error
default: // Fall back to init_module(2).
reader = file
}
}
if err != nil {
return fmt.Errorf("reading from %s: %w", path, err)
}
image, err := io.ReadAll(reader)
if err != nil {
return fmt.Errorf("reading module image from %s: %w", path, err)
}
err = file.Close()
if err != nil {
return fmt.Errorf("closing module file %s: %w", path, err)
}
const params = ""
err = unix.InitModule(image, params)
switch err {
case nil, unix.EEXIST:
return nil
default:
return fmt.Errorf("init module read from %s: %w", path, err)
}
}