/
util.go
126 lines (105 loc) · 4.02 KB
/
util.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
// Copyright (c) 2018-2022, Sylabs Inc. All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the
// LICENSE.md file distributed with the sources of this project regarding your
// rights to use or distribute this software.
package build
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/sylabs/singularity/v4/internal/pkg/util/env"
"github.com/sylabs/singularity/v4/pkg/build/types"
"github.com/sylabs/singularity/v4/pkg/sylog"
"github.com/sylabs/singularity/v4/pkg/util/slice"
"golang.org/x/sys/unix"
)
func createStageFile(source string, b *types.Bundle, warnMsg string) (string, error) {
dest := filepath.Join(b.RootfsPath, source)
if err := unix.Access(dest, unix.R_OK); err != nil {
sylog.Warningf("%s: while accessing to %s: %s", warnMsg, dest, err)
return "", nil
}
sessionFile := filepath.Join(b.TmpDir, filepath.Base(source))
stageFile, err := os.Create(sessionFile)
if err != nil {
return "", fmt.Errorf("failed to create staging %s file: %s", sessionFile, err)
}
defer stageFile.Close()
content, err := os.ReadFile(source)
if err != nil {
return "", fmt.Errorf("failed to read %s: %s", source, err)
}
// Append an extra blank line to the end of the staged file. This is a trick to fix #5250
// where a yum install of the `setup` package can fail
//
// When /etc/hosts on the host system is unmodified from the distro 'setup' package, yum
// will try to rename & replace it if the 'setup' package is reinstalled / upgraded. This will
// fail as it is bind mounted, and cannot be renamed.
//
// Adding a newline means the staged file is now different than the one in the 'setup' package
// and yum will leave the file alone, as it considers it modified.
content = append(content, []byte("\n")...)
if _, err := stageFile.Write(content); err != nil {
return "", fmt.Errorf("failed to copy %s content to %s: %s", source, sessionFile, err)
}
return sessionFile, nil
}
func createScript(path string, content []byte) error {
f, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0o755)
if err != nil {
return fmt.Errorf("failed to create script: %s", err)
}
if _, err := f.Write(content); err != nil {
f.Close()
return fmt.Errorf("failed to write script: %s", err)
}
if err := f.Close(); err != nil {
return fmt.Errorf("failed to close script: %s", err)
}
return nil
}
func getSectionScriptArgs(name string, script string, s types.Script) ([]string, error) {
args := []string{"/bin/sh", "-ex"}
// trim potential trailing comment from args and append to args list
sectionParams := strings.Fields(strings.Split(s.Args, "#")[0])
commandOption := false
// look for -c option, we assume that everything after is part of -c
// arguments and we just inject script path as the last arguments of -c
for i, param := range sectionParams {
if param == "-c" {
if len(sectionParams)-1 < i+1 {
return nil, fmt.Errorf("bad %s section '-c' parameter: missing arguments", name)
}
// replace shell "[args...]" arguments list by single
// argument "shell [args...] script"
shellArgs := strings.Join(sectionParams[i+1:], " ")
sectionParams = append(sectionParams[0:i+1], shellArgs+" "+script)
commandOption = true
break
}
}
args = append(args, sectionParams...)
if !commandOption {
args = append(args, script)
}
return args, nil
}
// currentEnvNoSingularity returns the current environment, minus any SINGULARITY_ vars,
// but allowing those specified in the permitted slice. E.g. 'NV' in the permitted slice
// will pass through `SINGULARITY_NV`, but strip out `SINGULARITY_OTHERVAR`.
func currentEnvNoSingularity(permitted []string) []string {
envs := make([]string, 0)
for _, e := range os.Environ() {
if !strings.HasPrefix(e, env.SingularityPrefix) {
envs = append(envs, e)
} else {
envKey := strings.SplitN(e, "=", 2)
if slice.ContainsString(permitted, strings.TrimPrefix(envKey[0], env.SingularityPrefix)) {
sylog.Debugf("Passing through env var %s to singularity", e)
envs = append(envs, e)
}
}
}
return envs
}