File: default.go

package info (click to toggle)
golang-github-containers-image 5.28.0-4
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 5,104 kB
  • sloc: sh: 194; makefile: 73
file content (76 lines) | stat: -rw-r--r-- 3,187 bytes parent folder | download
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
package blobinfocache

import (
	"fmt"
	"os"
	"path/filepath"

	"github.com/containers/image/v5/internal/rootless"
	"github.com/containers/image/v5/pkg/blobinfocache/memory"
	"github.com/containers/image/v5/pkg/blobinfocache/sqlite"
	"github.com/containers/image/v5/types"
	"github.com/sirupsen/logrus"
)

const (
	// blobInfoCacheFilename is the file name used for blob info caches.
	// If the format changes in an incompatible way, increase the version number.
	blobInfoCacheFilename = "blob-info-cache-v1.sqlite"
	// systemBlobInfoCacheDir is the directory containing the blob info cache (in blobInfocacheFilename) for root-running processes.
	systemBlobInfoCacheDir = "/var/lib/containers/cache"
)

// blobInfoCacheDir returns a path to a blob info cache appropriate for sys and euid.
// euid is used so that (sudo …) does not write root-owned files into the unprivileged users’ home directory.
func blobInfoCacheDir(sys *types.SystemContext, euid int) (string, error) {
	if sys != nil && sys.BlobInfoCacheDir != "" {
		return sys.BlobInfoCacheDir, nil
	}

	// FIXME? On Windows, os.Geteuid() returns -1.  What should we do?  Right now we treat it as unprivileged
	// and fail (fall back to memory-only) if neither HOME nor XDG_DATA_HOME is set, which is, at least, safe.
	if euid == 0 {
		if sys != nil && sys.RootForImplicitAbsolutePaths != "" {
			return filepath.Join(sys.RootForImplicitAbsolutePaths, systemBlobInfoCacheDir), nil
		}
		return systemBlobInfoCacheDir, nil
	}

	// This is intended to mirror the GraphRoot determination in github.com/containers/libpod/pkg/util.GetRootlessStorageOpts.
	dataDir := os.Getenv("XDG_DATA_HOME")
	if dataDir == "" {
		home := os.Getenv("HOME")
		if home == "" {
			return "", fmt.Errorf("neither XDG_DATA_HOME nor HOME was set non-empty")
		}
		dataDir = filepath.Join(home, ".local", "share")
	}
	return filepath.Join(dataDir, "containers", "cache"), nil
}

// DefaultCache returns the default BlobInfoCache implementation appropriate for sys.
func DefaultCache(sys *types.SystemContext) types.BlobInfoCache {
	dir, err := blobInfoCacheDir(sys, rootless.GetRootlessEUID())
	if err != nil {
		logrus.Debugf("Error determining a location for %s, using a memory-only cache", blobInfoCacheFilename)
		return memory.New()
	}
	path := filepath.Join(dir, blobInfoCacheFilename)
	if err := os.MkdirAll(dir, 0700); err != nil {
		logrus.Debugf("Error creating parent directories for %s, using a memory-only cache: %v", path, err)
		return memory.New()
	}

	// It might make sense to keep a single sqlite cache object, and a single initialized sqlite connection, open
	// as global singleton, for the vast majority of callers who don’t override thde cache location.
	// OTOH that would keep a file descriptor open forever, even for long-term callers who copy images rarely,
	// and the performance benefit to this over using an Open()/Close() pair for a single image copy is < 10%.

	cache, err := sqlite.New(path)
	if err != nil {
		logrus.Debugf("Error creating a SQLite blob info cache at %s, using a memory-only cache: %v", path, err)
		return memory.New()
	}
	logrus.Debugf("Using SQLite blob info cache at %s", path)
	return cache
}