summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--README.md6
-rw-r--r--test/system/005-info.bats4
-rw-r--r--test/system/030-run.bats2
-rw-r--r--test/system/035-logs.bats2
-rw-r--r--test/system/070-build.bats6
-rw-r--r--test/system/400-unprivileged-access.bats8
-rw-r--r--vendor.conf2
-rw-r--r--vendor/github.com/containers/storage/containers_ffjson.go2
-rw-r--r--vendor/github.com/containers/storage/drivers/copy/copy_linux.go (renamed from vendor/github.com/containers/storage/drivers/copy/copy.go)19
-rw-r--r--vendor/github.com/containers/storage/drivers/copy/copy_unsupported.go19
-rw-r--r--vendor/github.com/containers/storage/drivers/devmapper/device_setup.go13
-rw-r--r--vendor/github.com/containers/storage/drivers/overlay/overlay.go12
-rw-r--r--vendor/github.com/containers/storage/images_ffjson.go2
-rw-r--r--vendor/github.com/containers/storage/lockfile.go15
-rw-r--r--vendor/github.com/containers/storage/lockfile_unix.go75
-rw-r--r--vendor/github.com/containers/storage/lockfile_windows.go15
-rw-r--r--vendor/github.com/containers/storage/pkg/idtools/parser.go11
-rw-r--r--vendor/github.com/containers/storage/store.go29
-rw-r--r--vendor/github.com/containers/storage/utils.go24
20 files changed, 209 insertions, 63 deletions
diff --git a/Makefile b/Makefile
index ebd0ddf2d..1990c2d11 100644
--- a/Makefile
+++ b/Makefile
@@ -152,6 +152,12 @@ libpodimage: ## Build the libpod image
dbuild: libpodimage
${CONTAINER_RUNTIME} run --name=${LIBPOD_INSTANCE} --privileged -v ${PWD}:/go/src/${PROJECT} --rm ${LIBPOD_IMAGE} make all
+dbuild-podman-remote: libpodimage
+ ${CONTAINER_RUNTIME} run --name=${LIBPOD_INSTANCE} --privileged -v ${PWD}:/go/src/${PROJECT} --rm ${LIBPOD_IMAGE} go build -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS) remoteclient" -o bin/podman-remote $(PROJECT)/cmd/podman
+
+dbuild-podman-remote-darwin: libpodimage
+ ${CONTAINER_RUNTIME} run --name=${LIBPOD_INSTANCE} --privileged -v ${PWD}:/go/src/${PROJECT} --rm ${LIBPOD_IMAGE} env GOOS=darwin go build -ldflags '$(LDFLAGS_PODMAN)' -tags "remoteclient containers_image_openpgp exclude_graphdriver_devicemapper" -o bin/podman-remote-darwin $(PROJECT)/cmd/podman
+
test: libpodimage ## Run tests on built image
${CONTAINER_RUNTIME} run -e STORAGE_OPTIONS="--storage-driver=vfs" -e TESTFLAGS -e OCI_RUNTIME -e CGROUP_MANAGER=cgroupfs -e TRAVIS -t --privileged --rm -v ${CURDIR}:/go/src/${PROJECT} ${LIBPOD_IMAGE} make clean all localunit install.catatonit localintegration
diff --git a/README.md b/README.md
index 73a7057ea..da516fa0d 100644
--- a/README.md
+++ b/README.md
@@ -45,7 +45,11 @@ This project tests all builds against each supported version of Fedora, the late
Podman can also generate Kubernetes YAML based on a container or Pod (see
[podman-generate-kube](https://github.com/containers/libpod/blob/master/docs/podman-generate-kube.1.md)),
which allows for an easy transition from a local development environment
- to a production Kubernetes cluster.
+ to a production Kubernetes cluster. If Kubernetes does not fit your requirements,
+ there are other third-party tools that support the docker-compose format such as
+ [kompose](https://github.com/kubernetes/kompose/) and
+ [podman-compose](https://github.com/muayyad-alsadi/podman-compose)
+ that might be appropriate for your environment.
## OCI Projects Plans
diff --git a/test/system/005-info.bats b/test/system/005-info.bats
index c64b011bd..47c7a52fc 100644
--- a/test/system/005-info.bats
+++ b/test/system/005-info.bats
@@ -3,7 +3,7 @@
load helpers
@test "podman info - basic test" {
- skip_if_remote
+ skip_if_remote "capitalization inconsistencies"
run_podman info
@@ -28,7 +28,7 @@ RunRoot:
}
@test "podman info - json" {
- skip_if_remote
+ skip_if_remote "capitalization inconsistencies"
run_podman info --format=json
diff --git a/test/system/030-run.bats b/test/system/030-run.bats
index bdbe724ef..a29b1adc3 100644
--- a/test/system/030-run.bats
+++ b/test/system/030-run.bats
@@ -3,8 +3,6 @@
load helpers
@test "podman run - basic tests" {
- skip_if_remote
-
rand=$(random_string 30)
tests="
true | 0 |
diff --git a/test/system/035-logs.bats b/test/system/035-logs.bats
index 5736e0939..055865c8d 100644
--- a/test/system/035-logs.bats
+++ b/test/system/035-logs.bats
@@ -6,8 +6,6 @@
load helpers
@test "podman logs - basic test" {
- skip_if_remote
-
rand_string=$(random_string 40)
run_podman create $IMAGE echo $rand_string
diff --git a/test/system/070-build.bats b/test/system/070-build.bats
index c6a25093f..53acf6edd 100644
--- a/test/system/070-build.bats
+++ b/test/system/070-build.bats
@@ -6,7 +6,11 @@
load helpers
@test "podman build - basic test" {
- skip_if_remote
+ if [[ "$PODMAN" =~ -remote ]]; then
+ if [ "$(id -u)" -ne 0 ]; then
+ skip "unreliable with podman-remote and rootless; #2972"
+ fi
+ fi
rand_filename=$(random_string 20)
rand_content=$(random_string 50)
diff --git a/test/system/400-unprivileged-access.bats b/test/system/400-unprivileged-access.bats
index 0358b3beb..738d8d87b 100644
--- a/test/system/400-unprivileged-access.bats
+++ b/test/system/400-unprivileged-access.bats
@@ -31,6 +31,12 @@ die() {
echo "#| FAIL: $*" >&2
echo "#\\^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" >&2
+ # Show permissions of directories from here on up
+ while expr "$path" : "/var/lib/containers" >/dev/null; do
+ echo "#| $(ls -ld $path)"
+ path=$(dirname $path)
+ done
+
exit 1
}
@@ -65,8 +71,10 @@ EOF
# get podman image and container storage directories
run_podman info --format '{{.store.GraphRoot}}'
+ is "$output" "/var/lib/containers/storage" "GraphRoot in expected place"
GRAPH_ROOT="$output"
run_podman info --format '{{.store.RunRoot}}'
+ is "$output" "/var/run/containers/storage" "RunRoot in expected place"
RUN_ROOT="$output"
# The main test: find all world-writable files or directories underneath
diff --git a/vendor.conf b/vendor.conf
index 886e4794a..6ec2c9d1c 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -19,7 +19,7 @@ github.com/containers/image v1.5.1
github.com/vbauerster/mpb v3.3.4
github.com/mattn/go-isatty v0.0.4
github.com/VividCortex/ewma v1.1.1
-github.com/containers/storage v1.12.1
+github.com/containers/storage v1.12.3
github.com/containers/psgo v1.2
github.com/coreos/go-systemd v14
github.com/cri-o/ocicni 0c180f981b27ef6036fa5be29bcb4dd666e406eb
diff --git a/vendor/github.com/containers/storage/containers_ffjson.go b/vendor/github.com/containers/storage/containers_ffjson.go
index 40b912bb3..aef6becfe 100644
--- a/vendor/github.com/containers/storage/containers_ffjson.go
+++ b/vendor/github.com/containers/storage/containers_ffjson.go
@@ -1,5 +1,5 @@
// Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT.
-// source: ./containers.go
+// source: containers.go
package storage
diff --git a/vendor/github.com/containers/storage/drivers/copy/copy.go b/vendor/github.com/containers/storage/drivers/copy/copy_linux.go
index bcbc61284..d614b78fc 100644
--- a/vendor/github.com/containers/storage/drivers/copy/copy.go
+++ b/vendor/github.com/containers/storage/drivers/copy/copy_linux.go
@@ -1,4 +1,4 @@
-// +build linux
+// +build cgo
package copy
@@ -153,8 +153,8 @@ func DirCopy(srcDir, dstDir string, copyMode Mode, copyXattrs bool) error {
isHardlink := false
- switch f.Mode() & os.ModeType {
- case 0: // Regular file
+ switch mode := f.Mode(); {
+ case mode.IsRegular():
id := fileID{dev: stat.Dev, ino: stat.Ino}
if copyMode == Hardlink {
isHardlink = true
@@ -172,12 +172,12 @@ func DirCopy(srcDir, dstDir string, copyMode Mode, copyXattrs bool) error {
copiedFiles[id] = dstPath
}
- case os.ModeDir:
+ case mode.IsDir():
if err := os.Mkdir(dstPath, f.Mode()); err != nil && !os.IsExist(err) {
return err
}
- case os.ModeSymlink:
+ case mode&os.ModeSymlink != 0:
link, err := os.Readlink(srcPath)
if err != nil {
return err
@@ -187,14 +187,15 @@ func DirCopy(srcDir, dstDir string, copyMode Mode, copyXattrs bool) error {
return err
}
- case os.ModeNamedPipe:
+ case mode&os.ModeNamedPipe != 0:
fallthrough
- case os.ModeSocket:
+
+ case mode&os.ModeSocket != 0:
if err := unix.Mkfifo(dstPath, stat.Mode); err != nil {
return err
}
- case os.ModeDevice:
+ case mode&os.ModeDevice != 0:
if rsystem.RunningInUserNS() {
// cannot create a device if running in user namespace
return nil
@@ -204,7 +205,7 @@ func DirCopy(srcDir, dstDir string, copyMode Mode, copyXattrs bool) error {
}
default:
- return fmt.Errorf("unknown file type for %s", srcPath)
+ return fmt.Errorf("unknown file type with mode %v for %s", mode, srcPath)
}
// Everything below is copying metadata from src to dst. All this metadata
diff --git a/vendor/github.com/containers/storage/drivers/copy/copy_unsupported.go b/vendor/github.com/containers/storage/drivers/copy/copy_unsupported.go
new file mode 100644
index 000000000..4d44f2f35
--- /dev/null
+++ b/vendor/github.com/containers/storage/drivers/copy/copy_unsupported.go
@@ -0,0 +1,19 @@
+// +build !linux !cgo
+
+package copy
+
+import "github.com/containers/storage/pkg/chrootarchive"
+
+// Mode indicates whether to use hardlink or copy content
+type Mode int
+
+const (
+ // Content creates a new file, and copies the content of the file
+ Content Mode = iota
+)
+
+// DirCopy copies or hardlinks the contents of one directory to another,
+// properly handling soft links
+func DirCopy(srcDir, dstDir string, _ Mode, _ bool) error {
+ return chrootarchive.NewArchiver(nil).CopyWithTar(srcDir, dstDir)
+}
diff --git a/vendor/github.com/containers/storage/drivers/devmapper/device_setup.go b/vendor/github.com/containers/storage/drivers/devmapper/device_setup.go
index 58abca477..f63845252 100644
--- a/vendor/github.com/containers/storage/drivers/devmapper/device_setup.go
+++ b/vendor/github.com/containers/storage/drivers/devmapper/device_setup.go
@@ -119,10 +119,17 @@ func checkDevHasFS(dev string) error {
}
func verifyBlockDevice(dev string, force bool) error {
- if err := checkDevAvailable(dev); err != nil {
+ realPath, err := filepath.Abs(dev)
+ if err != nil {
+ return errors.Errorf("unable to get absolute path for %s: %s", dev, err)
+ }
+ if realPath, err = filepath.EvalSymlinks(realPath); err != nil {
+ return errors.Errorf("failed to canonicalise path for %s: %s", dev, err)
+ }
+ if err := checkDevAvailable(realPath); err != nil {
return err
}
- if err := checkDevInVG(dev); err != nil {
+ if err := checkDevInVG(realPath); err != nil {
return err
}
@@ -130,7 +137,7 @@ func verifyBlockDevice(dev string, force bool) error {
return nil
}
- if err := checkDevHasFS(dev); err != nil {
+ if err := checkDevHasFS(realPath); err != nil {
return err
}
return nil
diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go
index 657d9b3ce..69036a5c1 100644
--- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go
+++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go
@@ -796,7 +796,17 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
mountProgram := exec.Command(d.options.mountProgram, "-o", label, target)
mountProgram.Dir = d.home
- return mountProgram.Run()
+ var b bytes.Buffer
+ mountProgram.Stderr = &b
+ err := mountProgram.Run()
+ if err != nil {
+ output := b.String()
+ if output == "" {
+ output = "<stderr empty>"
+ }
+ return errors.Wrapf(err, "using mount program %s: %s", d.options.mountProgram, output)
+ }
+ return nil
}
} else if len(mountData) > pageSize {
//FIXME: We need to figure out to get this to work with additional stores
diff --git a/vendor/github.com/containers/storage/images_ffjson.go b/vendor/github.com/containers/storage/images_ffjson.go
index 539acfe93..6b40ebd59 100644
--- a/vendor/github.com/containers/storage/images_ffjson.go
+++ b/vendor/github.com/containers/storage/images_ffjson.go
@@ -1,5 +1,5 @@
// Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT.
-// source: ./images.go
+// source: images.go
package storage
diff --git a/vendor/github.com/containers/storage/lockfile.go b/vendor/github.com/containers/storage/lockfile.go
index 3a1befcbe..ed8753337 100644
--- a/vendor/github.com/containers/storage/lockfile.go
+++ b/vendor/github.com/containers/storage/lockfile.go
@@ -58,8 +58,17 @@ func GetROLockfile(path string) (Locker, error) {
return getLockfile(path, true)
}
-// getLockfile is a helper for GetLockfile and GetROLockfile and returns Locker
-// based on the path and read-only property.
+// getLockfile returns a Locker object, possibly (depending on the platform)
+// working inter-process, and associated with the specified path.
+//
+// If ro, the lock is a read-write lock and the returned Locker should correspond to the
+// “lock for reading” (shared) operation; otherwise, the lock is either an exclusive lock,
+// or a read-write lock and Locker should correspond to the “lock for writing” (exclusive) operation.
+//
+// WARNING:
+// - The lock may or MAY NOT be inter-process.
+// - There may or MAY NOT be an actual object on the filesystem created for the specified path.
+// - Even if ro, the lock MAY be exclusive.
func getLockfile(path string, ro bool) (Locker, error) {
lockfilesLock.Lock()
defer lockfilesLock.Unlock()
@@ -79,7 +88,7 @@ func getLockfile(path string, ro bool) (Locker, error) {
}
return locker, nil
}
- locker, err := getLockFile(path, ro) // platform dependent locker
+ locker, err := createLockerForPath(path, ro) // platform-dependent locker
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/containers/storage/lockfile_unix.go b/vendor/github.com/containers/storage/lockfile_unix.go
index a9dc64122..8e0f22cb5 100644
--- a/vendor/github.com/containers/storage/lockfile_unix.go
+++ b/vendor/github.com/containers/storage/lockfile_unix.go
@@ -13,18 +13,51 @@ import (
"golang.org/x/sys/unix"
)
-func getLockFile(path string, ro bool) (Locker, error) {
- var fd int
- var err error
+type lockfile struct {
+ // rwMutex serializes concurrent reader-writer acquisitions in the same process space
+ rwMutex *sync.RWMutex
+ // stateMutex is used to synchronize concurrent accesses to the state below
+ stateMutex *sync.Mutex
+ counter int64
+ file string
+ fd uintptr
+ lw string
+ locktype int16
+ locked bool
+ ro bool
+}
+
+// openLock opens the file at path and returns the corresponding file
+// descriptor. Note that the path is opened read-only when ro is set. If ro
+// is unset, openLock will open the path read-write and create the file if
+// necessary.
+func openLock(path string, ro bool) (int, error) {
if ro {
- fd, err = unix.Open(path, os.O_RDONLY, 0)
- } else {
- fd, err = unix.Open(path, os.O_RDWR|os.O_CREATE, unix.S_IRUSR|unix.S_IWUSR)
+ return unix.Open(path, os.O_RDONLY, 0)
}
+ return unix.Open(path, os.O_RDWR|os.O_CREATE, unix.S_IRUSR|unix.S_IWUSR)
+}
+
+// createLockerForPath returns a Locker object, possibly (depending on the platform)
+// working inter-process and associated with the specified path.
+//
+// This function will be called at most once for each path value within a single process.
+//
+// If ro, the lock is a read-write lock and the returned Locker should correspond to the
+// “lock for reading” (shared) operation; otherwise, the lock is either an exclusive lock,
+// or a read-write lock and Locker should correspond to the “lock for writing” (exclusive) operation.
+//
+// WARNING:
+// - The lock may or MAY NOT be inter-process.
+// - There may or MAY NOT be an actual object on the filesystem created for the specified path.
+// - Even if ro, the lock MAY be exclusive.
+func createLockerForPath(path string, ro bool) (Locker, error) {
+ // Check if we can open the lock.
+ fd, err := openLock(path, ro)
if err != nil {
return nil, errors.Wrapf(err, "error opening %q", path)
}
- unix.CloseOnExec(fd)
+ unix.Close(fd)
locktype := unix.F_WRLCK
if ro {
@@ -34,27 +67,12 @@ func getLockFile(path string, ro bool) (Locker, error) {
stateMutex: &sync.Mutex{},
rwMutex: &sync.RWMutex{},
file: path,
- fd: uintptr(fd),
lw: stringid.GenerateRandomID(),
locktype: int16(locktype),
locked: false,
ro: ro}, nil
}
-type lockfile struct {
- // rwMutex serializes concurrent reader-writer acquisitions in the same process space
- rwMutex *sync.RWMutex
- // stateMutex is used to synchronize concurrent accesses to the state below
- stateMutex *sync.Mutex
- counter int64
- file string
- fd uintptr
- lw string
- locktype int16
- locked bool
- ro bool
-}
-
// lock locks the lockfile via FCTNL(2) based on the specified type and
// command.
func (l *lockfile) lock(l_type int16) {
@@ -63,7 +81,6 @@ func (l *lockfile) lock(l_type int16) {
Whence: int16(os.SEEK_SET),
Start: 0,
Len: 0,
- Pid: int32(os.Getpid()),
}
switch l_type {
case unix.F_RDLCK:
@@ -74,7 +91,16 @@ func (l *lockfile) lock(l_type int16) {
panic(fmt.Sprintf("attempted to acquire a file lock of unrecognized type %d", l_type))
}
l.stateMutex.Lock()
+ defer l.stateMutex.Unlock()
if l.counter == 0 {
+ // If we're the first reference on the lock, we need to open the file again.
+ fd, err := openLock(l.file, l.ro)
+ if err != nil {
+ panic(fmt.Sprintf("error opening %q", l.file))
+ }
+ unix.CloseOnExec(fd)
+ l.fd = uintptr(fd)
+
// Optimization: only use the (expensive) fcntl syscall when
// the counter is 0. In this case, we're either the first
// reader lock or a writer lock.
@@ -85,7 +111,6 @@ func (l *lockfile) lock(l_type int16) {
l.locktype = l_type
l.locked = true
l.counter++
- l.stateMutex.Unlock()
}
// Lock locks the lockfile as a writer. Note that RLock() will be called if
@@ -133,6 +158,8 @@ func (l *lockfile) Unlock() {
for unix.FcntlFlock(l.fd, unix.F_SETLKW, &lk) != nil {
time.Sleep(10 * time.Millisecond)
}
+ // Close the file descriptor on the last unlock.
+ unix.Close(int(l.fd))
}
if l.locktype == unix.F_RDLCK {
l.rwMutex.RUnlock()
diff --git a/vendor/github.com/containers/storage/lockfile_windows.go b/vendor/github.com/containers/storage/lockfile_windows.go
index a3821bfeb..c02069495 100644
--- a/vendor/github.com/containers/storage/lockfile_windows.go
+++ b/vendor/github.com/containers/storage/lockfile_windows.go
@@ -8,7 +8,20 @@ import (
"time"
)
-func getLockFile(path string, ro bool) (Locker, error) {
+// createLockerForPath returns a Locker object, possibly (depending on the platform)
+// working inter-process and associated with the specified path.
+//
+// This function will be called at most once for each path value within a single process.
+//
+// If ro, the lock is a read-write lock and the returned Locker should correspond to the
+// “lock for reading” (shared) operation; otherwise, the lock is either an exclusive lock,
+// or a read-write lock and Locker should correspond to the “lock for writing” (exclusive) operation.
+//
+// WARNING:
+// - The lock may or MAY NOT be inter-process.
+// - There may or MAY NOT be an actual object on the filesystem created for the specified path.
+// - Even if ro, the lock MAY be exclusive.
+func createLockerForPath(path string, ro bool) (Locker, error) {
return &lockfile{locked: false}, nil
}
diff --git a/vendor/github.com/containers/storage/pkg/idtools/parser.go b/vendor/github.com/containers/storage/pkg/idtools/parser.go
index c56aa86a2..86f98f16e 100644
--- a/vendor/github.com/containers/storage/pkg/idtools/parser.go
+++ b/vendor/github.com/containers/storage/pkg/idtools/parser.go
@@ -2,6 +2,8 @@ package idtools
import (
"fmt"
+ "math"
+ "math/bits"
"strconv"
"strings"
)
@@ -31,10 +33,11 @@ func parseTriple(spec []string) (container, host, size uint32, err error) {
// ParseIDMap parses idmap triples from string.
func ParseIDMap(mapSpec []string, mapSetting string) (idmap []IDMap, err error) {
+ stdErr := fmt.Errorf("error initializing ID mappings: %s setting is malformed", mapSetting)
for _, idMapSpec := range mapSpec {
idSpec := strings.Fields(strings.Map(nonDigitsToWhitespace, idMapSpec))
if len(idSpec)%3 != 0 {
- return nil, fmt.Errorf("error initializing ID mappings: %s setting is malformed", mapSetting)
+ return nil, stdErr
}
for i := range idSpec {
if i%3 != 0 {
@@ -42,7 +45,11 @@ func ParseIDMap(mapSpec []string, mapSetting string) (idmap []IDMap, err error)
}
cid, hid, size, err := parseTriple(idSpec[i : i+3])
if err != nil {
- return nil, fmt.Errorf("error initializing ID mappings: %s setting is malformed", mapSetting)
+ return nil, stdErr
+ }
+ // Avoid possible integer overflow on 32bit builds
+ if bits.UintSize == 32 && (cid > math.MaxInt32 || hid > math.MaxInt32 || size > math.MaxInt32) {
+ return nil, stdErr
}
mapping := IDMap{
ContainerID: int(cid),
diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go
index 7e39e3959..27b00f6fe 100644
--- a/vendor/github.com/containers/storage/store.go
+++ b/vendor/github.com/containers/storage/store.go
@@ -460,6 +460,9 @@ type Store interface {
// Version returns version information, in the form of key-value pairs, from
// the storage package.
Version() ([][2]string, error)
+
+ // GetDigestLock returns digest-specific Locker.
+ GetDigestLock(digest.Digest) (Locker, error)
}
// IDMappingOptions are used for specifying how ID mapping should be set up for
@@ -529,6 +532,7 @@ type store struct {
imageStore ImageStore
roImageStores []ROImageStore
containerStore ContainerStore
+ digestLockRoot string
}
// GetStore attempts to find an already-created Store object matching the
@@ -698,9 +702,20 @@ func (s *store) load() error {
return err
}
s.containerStore = rcs
+
+ s.digestLockRoot = filepath.Join(s.runRoot, driverPrefix+"locks")
+ if err := os.MkdirAll(s.digestLockRoot, 0700); err != nil {
+ return err
+ }
+
return nil
}
+// GetDigestLock returns a digest-specific Locker.
+func (s *store) GetDigestLock(d digest.Digest) (Locker, error) {
+ return GetLockfile(filepath.Join(s.digestLockRoot, d.String()))
+}
+
func (s *store) getGraphDriver() (drivers.Driver, error) {
if s.graphDriver != nil {
return s.graphDriver, nil
@@ -1023,8 +1038,9 @@ func (s *store) imageTopLayerForMapping(image *Image, ristore ROImageStore, crea
return reflect.DeepEqual(layer.UIDMap, options.UIDMap) && reflect.DeepEqual(layer.GIDMap, options.GIDMap)
}
var layer, parentLayer *Layer
+ allStores := append([]ROLayerStore{rlstore}, lstores...)
// Locate the image's top layer and its parent, if it has one.
- for _, s := range append([]ROLayerStore{rlstore}, lstores...) {
+ for _, s := range allStores {
store := s
if store != rlstore {
store.Lock()
@@ -1041,10 +1057,13 @@ func (s *store) imageTopLayerForMapping(image *Image, ristore ROImageStore, crea
// We want the layer's parent, too, if it has one.
var cParentLayer *Layer
if cLayer.Parent != "" {
- // Its parent should be around here, somewhere.
- if cParentLayer, err = store.Get(cLayer.Parent); err != nil {
- // Nope, couldn't find it. We're not going to be able
- // to diff this one properly.
+ // Its parent should be in one of the stores, somewhere.
+ for _, ps := range allStores {
+ if cParentLayer, err = ps.Get(cLayer.Parent); err == nil {
+ break
+ }
+ }
+ if cParentLayer == nil {
continue
}
}
diff --git a/vendor/github.com/containers/storage/utils.go b/vendor/github.com/containers/storage/utils.go
index e74956c9e..6c9f163a3 100644
--- a/vendor/github.com/containers/storage/utils.go
+++ b/vendor/github.com/containers/storage/utils.go
@@ -6,6 +6,7 @@ import (
"os/exec"
"os/user"
"path/filepath"
+ "strconv"
"strings"
"github.com/BurntSushi/toml"
@@ -73,7 +74,7 @@ func GetRootlessRuntimeDir(rootlessUid int) (string, error) {
if runtimeDir == "" {
tmpDir := fmt.Sprintf("/run/user/%d", rootlessUid)
st, err := system.Stat(tmpDir)
- if err == nil && int(st.UID()) == os.Getuid() && st.Mode() == 0700 {
+ if err == nil && int(st.UID()) == os.Getuid() && st.Mode()&0700 == 0700 && st.Mode()&0066 == 0000 {
return tmpDir, nil
}
}
@@ -158,6 +159,21 @@ func getTomlStorage(storeOptions *StoreOptions) *tomlConfig {
return config
}
+func getRootlessUID() int {
+ uidEnv := os.Getenv("_CONTAINERS_ROOTLESS_UID")
+ if uidEnv != "" {
+ u, _ := strconv.Atoi(uidEnv)
+ return u
+ }
+ return os.Geteuid()
+}
+
+// DefaultStoreOptionsAutoDetectUID returns the default storage ops for containers
+func DefaultStoreOptionsAutoDetectUID() (StoreOptions, error) {
+ uid := getRootlessUID()
+ return DefaultStoreOptions(uid != 0, uid)
+}
+
// DefaultStoreOptions returns the default storage ops for containers
func DefaultStoreOptions(rootless bool, rootlessUid int) (StoreOptions, error) {
var (
@@ -166,14 +182,14 @@ func DefaultStoreOptions(rootless bool, rootlessUid int) (StoreOptions, error) {
err error
)
storageOpts := defaultStoreOptions
- if rootless {
+ if rootless && rootlessUid != 0 {
storageOpts, err = getRootlessStorageOpts(rootlessUid)
if err != nil {
return storageOpts, err
}
}
- storageConf, err := DefaultConfigFile(rootless)
+ storageConf, err := DefaultConfigFile(rootless && rootlessUid != 0)
if err != nil {
return storageOpts, err
}
@@ -188,7 +204,7 @@ func DefaultStoreOptions(rootless bool, rootlessUid int) (StoreOptions, error) {
return storageOpts, errors.Wrapf(err, "cannot stat %s", storageConf)
}
- if rootless {
+ if rootless && rootlessUid != 0 {
if err == nil {
// If the file did not specify a graphroot or runroot,
// set sane defaults so we don't try and use root-owned