Skip to content

Commit 8b40e07

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 6481f48 commit 8b40e07

File tree

1 file changed

+52
-12
lines changed

1 file changed

+52
-12
lines changed

pkg/homedir/homedir_unix.go

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ import (
1010
"fmt"
1111
"os"
1212
"path/filepath"
13+
"strconv"
1314
"strings"
1415
"sync"
1516
"syscall"
1617

1718
"github.com/containers/storage/pkg/unshare"
19+
"github.com/sirupsen/logrus"
1820
)
1921

2022
// Key returns the env var name for the user's home dir based on
@@ -42,18 +44,6 @@ func GetShortcutString() string {
4244
return "~"
4345
}
4446

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

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

139131
return rootlessConfigHomeDir, rootlessConfigHomeDirError
140132
}
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)