@@ -13,8 +13,10 @@ import (
13
13
"path/filepath"
14
14
"strings"
15
15
"sync"
16
+ "strconv"
16
17
"syscall"
17
18
19
+ "github.com/sirupsen/logrus"
18
20
"github.com/containers/storage/pkg/unshare"
19
21
)
20
22
@@ -101,6 +103,8 @@ func stick(f string) error {
101
103
var (
102
104
rootlessConfigHomeDirOnce sync.Once
103
105
rootlessConfigHomeDir string
106
+ rootlessRuntimeDirOnce sync.Once
107
+ rootlessRuntimeDir string
104
108
)
105
109
106
110
// GetRootlessConfigHomeDir returns the config home directory when running as non root
@@ -131,3 +135,62 @@ func GetRootlessConfigHomeDir() (string, error) {
131
135
132
136
return rootlessConfigHomeDir , nil
133
137
}
138
+
139
+ // GetRuntimeDirUser returns the runtime directory
140
+ func GetRuntimeDirUser (rootless bool , rootlessUID int ) (string , error ) {
141
+ var rootlessRuntimeDirError error
142
+
143
+ if ! rootless {
144
+ return "" , nil
145
+ }
146
+
147
+ rootlessRuntimeDirOnce .Do (func () {
148
+ runtimeDir := os .Getenv ("XDG_RUNTIME_DIR" )
149
+
150
+ if runtimeDir != "" {
151
+ rootlessRuntimeDir , rootlessRuntimeDirError = filepath .EvalSymlinks (runtimeDir )
152
+ return
153
+ }
154
+
155
+ uid := strconv .Itoa (rootlessUID )
156
+ if runtimeDir == "" {
157
+ tmpDir := filepath .Join ("/run" , "user" , uid )
158
+ if err := os .MkdirAll (tmpDir , 0700 ); err != nil {
159
+ logrus .Debug (err )
160
+ }
161
+ st , err := os .Stat (tmpDir )
162
+ if err == nil && int (st .Sys ().(* syscall.Stat_t ).Uid ) == os .Geteuid () && (st .Mode ().Perm ()& 0700 == 0700 ) {
163
+ runtimeDir = tmpDir
164
+ }
165
+ }
166
+ if runtimeDir == "" {
167
+ tmpDir := filepath .Join (os .TempDir (), fmt .Sprintf ("storage-run-%s" , uid ))
168
+ if err := os .MkdirAll (tmpDir , 0700 ); err != nil {
169
+ logrus .Debug (err )
170
+ }
171
+ st , err := os .Stat (tmpDir )
172
+ if err == nil && int (st .Sys ().(* syscall.Stat_t ).Uid ) == os .Geteuid () && (st .Mode ().Perm ()& 0700 == 0700 ) {
173
+ runtimeDir = tmpDir
174
+ }
175
+ }
176
+ if runtimeDir == "" {
177
+ home := os .Getenv ("HOME" )
178
+ if home == "" {
179
+ rootlessRuntimeDirError = errors .New ("neither XDG_RUNTIME_DIR nor HOME was set non-empty" )
180
+ return
181
+ }
182
+ resolvedHome , err := filepath .EvalSymlinks (home )
183
+ if err != nil {
184
+ rootlessRuntimeDirError = fmt .Errorf ("cannot resolve %s: %w" , home , err )
185
+ return
186
+ }
187
+ runtimeDir = filepath .Join (resolvedHome , "rundir" )
188
+ }
189
+ rootlessRuntimeDir = runtimeDir
190
+ })
191
+
192
+ if rootlessRuntimeDirError != nil {
193
+ return "" , rootlessRuntimeDirError
194
+ }
195
+ return rootlessRuntimeDir , nil
196
+ }
0 commit comments