Skip to content

Commit

Permalink
pkg/homedir: enhance GetRuntimeDir()
Browse files Browse the repository at this point in the history
copy the version from Podman.

[NO NEW TESTS NEEDED] moved from Podman

Signed-off-by: Giuseppe Scrivano <[email protected]>
  • Loading branch information
giuseppe committed Nov 15, 2023
1 parent 61c1ece commit 0e6a96b
Showing 1 changed file with 52 additions and 13 deletions.
65 changes: 52 additions & 13 deletions pkg/homedir/homedir_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ package homedir
// NOTE: this package has originally been copied from github.com/docker/docker.

import (
"errors"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"sync"
"syscall"

"github.com/containers/storage/pkg/unshare"
"github.com/sirupsen/logrus"
)

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

// GetRuntimeDir returns XDG_RUNTIME_DIR.
// XDG_RUNTIME_DIR is typically configured via pam_systemd.
// GetRuntimeDir returns non-nil error if XDG_RUNTIME_DIR is not set.
//
// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
func GetRuntimeDir() (string, error) {
if xdgRuntimeDir := os.Getenv("XDG_RUNTIME_DIR"); xdgRuntimeDir != "" {
return filepath.EvalSymlinks(xdgRuntimeDir)
}
return "", errors.New("could not get XDG_RUNTIME_DIR")
}

// StickRuntimeDirContents sets the sticky bit on files that are under
// XDG_RUNTIME_DIR, so that the files won't be periodically removed by the system.
//
Expand Down Expand Up @@ -102,6 +91,8 @@ var (
rootlessConfigHomeDirError error
rootlessConfigHomeDirOnce sync.Once
rootlessConfigHomeDir string
rootlessRuntimeDirOnce sync.Once
rootlessRuntimeDir string
)

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

return rootlessConfigHomeDir, rootlessConfigHomeDirError
}

// GetRuntimeDir returns a directory suitable to store runtime files.
// The function will try to use the XDG_RUNTIME_DIR env variable if it is set.
// XDG_RUNTIME_DIR is typically configured via pam_systemd.
// If XDG_RUNTIME_DIR is not set, GetRuntimeDir will try to find a suitable
// directory for the current user.
//
// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
func GetRuntimeDir() (string, error) {
var rootlessRuntimeDirError error

rootlessRuntimeDirOnce.Do(func() {
runtimeDir := os.Getenv("XDG_RUNTIME_DIR")

if runtimeDir != "" {
rootlessRuntimeDir, rootlessRuntimeDirError = filepath.EvalSymlinks(runtimeDir)
return
}

uid := strconv.Itoa(unshare.GetRootlessUID())
if runtimeDir == "" {
tmpDir := filepath.Join("/run", "user", uid)
if err := os.MkdirAll(tmpDir, 0o700); err != nil {
logrus.Debug(err)
}
st, err := os.Lstat(tmpDir)
if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && isWriteableOnlyByOwner(st.Mode().Perm()) {
runtimeDir = tmpDir
}
}
if runtimeDir == "" {
tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("storage-run-%s", uid))
if err := os.MkdirAll(tmpDir, 0o700); err != nil {
logrus.Debug(err)
}
st, err := os.Lstat(tmpDir)
if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && isWriteableOnlyByOwner(st.Mode().Perm()) {
runtimeDir = tmpDir
} else {
rootlessRuntimeDirError = fmt.Errorf("path %q exists and it is not writeable only by the current user", tmpDir)
return
}
}
rootlessRuntimeDir = runtimeDir
})

return rootlessRuntimeDir, rootlessRuntimeDirError
}

0 comments on commit 0e6a96b

Please sign in to comment.