mirror of
https://github.com/containers/podman.git
synced 2025-06-18 07:28:57 +08:00
Update vendor of container/storage
Lots of fixes for issues found by podman. overlay: propagate errors from mountProgram utils: root in a userns uses global conf file Fix handling of additional stores Correctly check permissions on rootless directory Fix possible integer overflow on 32bit builds Evaluate device path for lvm lockfile test: make concurrent RW test determinisitc lockfile test: make concurrent read tests deterministic Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
@ -19,7 +19,7 @@ github.com/containers/image v1.5.1
|
|||||||
github.com/vbauerster/mpb v3.3.4
|
github.com/vbauerster/mpb v3.3.4
|
||||||
github.com/mattn/go-isatty v0.0.4
|
github.com/mattn/go-isatty v0.0.4
|
||||||
github.com/VividCortex/ewma v1.1.1
|
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/containers/psgo v1.2
|
||||||
github.com/coreos/go-systemd v14
|
github.com/coreos/go-systemd v14
|
||||||
github.com/cri-o/ocicni 0c180f981b27ef6036fa5be29bcb4dd666e406eb
|
github.com/cri-o/ocicni 0c180f981b27ef6036fa5be29bcb4dd666e406eb
|
||||||
|
2
vendor/github.com/containers/storage/containers_ffjson.go
generated
vendored
2
vendor/github.com/containers/storage/containers_ffjson.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
// Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT.
|
// Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT.
|
||||||
// source: ./containers.go
|
// source: containers.go
|
||||||
|
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// +build linux
|
// +build cgo
|
||||||
|
|
||||||
package copy
|
package copy
|
||||||
|
|
||||||
@ -153,8 +153,8 @@ func DirCopy(srcDir, dstDir string, copyMode Mode, copyXattrs bool) error {
|
|||||||
|
|
||||||
isHardlink := false
|
isHardlink := false
|
||||||
|
|
||||||
switch f.Mode() & os.ModeType {
|
switch mode := f.Mode(); {
|
||||||
case 0: // Regular file
|
case mode.IsRegular():
|
||||||
id := fileID{dev: stat.Dev, ino: stat.Ino}
|
id := fileID{dev: stat.Dev, ino: stat.Ino}
|
||||||
if copyMode == Hardlink {
|
if copyMode == Hardlink {
|
||||||
isHardlink = true
|
isHardlink = true
|
||||||
@ -172,12 +172,12 @@ func DirCopy(srcDir, dstDir string, copyMode Mode, copyXattrs bool) error {
|
|||||||
copiedFiles[id] = dstPath
|
copiedFiles[id] = dstPath
|
||||||
}
|
}
|
||||||
|
|
||||||
case os.ModeDir:
|
case mode.IsDir():
|
||||||
if err := os.Mkdir(dstPath, f.Mode()); err != nil && !os.IsExist(err) {
|
if err := os.Mkdir(dstPath, f.Mode()); err != nil && !os.IsExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
case os.ModeSymlink:
|
case mode&os.ModeSymlink != 0:
|
||||||
link, err := os.Readlink(srcPath)
|
link, err := os.Readlink(srcPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -187,14 +187,15 @@ func DirCopy(srcDir, dstDir string, copyMode Mode, copyXattrs bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
case os.ModeNamedPipe:
|
case mode&os.ModeNamedPipe != 0:
|
||||||
fallthrough
|
fallthrough
|
||||||
case os.ModeSocket:
|
|
||||||
|
case mode&os.ModeSocket != 0:
|
||||||
if err := unix.Mkfifo(dstPath, stat.Mode); err != nil {
|
if err := unix.Mkfifo(dstPath, stat.Mode); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
case os.ModeDevice:
|
case mode&os.ModeDevice != 0:
|
||||||
if rsystem.RunningInUserNS() {
|
if rsystem.RunningInUserNS() {
|
||||||
// cannot create a device if running in user namespace
|
// cannot create a device if running in user namespace
|
||||||
return nil
|
return nil
|
||||||
@ -204,7 +205,7 @@ func DirCopy(srcDir, dstDir string, copyMode Mode, copyXattrs bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
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
|
// Everything below is copying metadata from src to dst. All this metadata
|
19
vendor/github.com/containers/storage/drivers/copy/copy_unsupported.go
generated
vendored
Normal file
19
vendor/github.com/containers/storage/drivers/copy/copy_unsupported.go
generated
vendored
Normal file
@ -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)
|
||||||
|
}
|
13
vendor/github.com/containers/storage/drivers/devmapper/device_setup.go
generated
vendored
13
vendor/github.com/containers/storage/drivers/devmapper/device_setup.go
generated
vendored
@ -119,10 +119,17 @@ func checkDevHasFS(dev string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func verifyBlockDevice(dev string, force bool) 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
|
return err
|
||||||
}
|
}
|
||||||
if err := checkDevInVG(dev); err != nil {
|
if err := checkDevInVG(realPath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +137,7 @@ func verifyBlockDevice(dev string, force bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := checkDevHasFS(dev); err != nil {
|
if err := checkDevHasFS(realPath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
12
vendor/github.com/containers/storage/drivers/overlay/overlay.go
generated
vendored
12
vendor/github.com/containers/storage/drivers/overlay/overlay.go
generated
vendored
@ -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 := exec.Command(d.options.mountProgram, "-o", label, target)
|
||||||
mountProgram.Dir = d.home
|
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 {
|
} else if len(mountData) > pageSize {
|
||||||
//FIXME: We need to figure out to get this to work with additional stores
|
//FIXME: We need to figure out to get this to work with additional stores
|
||||||
|
2
vendor/github.com/containers/storage/images_ffjson.go
generated
vendored
2
vendor/github.com/containers/storage/images_ffjson.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
// Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT.
|
// Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT.
|
||||||
// source: ./images.go
|
// source: images.go
|
||||||
|
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
|
15
vendor/github.com/containers/storage/lockfile.go
generated
vendored
15
vendor/github.com/containers/storage/lockfile.go
generated
vendored
@ -58,8 +58,17 @@ func GetROLockfile(path string) (Locker, error) {
|
|||||||
return getLockfile(path, true)
|
return getLockfile(path, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getLockfile is a helper for GetLockfile and GetROLockfile and returns Locker
|
// getLockfile returns a Locker object, possibly (depending on the platform)
|
||||||
// based on the path and read-only property.
|
// 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) {
|
func getLockfile(path string, ro bool) (Locker, error) {
|
||||||
lockfilesLock.Lock()
|
lockfilesLock.Lock()
|
||||||
defer lockfilesLock.Unlock()
|
defer lockfilesLock.Unlock()
|
||||||
@ -79,7 +88,7 @@ func getLockfile(path string, ro bool) (Locker, error) {
|
|||||||
}
|
}
|
||||||
return locker, nil
|
return locker, nil
|
||||||
}
|
}
|
||||||
locker, err := getLockFile(path, ro) // platform dependent locker
|
locker, err := createLockerForPath(path, ro) // platform-dependent locker
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
87
vendor/github.com/containers/storage/lockfile_unix.go
generated
vendored
87
vendor/github.com/containers/storage/lockfile_unix.go
generated
vendored
@ -13,34 +13,6 @@ import (
|
|||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getLockFile(path string, ro bool) (Locker, error) {
|
|
||||||
var fd int
|
|
||||||
var err 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)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "error opening %q", path)
|
|
||||||
}
|
|
||||||
unix.CloseOnExec(fd)
|
|
||||||
|
|
||||||
locktype := unix.F_WRLCK
|
|
||||||
if ro {
|
|
||||||
locktype = unix.F_RDLCK
|
|
||||||
}
|
|
||||||
return &lockfile{
|
|
||||||
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 {
|
type lockfile struct {
|
||||||
// rwMutex serializes concurrent reader-writer acquisitions in the same process space
|
// rwMutex serializes concurrent reader-writer acquisitions in the same process space
|
||||||
rwMutex *sync.RWMutex
|
rwMutex *sync.RWMutex
|
||||||
@ -55,6 +27,52 @@ type lockfile struct {
|
|||||||
ro 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 {
|
||||||
|
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.Close(fd)
|
||||||
|
|
||||||
|
locktype := unix.F_WRLCK
|
||||||
|
if ro {
|
||||||
|
locktype = unix.F_RDLCK
|
||||||
|
}
|
||||||
|
return &lockfile{
|
||||||
|
stateMutex: &sync.Mutex{},
|
||||||
|
rwMutex: &sync.RWMutex{},
|
||||||
|
file: path,
|
||||||
|
lw: stringid.GenerateRandomID(),
|
||||||
|
locktype: int16(locktype),
|
||||||
|
locked: false,
|
||||||
|
ro: ro}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// lock locks the lockfile via FCTNL(2) based on the specified type and
|
// lock locks the lockfile via FCTNL(2) based on the specified type and
|
||||||
// command.
|
// command.
|
||||||
func (l *lockfile) lock(l_type int16) {
|
func (l *lockfile) lock(l_type int16) {
|
||||||
@ -63,7 +81,6 @@ func (l *lockfile) lock(l_type int16) {
|
|||||||
Whence: int16(os.SEEK_SET),
|
Whence: int16(os.SEEK_SET),
|
||||||
Start: 0,
|
Start: 0,
|
||||||
Len: 0,
|
Len: 0,
|
||||||
Pid: int32(os.Getpid()),
|
|
||||||
}
|
}
|
||||||
switch l_type {
|
switch l_type {
|
||||||
case unix.F_RDLCK:
|
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))
|
panic(fmt.Sprintf("attempted to acquire a file lock of unrecognized type %d", l_type))
|
||||||
}
|
}
|
||||||
l.stateMutex.Lock()
|
l.stateMutex.Lock()
|
||||||
|
defer l.stateMutex.Unlock()
|
||||||
if l.counter == 0 {
|
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
|
// Optimization: only use the (expensive) fcntl syscall when
|
||||||
// the counter is 0. In this case, we're either the first
|
// the counter is 0. In this case, we're either the first
|
||||||
// reader lock or a writer lock.
|
// reader lock or a writer lock.
|
||||||
@ -85,7 +111,6 @@ func (l *lockfile) lock(l_type int16) {
|
|||||||
l.locktype = l_type
|
l.locktype = l_type
|
||||||
l.locked = true
|
l.locked = true
|
||||||
l.counter++
|
l.counter++
|
||||||
l.stateMutex.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock locks the lockfile as a writer. Note that RLock() will be called if
|
// 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 {
|
for unix.FcntlFlock(l.fd, unix.F_SETLKW, &lk) != nil {
|
||||||
time.Sleep(10 * time.Millisecond)
|
time.Sleep(10 * time.Millisecond)
|
||||||
}
|
}
|
||||||
|
// Close the file descriptor on the last unlock.
|
||||||
|
unix.Close(int(l.fd))
|
||||||
}
|
}
|
||||||
if l.locktype == unix.F_RDLCK {
|
if l.locktype == unix.F_RDLCK {
|
||||||
l.rwMutex.RUnlock()
|
l.rwMutex.RUnlock()
|
||||||
|
15
vendor/github.com/containers/storage/lockfile_windows.go
generated
vendored
15
vendor/github.com/containers/storage/lockfile_windows.go
generated
vendored
@ -8,7 +8,20 @@ import (
|
|||||||
"time"
|
"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
|
return &lockfile{locked: false}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
vendor/github.com/containers/storage/pkg/idtools/parser.go
generated
vendored
11
vendor/github.com/containers/storage/pkg/idtools/parser.go
generated
vendored
@ -2,6 +2,8 @@ package idtools
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"math/bits"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@ -31,10 +33,11 @@ func parseTriple(spec []string) (container, host, size uint32, err error) {
|
|||||||
|
|
||||||
// ParseIDMap parses idmap triples from string.
|
// ParseIDMap parses idmap triples from string.
|
||||||
func ParseIDMap(mapSpec []string, mapSetting string) (idmap []IDMap, err error) {
|
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 {
|
for _, idMapSpec := range mapSpec {
|
||||||
idSpec := strings.Fields(strings.Map(nonDigitsToWhitespace, idMapSpec))
|
idSpec := strings.Fields(strings.Map(nonDigitsToWhitespace, idMapSpec))
|
||||||
if len(idSpec)%3 != 0 {
|
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 {
|
for i := range idSpec {
|
||||||
if i%3 != 0 {
|
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])
|
cid, hid, size, err := parseTriple(idSpec[i : i+3])
|
||||||
if err != nil {
|
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{
|
mapping := IDMap{
|
||||||
ContainerID: int(cid),
|
ContainerID: int(cid),
|
||||||
|
29
vendor/github.com/containers/storage/store.go
generated
vendored
29
vendor/github.com/containers/storage/store.go
generated
vendored
@ -460,6 +460,9 @@ type Store interface {
|
|||||||
// Version returns version information, in the form of key-value pairs, from
|
// Version returns version information, in the form of key-value pairs, from
|
||||||
// the storage package.
|
// the storage package.
|
||||||
Version() ([][2]string, error)
|
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
|
// IDMappingOptions are used for specifying how ID mapping should be set up for
|
||||||
@ -529,6 +532,7 @@ type store struct {
|
|||||||
imageStore ImageStore
|
imageStore ImageStore
|
||||||
roImageStores []ROImageStore
|
roImageStores []ROImageStore
|
||||||
containerStore ContainerStore
|
containerStore ContainerStore
|
||||||
|
digestLockRoot string
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStore attempts to find an already-created Store object matching the
|
// GetStore attempts to find an already-created Store object matching the
|
||||||
@ -698,9 +702,20 @@ func (s *store) load() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.containerStore = rcs
|
s.containerStore = rcs
|
||||||
|
|
||||||
|
s.digestLockRoot = filepath.Join(s.runRoot, driverPrefix+"locks")
|
||||||
|
if err := os.MkdirAll(s.digestLockRoot, 0700); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
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) {
|
func (s *store) getGraphDriver() (drivers.Driver, error) {
|
||||||
if s.graphDriver != nil {
|
if s.graphDriver != nil {
|
||||||
return 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)
|
return reflect.DeepEqual(layer.UIDMap, options.UIDMap) && reflect.DeepEqual(layer.GIDMap, options.GIDMap)
|
||||||
}
|
}
|
||||||
var layer, parentLayer *Layer
|
var layer, parentLayer *Layer
|
||||||
|
allStores := append([]ROLayerStore{rlstore}, lstores...)
|
||||||
// Locate the image's top layer and its parent, if it has one.
|
// 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
|
store := s
|
||||||
if store != rlstore {
|
if store != rlstore {
|
||||||
store.Lock()
|
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.
|
// We want the layer's parent, too, if it has one.
|
||||||
var cParentLayer *Layer
|
var cParentLayer *Layer
|
||||||
if cLayer.Parent != "" {
|
if cLayer.Parent != "" {
|
||||||
// Its parent should be around here, somewhere.
|
// Its parent should be in one of the stores, somewhere.
|
||||||
if cParentLayer, err = store.Get(cLayer.Parent); err != nil {
|
for _, ps := range allStores {
|
||||||
// Nope, couldn't find it. We're not going to be able
|
if cParentLayer, err = ps.Get(cLayer.Parent); err == nil {
|
||||||
// to diff this one properly.
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cParentLayer == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
24
vendor/github.com/containers/storage/utils.go
generated
vendored
24
vendor/github.com/containers/storage/utils.go
generated
vendored
@ -6,6 +6,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
@ -73,7 +74,7 @@ func GetRootlessRuntimeDir(rootlessUid int) (string, error) {
|
|||||||
if runtimeDir == "" {
|
if runtimeDir == "" {
|
||||||
tmpDir := fmt.Sprintf("/run/user/%d", rootlessUid)
|
tmpDir := fmt.Sprintf("/run/user/%d", rootlessUid)
|
||||||
st, err := system.Stat(tmpDir)
|
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
|
return tmpDir, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -158,6 +159,21 @@ func getTomlStorage(storeOptions *StoreOptions) *tomlConfig {
|
|||||||
return config
|
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
|
// DefaultStoreOptions returns the default storage ops for containers
|
||||||
func DefaultStoreOptions(rootless bool, rootlessUid int) (StoreOptions, error) {
|
func DefaultStoreOptions(rootless bool, rootlessUid int) (StoreOptions, error) {
|
||||||
var (
|
var (
|
||||||
@ -166,14 +182,14 @@ func DefaultStoreOptions(rootless bool, rootlessUid int) (StoreOptions, error) {
|
|||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
storageOpts := defaultStoreOptions
|
storageOpts := defaultStoreOptions
|
||||||
if rootless {
|
if rootless && rootlessUid != 0 {
|
||||||
storageOpts, err = getRootlessStorageOpts(rootlessUid)
|
storageOpts, err = getRootlessStorageOpts(rootlessUid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return storageOpts, err
|
return storageOpts, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
storageConf, err := DefaultConfigFile(rootless)
|
storageConf, err := DefaultConfigFile(rootless && rootlessUid != 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return storageOpts, err
|
return storageOpts, err
|
||||||
}
|
}
|
||||||
@ -188,7 +204,7 @@ func DefaultStoreOptions(rootless bool, rootlessUid int) (StoreOptions, error) {
|
|||||||
return storageOpts, errors.Wrapf(err, "cannot stat %s", storageConf)
|
return storageOpts, errors.Wrapf(err, "cannot stat %s", storageConf)
|
||||||
}
|
}
|
||||||
|
|
||||||
if rootless {
|
if rootless && rootlessUid != 0 {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// If the file did not specify a graphroot or runroot,
|
// If the file did not specify a graphroot or runroot,
|
||||||
// set sane defaults so we don't try and use root-owned
|
// set sane defaults so we don't try and use root-owned
|
||||||
|
Reference in New Issue
Block a user