Skip to content

Commit 0e6a96b

Browse files
committed
pkg/homedir: enhance GetRuntimeDir()
copy the version from Podman. [NO NEW TESTS NEEDED] moved from Podman Signed-off-by: Giuseppe Scrivano <[email protected]>
1 parent 61c1ece commit 0e6a96b

File tree

1 file changed

+52
-13
lines changed

1 file changed

+52
-13
lines changed

pkg/homedir/homedir_unix.go

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,16 @@ package homedir
77
// NOTE: this package has originally been copied from github.com/docker/docker.
88

99
import (
10-
"errors"
1110
"fmt"
1211
"os"
1312
"path/filepath"
13+
"strconv"
1414
"strings"
1515
"sync"
1616
"syscall"
1717

1818
"github.com/containers/storage/pkg/unshare"
19+
"github.com/sirupsen/logrus"
1920
)
2021

2122
// Key returns the env var name for the user's home dir based on
@@ -43,18 +44,6 @@ func GetShortcutString() string {
4344
return "~"
4445
}
4546

46-
// GetRuntimeDir returns XDG_RUNTIME_DIR.
47-
// XDG_RUNTIME_DIR is typically configured via pam_systemd.
48-
// GetRuntimeDir returns non-nil error if XDG_RUNTIME_DIR is not set.
49-
//
50-
// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
51-
func GetRuntimeDir() (string, error) {
52-
if xdgRuntimeDir := os.Getenv("XDG_RUNTIME_DIR"); xdgRuntimeDir != "" {
53-
return filepath.EvalSymlinks(xdgRuntimeDir)
54-
}
55-
return "", errors.New("could not get XDG_RUNTIME_DIR")
56-
}
57-
5847
// StickRuntimeDirContents sets the sticky bit on files that are under
5948
// XDG_RUNTIME_DIR, so that the files won't be periodically removed by the system.
6049
//
@@ -102,6 +91,8 @@ var (
10291
rootlessConfigHomeDirError error
10392
rootlessConfigHomeDirOnce sync.Once
10493
rootlessConfigHomeDir string
94+
rootlessRuntimeDirOnce sync.Once
95+
rootlessRuntimeDir string
10596
)
10697

10798
// isWriteableOnlyByOwner checks that the specified permission mask allows write
@@ -139,3 +130,51 @@ func GetConfigHome() (string, error) {
139130

140131
return rootlessConfigHomeDir, rootlessConfigHomeDirError
141132
}
133+
134+
// GetRuntimeDir returns a directory suitable to store runtime files.
135+
// The function will try to use the XDG_RUNTIME_DIR env variable if it is set.
136+
// XDG_RUNTIME_DIR is typically configured via pam_systemd.
137+
// If XDG_RUNTIME_DIR is not set, GetRuntimeDir will try to find a suitable
138+
// directory for the current user.
139+
//
140+
// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
141+
func GetRuntimeDir() (string, error) {
142+
var rootlessRuntimeDirError error
143+
144+
rootlessRuntimeDirOnce.Do(func() {
145+
runtimeDir := os.Getenv("XDG_RUNTIME_DIR")
146+
147+
if runtimeDir != "" {
148+
rootlessRuntimeDir, rootlessRuntimeDirError = filepath.EvalSymlinks(runtimeDir)
149+
return
150+
}
151+
152+
uid := strconv.Itoa(unshare.GetRootlessUID())
153+
if runtimeDir == "" {
154+
tmpDir := filepath.Join("/run", "user", uid)
155+
if err := os.MkdirAll(tmpDir, 0o700); err != nil {
156+
logrus.Debug(err)
157+
}
158+
st, err := os.Lstat(tmpDir)
159+
if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && isWriteableOnlyByOwner(st.Mode().Perm()) {
160+
runtimeDir = tmpDir
161+
}
162+
}
163+
if runtimeDir == "" {
164+
tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("storage-run-%s", uid))
165+
if err := os.MkdirAll(tmpDir, 0o700); err != nil {
166+
logrus.Debug(err)
167+
}
168+
st, err := os.Lstat(tmpDir)
169+
if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && isWriteableOnlyByOwner(st.Mode().Perm()) {
170+
runtimeDir = tmpDir
171+
} else {
172+
rootlessRuntimeDirError = fmt.Errorf("path %q exists and it is not writeable only by the current user", tmpDir)
173+
return
174+
}
175+
}
176+
rootlessRuntimeDir = runtimeDir
177+
})
178+
179+
return rootlessRuntimeDir, rootlessRuntimeDirError
180+
}

0 commit comments

Comments
 (0)