mirror of
https://github.com/containers/podman.git
synced 2025-10-18 11:42:55 +08:00
vendor: update containers/storage
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
2
vendor/github.com/containers/storage/.cirrus.yml
generated
vendored
2
vendor/github.com/containers/storage/.cirrus.yml
generated
vendored
@ -171,7 +171,7 @@ vendor_task:
|
||||
cross_task:
|
||||
alias: cross
|
||||
container:
|
||||
image: golang:1.21
|
||||
image: golang:1.22
|
||||
build_script: make cross
|
||||
|
||||
|
||||
|
2
vendor/github.com/containers/storage/Makefile
generated
vendored
2
vendor/github.com/containers/storage/Makefile
generated
vendored
@ -35,7 +35,7 @@ TESTFLAGS := $(shell $(GO) test -race $(BUILDFLAGS) ./pkg/stringutils 2>&1 > /de
|
||||
# N/B: This value is managed by Renovate, manual changes are
|
||||
# possible, as long as they don't disturb the formatting
|
||||
# (i.e. DO NOT ADD A 'v' prefix!)
|
||||
GOLANGCI_LINT_VERSION := 1.60.3
|
||||
GOLANGCI_LINT_VERSION := 1.61.0
|
||||
|
||||
default all: local-binary docs local-validate local-cross ## validate all checks, build and cross-build\nbinaries and docs
|
||||
|
||||
|
16
vendor/github.com/containers/storage/check.go
generated
vendored
16
vendor/github.com/containers/storage/check.go
generated
vendored
@ -8,6 +8,7 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -769,12 +770,9 @@ func (s *store) Repair(report CheckReport, options *RepairOptions) []error {
|
||||
return d
|
||||
}
|
||||
isUnaccounted := func(errs []error) bool {
|
||||
for _, err := range errs {
|
||||
if errors.Is(err, ErrLayerUnaccounted) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.ContainsFunc(errs, func(err error) bool {
|
||||
return errors.Is(err, ErrLayerUnaccounted)
|
||||
})
|
||||
}
|
||||
sort.Slice(layersToDelete, func(i, j int) bool {
|
||||
// we've not heard of either of them, so remove them in the order the driver suggested
|
||||
@ -1005,12 +1003,12 @@ func (c *checkDirectory) remove(path string) {
|
||||
func (c *checkDirectory) header(hdr *tar.Header) {
|
||||
name := path.Clean(hdr.Name)
|
||||
dir, base := path.Split(name)
|
||||
if strings.HasPrefix(base, archive.WhiteoutPrefix) {
|
||||
if file, ok := strings.CutPrefix(base, archive.WhiteoutPrefix); ok {
|
||||
if base == archive.WhiteoutOpaqueDir {
|
||||
c.remove(path.Clean(dir))
|
||||
c.add(path.Clean(dir), tar.TypeDir, hdr.Uid, hdr.Gid, hdr.Size, os.FileMode(hdr.Mode), hdr.ModTime.Unix())
|
||||
} else {
|
||||
c.remove(path.Join(dir, base[len(archive.WhiteoutPrefix):]))
|
||||
c.remove(path.Join(dir, file))
|
||||
}
|
||||
} else {
|
||||
if hdr.Typeflag == tar.TypeLink {
|
||||
@ -1044,7 +1042,7 @@ func (c *checkDirectory) header(hdr *tar.Header) {
|
||||
|
||||
// headers updates a checkDirectory using information from the passed-in header slice
|
||||
func (c *checkDirectory) headers(hdrs []*tar.Header) {
|
||||
hdrs = append([]*tar.Header{}, hdrs...)
|
||||
hdrs = slices.Clone(hdrs)
|
||||
// sort the headers from the diff to ensure that whiteouts appear
|
||||
// before content when they both appear in the same directory, per
|
||||
// https://github.com/opencontainers/image-spec/blob/main/layer.md#whiteouts
|
||||
|
41
vendor/github.com/containers/storage/containers.go
generated
vendored
41
vendor/github.com/containers/storage/containers.go
generated
vendored
@ -3,8 +3,10 @@ package storage
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -162,17 +164,17 @@ type containerStore struct {
|
||||
func copyContainer(c *Container) *Container {
|
||||
return &Container{
|
||||
ID: c.ID,
|
||||
Names: copyStringSlice(c.Names),
|
||||
Names: slices.Clone(c.Names),
|
||||
ImageID: c.ImageID,
|
||||
LayerID: c.LayerID,
|
||||
Metadata: c.Metadata,
|
||||
BigDataNames: copyStringSlice(c.BigDataNames),
|
||||
BigDataSizes: copyStringInt64Map(c.BigDataSizes),
|
||||
BigDataDigests: copyStringDigestMap(c.BigDataDigests),
|
||||
BigDataNames: slices.Clone(c.BigDataNames),
|
||||
BigDataSizes: maps.Clone(c.BigDataSizes),
|
||||
BigDataDigests: maps.Clone(c.BigDataDigests),
|
||||
Created: c.Created,
|
||||
UIDMap: copyIDMap(c.UIDMap),
|
||||
GIDMap: copyIDMap(c.GIDMap),
|
||||
Flags: copyStringInterfaceMap(c.Flags),
|
||||
Flags: maps.Clone(c.Flags),
|
||||
volatileStore: c.volatileStore,
|
||||
}
|
||||
}
|
||||
@ -696,7 +698,7 @@ func (r *containerStore) create(id string, names []string, image, layer string,
|
||||
volatileStore: options.Volatile,
|
||||
}
|
||||
if options.MountOpts != nil {
|
||||
container.Flags[mountOptsFlag] = append([]string{}, options.MountOpts...)
|
||||
container.Flags[mountOptsFlag] = slices.Clone(options.MountOpts)
|
||||
}
|
||||
if options.Volatile {
|
||||
container.Flags[volatileFlag] = true
|
||||
@ -788,13 +790,6 @@ func (r *containerStore) Delete(id string) error {
|
||||
return ErrContainerUnknown
|
||||
}
|
||||
id = container.ID
|
||||
toDeleteIndex := -1
|
||||
for i, candidate := range r.containers {
|
||||
if candidate.ID == id {
|
||||
toDeleteIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
delete(r.byid, id)
|
||||
// This can only fail if the ID is already missing, which shouldn’t happen — and in that case the index is already in the desired state anyway.
|
||||
// The store’s Delete method is used on various paths to recover from failures, so this should be robust against partially missing data.
|
||||
@ -803,14 +798,9 @@ func (r *containerStore) Delete(id string) error {
|
||||
for _, name := range container.Names {
|
||||
delete(r.byname, name)
|
||||
}
|
||||
if toDeleteIndex != -1 {
|
||||
// delete the container at toDeleteIndex
|
||||
if toDeleteIndex == len(r.containers)-1 {
|
||||
r.containers = r.containers[:len(r.containers)-1]
|
||||
} else {
|
||||
r.containers = append(r.containers[:toDeleteIndex], r.containers[toDeleteIndex+1:]...)
|
||||
}
|
||||
}
|
||||
r.containers = slices.DeleteFunc(r.containers, func(candidate *Container) bool {
|
||||
return candidate.ID == id
|
||||
})
|
||||
if err := r.saveFor(container); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -948,14 +938,7 @@ func (r *containerStore) SetBigData(id, key string, data []byte) error {
|
||||
if !sizeOk || oldSize != c.BigDataSizes[key] || !digestOk || oldDigest != newDigest {
|
||||
save = true
|
||||
}
|
||||
addName := true
|
||||
for _, name := range c.BigDataNames {
|
||||
if name == key {
|
||||
addName = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if addName {
|
||||
if !slices.Contains(c.BigDataNames, key) {
|
||||
c.BigDataNames = append(c.BigDataNames, key)
|
||||
save = true
|
||||
}
|
||||
|
4
vendor/github.com/containers/storage/drivers/driver.go
generated
vendored
4
vendor/github.com/containers/storage/drivers/driver.go
generated
vendored
@ -254,8 +254,8 @@ type Differ interface {
|
||||
type DriverWithDiffer interface {
|
||||
Driver
|
||||
// ApplyDiffWithDiffer applies the changes using the callback function.
|
||||
// If id is empty, then a staging directory is created. The staging directory is guaranteed to be usable with ApplyDiffFromStagingDirectory.
|
||||
ApplyDiffWithDiffer(id, parent string, options *ApplyDiffWithDifferOpts, differ Differ) (output DriverWithDifferOutput, err error)
|
||||
// The staging directory created by this function is guaranteed to be usable with ApplyDiffFromStagingDirectory.
|
||||
ApplyDiffWithDiffer(options *ApplyDiffWithDifferOpts, differ Differ) (output DriverWithDifferOutput, err error)
|
||||
// ApplyDiffFromStagingDirectory applies the changes using the diffOutput target directory.
|
||||
ApplyDiffFromStagingDirectory(id, parent string, diffOutput *DriverWithDifferOutput, options *ApplyDiffWithDifferOpts) error
|
||||
// CleanupStagingDirectory cleanups the staging directory. It can be used to cleanup the staging directory on errors
|
||||
|
12
vendor/github.com/containers/storage/drivers/overlay/mount.go
generated
vendored
12
vendor/github.com/containers/storage/drivers/overlay/mount.go
generated
vendored
@ -103,20 +103,20 @@ func mountOverlayFromMain() {
|
||||
// paths, but we don't want to mess with other options.
|
||||
var upperk, upperv, workk, workv, lowerk, lowerv, labelk, labelv, others string
|
||||
for _, arg := range strings.Split(options.Label, ",") {
|
||||
kv := strings.SplitN(arg, "=", 2)
|
||||
switch kv[0] {
|
||||
key, val, _ := strings.Cut(arg, "=")
|
||||
switch key {
|
||||
case "upperdir":
|
||||
upperk = "upperdir="
|
||||
upperv = kv[1]
|
||||
upperv = val
|
||||
case "workdir":
|
||||
workk = "workdir="
|
||||
workv = kv[1]
|
||||
workv = val
|
||||
case "lowerdir":
|
||||
lowerk = "lowerdir="
|
||||
lowerv = kv[1]
|
||||
lowerv = val
|
||||
case "label":
|
||||
labelk = "label="
|
||||
labelv = kv[1]
|
||||
labelv = val
|
||||
default:
|
||||
if others == "" {
|
||||
others = arg
|
||||
|
111
vendor/github.com/containers/storage/drivers/overlay/overlay.go
generated
vendored
111
vendor/github.com/containers/storage/drivers/overlay/overlay.go
generated
vendored
@ -14,6 +14,7 @@ import (
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -158,30 +159,7 @@ func init() {
|
||||
}
|
||||
|
||||
func hasMetacopyOption(opts []string) bool {
|
||||
for _, s := range opts {
|
||||
if s == "metacopy=on" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func stripOption(opts []string, option string) []string {
|
||||
for i, s := range opts {
|
||||
if s == option {
|
||||
return stripOption(append(opts[:i], opts[i+1:]...), option)
|
||||
}
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
func hasVolatileOption(opts []string) bool {
|
||||
for _, s := range opts {
|
||||
if s == "volatile" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains(opts, "metacopy=on")
|
||||
}
|
||||
|
||||
func getMountProgramFlagFile(path string) string {
|
||||
@ -1526,14 +1504,13 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
|
||||
logrus.Debugf("Ignoring global metacopy option, the mount program doesn't support it")
|
||||
}
|
||||
}
|
||||
optsList = stripOption(optsList, "metacopy=on")
|
||||
optsList = slices.DeleteFunc(optsList, func(opt string) bool {
|
||||
return opt == "metacopy=on"
|
||||
})
|
||||
}
|
||||
|
||||
for _, o := range optsList {
|
||||
if o == "ro" {
|
||||
readWrite = false
|
||||
break
|
||||
}
|
||||
if slices.Contains(optsList, "ro") {
|
||||
readWrite = false
|
||||
}
|
||||
|
||||
lowers, err := os.ReadFile(path.Join(dir, lowerFile))
|
||||
@ -1732,7 +1709,7 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
|
||||
optsList = append(optsList, "userxattr")
|
||||
}
|
||||
|
||||
if options.Volatile && !hasVolatileOption(optsList) {
|
||||
if options.Volatile && !slices.Contains(optsList, "volatile") {
|
||||
supported, err := d.getSupportsVolatile()
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -1896,7 +1873,9 @@ func (d *Driver) getMergedDir(id, dir string, inAdditionalStore bool) string {
|
||||
// and since the rundir cannot be shared for different stores, it is safe to assume the
|
||||
// current process has exclusive access to it.
|
||||
//
|
||||
// LOCKING BUG? the .DiffSize operation does not currently hold an exclusive lock on the primary store.
|
||||
// TO DO: LOCKING BUG: the .DiffSize operation does not currently hold an exclusive lock on the primary store.
|
||||
// (_Some_ of the callers might be better ported to use a metadata-only size computation instead of DiffSize,
|
||||
// but DiffSize probably needs to remain for computing sizes of container’s RW layers.)
|
||||
if inAdditionalStore {
|
||||
return path.Join(d.runhome, id, "merged")
|
||||
}
|
||||
@ -2187,7 +2166,7 @@ func supportsDataOnlyLayersCached(home, runhome string) (bool, error) {
|
||||
}
|
||||
|
||||
// ApplyDiffWithDiffer applies the changes in the new layer using the specified function
|
||||
func (d *Driver) ApplyDiffWithDiffer(id, parent string, options *graphdriver.ApplyDiffWithDifferOpts, differ graphdriver.Differ) (output graphdriver.DriverWithDifferOutput, errRet error) {
|
||||
func (d *Driver) ApplyDiffWithDiffer(options *graphdriver.ApplyDiffWithDifferOpts, differ graphdriver.Differ) (output graphdriver.DriverWithDifferOutput, errRet error) {
|
||||
var idMappings *idtools.IDMappings
|
||||
var forceMask *os.FileMode
|
||||
|
||||
@ -2205,44 +2184,36 @@ func (d *Driver) ApplyDiffWithDiffer(id, parent string, options *graphdriver.App
|
||||
|
||||
var applyDir string
|
||||
|
||||
if id == "" {
|
||||
stagingDir := d.getStagingDir(id)
|
||||
err := os.MkdirAll(stagingDir, 0o700)
|
||||
if err != nil && !os.IsExist(err) {
|
||||
return graphdriver.DriverWithDifferOutput{}, err
|
||||
}
|
||||
layerDir, err := os.MkdirTemp(stagingDir, "")
|
||||
if err != nil {
|
||||
return graphdriver.DriverWithDifferOutput{}, err
|
||||
}
|
||||
perms := defaultPerms
|
||||
if forceMask != nil {
|
||||
perms = *forceMask
|
||||
}
|
||||
applyDir = filepath.Join(layerDir, "dir")
|
||||
if err := os.Mkdir(applyDir, perms); err != nil {
|
||||
return graphdriver.DriverWithDifferOutput{}, err
|
||||
}
|
||||
|
||||
lock, err := lockfile.GetLockFile(filepath.Join(layerDir, stagingLockFile))
|
||||
if err != nil {
|
||||
return graphdriver.DriverWithDifferOutput{}, err
|
||||
}
|
||||
defer func() {
|
||||
if errRet != nil {
|
||||
delete(d.stagingDirsLocks, layerDir)
|
||||
lock.Unlock()
|
||||
}
|
||||
}()
|
||||
d.stagingDirsLocks[layerDir] = lock
|
||||
lock.Lock()
|
||||
} else {
|
||||
var err error
|
||||
applyDir, err = d.getDiffPath(id)
|
||||
if err != nil {
|
||||
return graphdriver.DriverWithDifferOutput{}, err
|
||||
}
|
||||
stagingDir := d.getStagingDir("")
|
||||
err := os.MkdirAll(stagingDir, 0o700)
|
||||
if err != nil && !os.IsExist(err) {
|
||||
return graphdriver.DriverWithDifferOutput{}, err
|
||||
}
|
||||
layerDir, err := os.MkdirTemp(stagingDir, "")
|
||||
if err != nil {
|
||||
return graphdriver.DriverWithDifferOutput{}, err
|
||||
}
|
||||
perms := defaultPerms
|
||||
if forceMask != nil {
|
||||
perms = *forceMask
|
||||
}
|
||||
applyDir = filepath.Join(layerDir, "dir")
|
||||
if err := os.Mkdir(applyDir, perms); err != nil {
|
||||
return graphdriver.DriverWithDifferOutput{}, err
|
||||
}
|
||||
|
||||
lock, err := lockfile.GetLockFile(filepath.Join(layerDir, stagingLockFile))
|
||||
if err != nil {
|
||||
return graphdriver.DriverWithDifferOutput{}, err
|
||||
}
|
||||
defer func() {
|
||||
if errRet != nil {
|
||||
delete(d.stagingDirsLocks, layerDir)
|
||||
lock.Unlock()
|
||||
}
|
||||
}()
|
||||
d.stagingDirsLocks[layerDir] = lock
|
||||
lock.Lock()
|
||||
|
||||
logrus.Debugf("Applying differ in %s", applyDir)
|
||||
|
||||
|
4
vendor/github.com/containers/storage/drivers/windows/windows.go
generated
vendored
4
vendor/github.com/containers/storage/drivers/windows/windows.go
generated
vendored
@ -764,8 +764,8 @@ func writeLayerFromTar(r io.Reader, w hcsshim.LayerWriter, root string) (int64,
|
||||
buf := bufio.NewWriter(nil)
|
||||
for err == nil {
|
||||
base := path.Base(hdr.Name)
|
||||
if strings.HasPrefix(base, archive.WhiteoutPrefix) {
|
||||
name := path.Join(path.Dir(hdr.Name), base[len(archive.WhiteoutPrefix):])
|
||||
if rm, ok := strings.CutPrefix(base, archive.WhiteoutPrefix); ok {
|
||||
name := path.Join(path.Dir(hdr.Name), rm)
|
||||
err = w.Remove(filepath.FromSlash(name))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
67
vendor/github.com/containers/storage/images.go
generated
vendored
67
vendor/github.com/containers/storage/images.go
generated
vendored
@ -2,8 +2,10 @@ package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@ -181,18 +183,18 @@ func copyImage(i *Image) *Image {
|
||||
return &Image{
|
||||
ID: i.ID,
|
||||
Digest: i.Digest,
|
||||
Digests: copyDigestSlice(i.Digests),
|
||||
Names: copyStringSlice(i.Names),
|
||||
NamesHistory: copyStringSlice(i.NamesHistory),
|
||||
Digests: slices.Clone(i.Digests),
|
||||
Names: slices.Clone(i.Names),
|
||||
NamesHistory: slices.Clone(i.NamesHistory),
|
||||
TopLayer: i.TopLayer,
|
||||
MappedTopLayers: copyStringSlice(i.MappedTopLayers),
|
||||
MappedTopLayers: slices.Clone(i.MappedTopLayers),
|
||||
Metadata: i.Metadata,
|
||||
BigDataNames: copyStringSlice(i.BigDataNames),
|
||||
BigDataSizes: copyStringInt64Map(i.BigDataSizes),
|
||||
BigDataDigests: copyStringDigestMap(i.BigDataDigests),
|
||||
BigDataNames: slices.Clone(i.BigDataNames),
|
||||
BigDataSizes: maps.Clone(i.BigDataSizes),
|
||||
BigDataDigests: maps.Clone(i.BigDataDigests),
|
||||
Created: i.Created,
|
||||
ReadOnly: i.ReadOnly,
|
||||
Flags: copyStringInterfaceMap(i.Flags),
|
||||
Flags: maps.Clone(i.Flags),
|
||||
}
|
||||
}
|
||||
|
||||
@ -863,12 +865,6 @@ func (r *imageStore) Delete(id string) error {
|
||||
return fmt.Errorf("locating image with ID %q: %w", id, ErrImageUnknown)
|
||||
}
|
||||
id = image.ID
|
||||
toDeleteIndex := -1
|
||||
for i, candidate := range r.images {
|
||||
if candidate.ID == id {
|
||||
toDeleteIndex = i
|
||||
}
|
||||
}
|
||||
delete(r.byid, id)
|
||||
// This can only fail if the ID is already missing, which shouldn’t happen — and in that case the index is already in the desired state anyway.
|
||||
// The store’s Delete method is used on various paths to recover from failures, so this should be robust against partially missing data.
|
||||
@ -877,21 +873,18 @@ func (r *imageStore) Delete(id string) error {
|
||||
delete(r.byname, name)
|
||||
}
|
||||
for _, digest := range image.Digests {
|
||||
prunedList := imageSliceWithoutValue(r.bydigest[digest], image)
|
||||
prunedList := slices.DeleteFunc(r.bydigest[digest], func(i *Image) bool {
|
||||
return i == image
|
||||
})
|
||||
if len(prunedList) == 0 {
|
||||
delete(r.bydigest, digest)
|
||||
} else {
|
||||
r.bydigest[digest] = prunedList
|
||||
}
|
||||
}
|
||||
if toDeleteIndex != -1 {
|
||||
// delete the image at toDeleteIndex
|
||||
if toDeleteIndex == len(r.images)-1 {
|
||||
r.images = r.images[:len(r.images)-1]
|
||||
} else {
|
||||
r.images = append(r.images[:toDeleteIndex], r.images[toDeleteIndex+1:]...)
|
||||
}
|
||||
}
|
||||
r.images = slices.DeleteFunc(r.images, func(candidate *Image) bool {
|
||||
return candidate.ID == id
|
||||
})
|
||||
if err := r.Save(); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -977,17 +970,6 @@ func (r *imageStore) BigDataNames(id string) ([]string, error) {
|
||||
return copyStringSlice(image.BigDataNames), nil
|
||||
}
|
||||
|
||||
func imageSliceWithoutValue(slice []*Image, value *Image) []*Image {
|
||||
modified := make([]*Image, 0, len(slice))
|
||||
for _, v := range slice {
|
||||
if v == value {
|
||||
continue
|
||||
}
|
||||
modified = append(modified, v)
|
||||
}
|
||||
return modified
|
||||
}
|
||||
|
||||
// Requires startWriting.
|
||||
func (r *imageStore) SetBigData(id, key string, data []byte, digestManifest func([]byte) (digest.Digest, error)) error {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
@ -1037,21 +1019,16 @@ func (r *imageStore) setBigData(image *Image, key string, data []byte, newDigest
|
||||
if !sizeOk || oldSize != image.BigDataSizes[key] || !digestOk || oldDigest != newDigest {
|
||||
save = true
|
||||
}
|
||||
addName := true
|
||||
for _, name := range image.BigDataNames {
|
||||
if name == key {
|
||||
addName = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if addName {
|
||||
if !slices.Contains(image.BigDataNames, key) {
|
||||
image.BigDataNames = append(image.BigDataNames, key)
|
||||
save = true
|
||||
}
|
||||
for _, oldDigest := range image.Digests {
|
||||
// remove the image from the list of images in the digest-based index
|
||||
if list, ok := r.bydigest[oldDigest]; ok {
|
||||
prunedList := imageSliceWithoutValue(list, image)
|
||||
prunedList := slices.DeleteFunc(list, func(i *Image) bool {
|
||||
return i == image
|
||||
})
|
||||
if len(prunedList) == 0 {
|
||||
delete(r.bydigest, oldDigest)
|
||||
} else {
|
||||
@ -1066,9 +1043,7 @@ func (r *imageStore) setBigData(image *Image, key string, data []byte, newDigest
|
||||
// add the image to the list of images in the digest-based index which
|
||||
// corresponds to the new digest for this item, unless it's already there
|
||||
list := r.bydigest[newDigest]
|
||||
if len(list) == len(imageSliceWithoutValue(list, image)) {
|
||||
// the list isn't shortened by trying to prune this image from it,
|
||||
// so it's not in there yet
|
||||
if !slices.Contains(list, image) {
|
||||
r.bydigest[newDigest] = append(list, image)
|
||||
}
|
||||
}
|
||||
|
120
vendor/github.com/containers/storage/layers.go
generated
vendored
120
vendor/github.com/containers/storage/layers.go
generated
vendored
@ -5,10 +5,12 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"maps"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -312,9 +314,8 @@ type rwLayerStore interface {
|
||||
// applies its changes to a specified layer.
|
||||
ApplyDiff(to string, diff io.Reader) (int64, error)
|
||||
|
||||
// ApplyDiffWithDiffer applies the changes through the differ callback function.
|
||||
// If to is the empty string, then a staging directory is created by the driver.
|
||||
ApplyDiffWithDiffer(to string, options *drivers.ApplyDiffWithDifferOpts, differ drivers.Differ) (*drivers.DriverWithDifferOutput, error)
|
||||
// applyDiffWithDifferNoLock applies the changes through the differ callback function.
|
||||
applyDiffWithDifferNoLock(options *drivers.ApplyDiffWithDifferOpts, differ drivers.Differ) (*drivers.DriverWithDifferOutput, error)
|
||||
|
||||
// CleanupStagingDirectory cleanups the staging directory. It can be used to cleanup the staging directory on errors
|
||||
CleanupStagingDirectory(stagingDirectory string) error
|
||||
@ -435,7 +436,7 @@ func layerLocation(l *Layer) layerLocations {
|
||||
func copyLayer(l *Layer) *Layer {
|
||||
return &Layer{
|
||||
ID: l.ID,
|
||||
Names: copyStringSlice(l.Names),
|
||||
Names: slices.Clone(l.Names),
|
||||
Parent: l.Parent,
|
||||
Metadata: l.Metadata,
|
||||
MountLabel: l.MountLabel,
|
||||
@ -450,8 +451,8 @@ func copyLayer(l *Layer) *Layer {
|
||||
CompressionType: l.CompressionType,
|
||||
ReadOnly: l.ReadOnly,
|
||||
volatileStore: l.volatileStore,
|
||||
BigDataNames: copyStringSlice(l.BigDataNames),
|
||||
Flags: copyStringInterfaceMap(l.Flags),
|
||||
BigDataNames: slices.Clone(l.BigDataNames),
|
||||
Flags: maps.Clone(l.Flags),
|
||||
UIDMap: copyIDMap(l.UIDMap),
|
||||
GIDMap: copyIDMap(l.GIDMap),
|
||||
UIDs: copyUint32Slice(l.UIDs),
|
||||
@ -1372,7 +1373,7 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount
|
||||
templateCompressedDigest, templateCompressedSize = templateLayer.CompressedDigest, templateLayer.CompressedSize
|
||||
templateUncompressedDigest, templateUncompressedSize = templateLayer.UncompressedDigest, templateLayer.UncompressedSize
|
||||
templateCompressionType = templateLayer.CompressionType
|
||||
templateUIDs, templateGIDs = append([]uint32{}, templateLayer.UIDs...), append([]uint32{}, templateLayer.GIDs...)
|
||||
templateUIDs, templateGIDs = slices.Clone(templateLayer.UIDs), slices.Clone(templateLayer.GIDs)
|
||||
templateTSdata, err = os.ReadFile(r.tspath(templateLayer.ID))
|
||||
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return nil, -1, err
|
||||
@ -1564,19 +1565,9 @@ func (r *layerStore) Mount(id string, options drivers.MountOpts) (string, error)
|
||||
// - r.layers[].MountPoint (directly and via loadMounts / saveMounts)
|
||||
// - r.bymount (via loadMounts / saveMounts)
|
||||
|
||||
// check whether options include ro option
|
||||
hasReadOnlyOpt := func(opts []string) bool {
|
||||
for _, item := range opts {
|
||||
if item == "ro" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// You are not allowed to mount layers from readonly stores if they
|
||||
// are not mounted read/only.
|
||||
if !r.lockfile.IsReadWrite() && !hasReadOnlyOpt(options.Options) {
|
||||
if !r.lockfile.IsReadWrite() && !slices.Contains(options.Options, "ro") {
|
||||
return "", fmt.Errorf("not allowed to update mount locations for layers at %q: %w", r.mountspath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
r.mountsLockfile.Lock()
|
||||
@ -1836,14 +1827,7 @@ func (r *layerStore) setBigData(layer *Layer, key string, data io.Reader) error
|
||||
return fmt.Errorf("closing bigdata file for the layer: %w", err)
|
||||
}
|
||||
|
||||
addName := true
|
||||
for _, name := range layer.BigDataNames {
|
||||
if name == key {
|
||||
addName = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if addName {
|
||||
if !slices.Contains(layer.BigDataNames, key) {
|
||||
layer.BigDataNames = append(layer.BigDataNames, key)
|
||||
return r.saveFor(layer)
|
||||
}
|
||||
@ -1938,32 +1922,13 @@ func (r *layerStore) deleteInternal(id string) error {
|
||||
delete(r.bymount, layer.MountPoint)
|
||||
}
|
||||
r.deleteInDigestMap(id)
|
||||
toDeleteIndex := -1
|
||||
for i, candidate := range r.layers {
|
||||
if candidate.ID == id {
|
||||
toDeleteIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if toDeleteIndex != -1 {
|
||||
// delete the layer at toDeleteIndex
|
||||
if toDeleteIndex == len(r.layers)-1 {
|
||||
r.layers = r.layers[:len(r.layers)-1]
|
||||
} else {
|
||||
r.layers = append(r.layers[:toDeleteIndex], r.layers[toDeleteIndex+1:]...)
|
||||
}
|
||||
}
|
||||
if mountLabel != "" {
|
||||
var found bool
|
||||
for _, candidate := range r.layers {
|
||||
if candidate.MountLabel == mountLabel {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
selinux.ReleaseLabel(mountLabel)
|
||||
}
|
||||
r.layers = slices.DeleteFunc(r.layers, func(candidate *Layer) bool {
|
||||
return candidate.ID == id
|
||||
})
|
||||
if mountLabel != "" && !slices.ContainsFunc(r.layers, func(candidate *Layer) bool {
|
||||
return candidate.MountLabel == mountLabel
|
||||
}) {
|
||||
selinux.ReleaseLabel(mountLabel)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -1971,21 +1936,15 @@ func (r *layerStore) deleteInternal(id string) error {
|
||||
// Requires startWriting.
|
||||
func (r *layerStore) deleteInDigestMap(id string) {
|
||||
for digest, layers := range r.bycompressedsum {
|
||||
for i, layerID := range layers {
|
||||
if layerID == id {
|
||||
layers = append(layers[:i], layers[i+1:]...)
|
||||
r.bycompressedsum[digest] = layers
|
||||
break
|
||||
}
|
||||
if i := slices.Index(layers, id); i != -1 {
|
||||
layers = slices.Delete(layers, i, i+1)
|
||||
r.bycompressedsum[digest] = layers
|
||||
}
|
||||
}
|
||||
for digest, layers := range r.byuncompressedsum {
|
||||
for i, layerID := range layers {
|
||||
if layerID == id {
|
||||
layers = append(layers[:i], layers[i+1:]...)
|
||||
r.byuncompressedsum[digest] = layers
|
||||
break
|
||||
}
|
||||
if i := slices.Index(layers, id); i != -1 {
|
||||
layers = slices.Delete(layers, i, i+1)
|
||||
r.byuncompressedsum[digest] = layers
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2545,9 +2504,7 @@ func (r *layerStore) applyDiffFromStagingDirectory(id string, diffOutput *driver
|
||||
if layer.Flags == nil {
|
||||
layer.Flags = make(map[string]interface{})
|
||||
}
|
||||
for k, v := range options.Flags {
|
||||
layer.Flags[k] = v
|
||||
}
|
||||
maps.Copy(layer.Flags, options.Flags)
|
||||
}
|
||||
if err = r.saveFor(layer); err != nil {
|
||||
return err
|
||||
@ -2585,37 +2542,14 @@ func (r *layerStore) applyDiffFromStagingDirectory(id string, diffOutput *driver
|
||||
return err
|
||||
}
|
||||
|
||||
// Requires startWriting.
|
||||
func (r *layerStore) ApplyDiffWithDiffer(to string, options *drivers.ApplyDiffWithDifferOpts, differ drivers.Differ) (*drivers.DriverWithDifferOutput, error) {
|
||||
// It must be called without any c/storage locks held to allow differ to make c/storage calls.
|
||||
func (r *layerStore) applyDiffWithDifferNoLock(options *drivers.ApplyDiffWithDifferOpts, differ drivers.Differ) (*drivers.DriverWithDifferOutput, error) {
|
||||
ddriver, ok := r.driver.(drivers.DriverWithDiffer)
|
||||
if !ok {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
if to == "" {
|
||||
output, err := ddriver.ApplyDiffWithDiffer("", "", options, differ)
|
||||
return &output, err
|
||||
}
|
||||
|
||||
layer, ok := r.lookup(to)
|
||||
if !ok {
|
||||
return nil, ErrLayerUnknown
|
||||
}
|
||||
if options == nil {
|
||||
options = &drivers.ApplyDiffWithDifferOpts{
|
||||
ApplyDiffOpts: drivers.ApplyDiffOpts{
|
||||
Mappings: r.layerMappings(layer),
|
||||
MountLabel: layer.MountLabel,
|
||||
},
|
||||
}
|
||||
}
|
||||
output, err := ddriver.ApplyDiffWithDiffer(layer.ID, layer.Parent, options, differ)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
layer.UIDs = output.UIDs
|
||||
layer.GIDs = output.GIDs
|
||||
err = r.saveFor(layer)
|
||||
output, err := ddriver.ApplyDiffWithDiffer(options, differ)
|
||||
return &output, err
|
||||
}
|
||||
|
||||
|
3
vendor/github.com/containers/storage/pkg/archive/archive_linux.go
generated
vendored
3
vendor/github.com/containers/storage/pkg/archive/archive_linux.go
generated
vendored
@ -124,8 +124,7 @@ func (overlayWhiteoutConverter) ConvertReadWithHandler(hdr *tar.Header, path str
|
||||
}
|
||||
|
||||
// if a file was deleted and we are using overlay, we need to create a character device
|
||||
if strings.HasPrefix(base, WhiteoutPrefix) {
|
||||
originalBase := base[len(WhiteoutPrefix):]
|
||||
if originalBase, ok := strings.CutPrefix(base, WhiteoutPrefix); ok {
|
||||
originalPath := filepath.Join(dir, originalBase)
|
||||
|
||||
if err := handler.Mknod(originalPath, unix.S_IFCHR, 0); err != nil {
|
||||
|
8
vendor/github.com/containers/storage/pkg/archive/changes.go
generated
vendored
8
vendor/github.com/containers/storage/pkg/archive/changes.go
generated
vendored
@ -5,6 +5,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
@ -97,8 +98,7 @@ func aufsDeletedFile(root, path string, fi os.FileInfo) (string, error) {
|
||||
f := filepath.Base(path)
|
||||
|
||||
// If there is a whiteout, then the file was removed
|
||||
if strings.HasPrefix(f, WhiteoutPrefix) {
|
||||
originalFile := f[len(WhiteoutPrefix):]
|
||||
if originalFile, ok := strings.CutPrefix(f, WhiteoutPrefix); ok {
|
||||
return filepath.Join(filepath.Dir(path), originalFile), nil
|
||||
}
|
||||
|
||||
@ -319,9 +319,7 @@ func (info *FileInfo) addChanges(oldInfo *FileInfo, changes *[]Change) {
|
||||
// otherwise any previous delete/change is considered recursive
|
||||
oldChildren := make(map[string]*FileInfo)
|
||||
if oldInfo != nil && info.isDir() {
|
||||
for k, v := range oldInfo.children {
|
||||
oldChildren[k] = v
|
||||
}
|
||||
maps.Copy(oldChildren, oldInfo.children)
|
||||
}
|
||||
|
||||
for name, newChild := range info.children {
|
||||
|
2
vendor/github.com/containers/storage/pkg/archive/changes_other.go
generated
vendored
2
vendor/github.com/containers/storage/pkg/archive/changes_other.go
generated
vendored
@ -31,7 +31,7 @@ func collectFileInfoForChanges(oldDir, newDir string, oldIDMap, newIDMap *idtool
|
||||
}()
|
||||
|
||||
// block until both routines have returned
|
||||
for i := 0; i < 2; i++ {
|
||||
for range 2 {
|
||||
if err := <-errs; err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
4
vendor/github.com/containers/storage/pkg/archive/fflags_bsd.go
generated
vendored
4
vendor/github.com/containers/storage/pkg/archive/fflags_bsd.go
generated
vendored
@ -80,9 +80,9 @@ func parseFileFlags(fflags string) (uint32, uint32, error) {
|
||||
var set, clear uint32 = 0, 0
|
||||
for _, fflag := range strings.Split(fflags, ",") {
|
||||
isClear := false
|
||||
if strings.HasPrefix(fflag, "no") {
|
||||
if clean, ok := strings.CutPrefix(fflag, "no"); ok {
|
||||
isClear = true
|
||||
fflag = strings.TrimPrefix(fflag, "no")
|
||||
fflag = clean
|
||||
}
|
||||
if value, ok := flagNameToValue[fflag]; ok {
|
||||
if isClear {
|
||||
|
2
vendor/github.com/containers/storage/pkg/chrootarchive/chroot_linux.go
generated
vendored
2
vendor/github.com/containers/storage/pkg/chrootarchive/chroot_linux.go
generated
vendored
@ -8,7 +8,7 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containers/storage/pkg/mount"
|
||||
"github.com/syndtr/gocapability/capability"
|
||||
"github.com/moby/sys/capability"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
|
27
vendor/github.com/containers/storage/pkg/chunked/cache_linux.go
generated
vendored
27
vendor/github.com/containers/storage/pkg/chunked/cache_linux.go
generated
vendored
@ -65,11 +65,10 @@ type layer struct {
|
||||
}
|
||||
|
||||
type layersCache struct {
|
||||
layers []*layer
|
||||
refs int
|
||||
store storage.Store
|
||||
mutex sync.RWMutex
|
||||
created time.Time
|
||||
layers []*layer
|
||||
refs int
|
||||
store storage.Store
|
||||
mutex sync.RWMutex
|
||||
}
|
||||
|
||||
var (
|
||||
@ -83,6 +82,7 @@ func (c *layer) release() {
|
||||
if err := unix.Munmap(c.mmapBuffer); err != nil {
|
||||
logrus.Warnf("Error Munmap: layer %q: %v", c.id, err)
|
||||
}
|
||||
c.mmapBuffer = nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,14 +107,13 @@ func (c *layersCache) release() {
|
||||
func getLayersCacheRef(store storage.Store) *layersCache {
|
||||
cacheMutex.Lock()
|
||||
defer cacheMutex.Unlock()
|
||||
if cache != nil && cache.store == store && time.Since(cache.created).Minutes() < 10 {
|
||||
if cache != nil && cache.store == store {
|
||||
cache.refs++
|
||||
return cache
|
||||
}
|
||||
cache := &layersCache{
|
||||
store: store,
|
||||
refs: 1,
|
||||
created: time.Now(),
|
||||
cache = &layersCache{
|
||||
store: store,
|
||||
refs: 1,
|
||||
}
|
||||
return cache
|
||||
}
|
||||
@ -291,7 +290,7 @@ func (c *layersCache) load() error {
|
||||
if r.ReadOnly {
|
||||
// If the layer is coming from a read-only store, do not attempt
|
||||
// to write to it.
|
||||
// Therefore,we won’t find any matches in read-only-store layers,
|
||||
// Therefore, we won’t find any matches in read-only-store layers,
|
||||
// unless the read-only store layer comes prepopulated with cacheKey data.
|
||||
continue
|
||||
}
|
||||
@ -781,14 +780,14 @@ func (c *layersCache) findDigestInternal(digest string) (string, string, int64,
|
||||
return "", "", -1, nil
|
||||
}
|
||||
|
||||
c.mutex.RLock()
|
||||
defer c.mutex.RUnlock()
|
||||
|
||||
binaryDigest, err := makeBinaryDigest(digest)
|
||||
if err != nil {
|
||||
return "", "", 0, err
|
||||
}
|
||||
|
||||
c.mutex.RLock()
|
||||
defer c.mutex.RUnlock()
|
||||
|
||||
for _, layer := range c.layers {
|
||||
if !layer.cacheFile.bloomFilter.maybeContains(binaryDigest) {
|
||||
continue
|
||||
|
2
vendor/github.com/containers/storage/pkg/chunked/storage_linux.go
generated
vendored
2
vendor/github.com/containers/storage/pkg/chunked/storage_linux.go
generated
vendored
@ -1331,7 +1331,7 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions, diff
|
||||
wg.Wait()
|
||||
}()
|
||||
|
||||
for i := 0; i < copyGoRoutines; i++ {
|
||||
for range copyGoRoutines {
|
||||
wg.Add(1)
|
||||
jobs := copyFileJobs
|
||||
|
||||
|
7
vendor/github.com/containers/storage/pkg/directory/directory_unix.go
generated
vendored
7
vendor/github.com/containers/storage/pkg/directory/directory_unix.go
generated
vendored
@ -4,8 +4,8 @@
|
||||
package directory
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
)
|
||||
@ -27,7 +27,7 @@ func Usage(dir string) (usage *DiskUsage, err error) {
|
||||
if err != nil {
|
||||
// if dir does not exist, Usage() returns the error.
|
||||
// if dir/x disappeared while walking, Usage() ignores dir/x.
|
||||
if os.IsNotExist(err) && d != dir {
|
||||
if errors.Is(err, fs.ErrNotExist) && d != dir {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
@ -35,6 +35,9 @@ func Usage(dir string) (usage *DiskUsage, err error) {
|
||||
|
||||
fileInfo, err := entry.Info()
|
||||
if err != nil {
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
7
vendor/github.com/containers/storage/pkg/directory/directory_windows.go
generated
vendored
7
vendor/github.com/containers/storage/pkg/directory/directory_windows.go
generated
vendored
@ -4,8 +4,8 @@
|
||||
package directory
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
@ -25,7 +25,7 @@ func Usage(dir string) (usage *DiskUsage, err error) {
|
||||
if err != nil {
|
||||
// if dir does not exist, Size() returns the error.
|
||||
// if dir/x disappeared while walking, Size() ignores dir/x.
|
||||
if os.IsNotExist(err) && path != dir {
|
||||
if errors.Is(err, fs.ErrNotExist) && path != dir {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
@ -40,6 +40,9 @@ func Usage(dir string) (usage *DiskUsage, err error) {
|
||||
|
||||
fileInfo, err := d.Info()
|
||||
if err != nil {
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
usage.Size += fileInfo.Size()
|
||||
|
12
vendor/github.com/containers/storage/pkg/mount/flags.go
generated
vendored
12
vendor/github.com/containers/storage/pkg/mount/flags.go
generated
vendored
@ -97,14 +97,14 @@ func MergeTmpfsOptions(options []string) ([]string, error) {
|
||||
}
|
||||
continue
|
||||
}
|
||||
opt := strings.SplitN(option, "=", 2)
|
||||
if len(opt) != 2 || !validFlags[opt[0]] {
|
||||
opt, _, ok := strings.Cut(option, "=")
|
||||
if !ok || !validFlags[opt] {
|
||||
return nil, fmt.Errorf("invalid tmpfs option %q", opt)
|
||||
}
|
||||
if !dataCollisions[opt[0]] {
|
||||
if !dataCollisions[opt] {
|
||||
// We prepend the option and add to collision map
|
||||
newOptions = append([]string{option}, newOptions...)
|
||||
dataCollisions[opt[0]] = true
|
||||
dataCollisions[opt] = true
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,8 +140,8 @@ func ParseOptions(options string) (int, string) {
|
||||
func ParseTmpfsOptions(options string) (int, string, error) {
|
||||
flags, data := ParseOptions(options)
|
||||
for _, o := range strings.Split(data, ",") {
|
||||
opt := strings.SplitN(o, "=", 2)
|
||||
if !validFlags[opt[0]] {
|
||||
opt, _, _ := strings.Cut(o, "=")
|
||||
if !validFlags[opt] {
|
||||
return 0, "", fmt.Errorf("invalid tmpfs option %q", opt)
|
||||
}
|
||||
}
|
||||
|
10
vendor/github.com/containers/storage/pkg/mount/mounter_freebsd.go
generated
vendored
10
vendor/github.com/containers/storage/pkg/mount/mounter_freebsd.go
generated
vendored
@ -40,13 +40,9 @@ func mount(device, target, mType string, flag uintptr, data string) error {
|
||||
isNullFS = true
|
||||
continue
|
||||
}
|
||||
opt := strings.SplitN(x, "=", 2)
|
||||
options = append(options, opt[0])
|
||||
if len(opt) == 2 {
|
||||
options = append(options, opt[1])
|
||||
} else {
|
||||
options = append(options, "")
|
||||
}
|
||||
name, val, _ := strings.Cut(x, "=")
|
||||
options = append(options, name)
|
||||
options = append(options, val)
|
||||
}
|
||||
}
|
||||
|
||||
|
2
vendor/github.com/containers/storage/pkg/mount/unmount_unix.go
generated
vendored
2
vendor/github.com/containers/storage/pkg/mount/unmount_unix.go
generated
vendored
@ -11,7 +11,7 @@ import (
|
||||
|
||||
func unmount(target string, flags int) error {
|
||||
var err error
|
||||
for i := 0; i < 50; i++ {
|
||||
for range 50 {
|
||||
err = unix.Unmount(target, flags)
|
||||
switch err {
|
||||
case unix.EBUSY:
|
||||
|
14
vendor/github.com/containers/storage/pkg/parsers/parsers.go
generated
vendored
14
vendor/github.com/containers/storage/pkg/parsers/parsers.go
generated
vendored
@ -11,11 +11,11 @@ import (
|
||||
|
||||
// ParseKeyValueOpt parses and validates the specified string as a key/value pair (key=value)
|
||||
func ParseKeyValueOpt(opt string) (string, string, error) {
|
||||
parts := strings.SplitN(opt, "=", 2)
|
||||
if len(parts) != 2 {
|
||||
k, v, ok := strings.Cut(opt, "=")
|
||||
if !ok {
|
||||
return "", "", fmt.Errorf("unable to parse key/value option: %s", opt)
|
||||
}
|
||||
return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil
|
||||
return strings.TrimSpace(k), strings.TrimSpace(v), nil
|
||||
}
|
||||
|
||||
// ParseUintList parses and validates the specified string as the value
|
||||
@ -42,19 +42,19 @@ func ParseUintList(val string) (map[int]bool, error) {
|
||||
errInvalidFormat := fmt.Errorf("invalid format: %s", val)
|
||||
|
||||
for _, r := range split {
|
||||
if !strings.Contains(r, "-") {
|
||||
minS, maxS, ok := strings.Cut(r, "-")
|
||||
if !ok {
|
||||
v, err := strconv.Atoi(r)
|
||||
if err != nil {
|
||||
return nil, errInvalidFormat
|
||||
}
|
||||
availableInts[v] = true
|
||||
} else {
|
||||
split := strings.SplitN(r, "-", 2)
|
||||
min, err := strconv.Atoi(split[0])
|
||||
min, err := strconv.Atoi(minS)
|
||||
if err != nil {
|
||||
return nil, errInvalidFormat
|
||||
}
|
||||
max, err := strconv.Atoi(split[1])
|
||||
max, err := strconv.Atoi(maxS)
|
||||
if err != nil {
|
||||
return nil, errInvalidFormat
|
||||
}
|
||||
|
6
vendor/github.com/containers/storage/pkg/stringutils/stringutils.go
generated
vendored
6
vendor/github.com/containers/storage/pkg/stringutils/stringutils.go
generated
vendored
@ -3,7 +3,7 @@ package stringutils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math/rand"
|
||||
"math/rand/v2"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -13,7 +13,7 @@ func GenerateRandomAlphaOnlyString(n int) string {
|
||||
letters := []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
b := make([]byte, n)
|
||||
for i := range b {
|
||||
b[i] = letters[rand.Intn(len(letters))]
|
||||
b[i] = letters[rand.IntN(len(letters))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
@ -25,7 +25,7 @@ func GenerateRandomASCIIString(n int) string {
|
||||
"~!@#$%^&*()-_+={}[]\\|<,>.?/\"';:` "
|
||||
res := make([]byte, n)
|
||||
for i := 0; i < n; i++ {
|
||||
res[i] = chars[rand.Intn(len(chars))]
|
||||
res[i] = chars[rand.IntN(len(chars))]
|
||||
}
|
||||
return string(res)
|
||||
}
|
||||
|
2
vendor/github.com/containers/storage/pkg/unshare/unshare_linux.go
generated
vendored
2
vendor/github.com/containers/storage/pkg/unshare/unshare_linux.go
generated
vendored
@ -21,9 +21,9 @@ import (
|
||||
|
||||
"github.com/containers/storage/pkg/idtools"
|
||||
"github.com/containers/storage/pkg/reexec"
|
||||
"github.com/moby/sys/capability"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/syndtr/gocapability/capability"
|
||||
)
|
||||
|
||||
// Cmd wraps an exec.Cmd created by the reexec package in unshare(), and
|
||||
|
83
vendor/github.com/containers/storage/store.go
generated
vendored
83
vendor/github.com/containers/storage/store.go
generated
vendored
@ -6,9 +6,11 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
@ -339,11 +341,17 @@ type Store interface {
|
||||
// }
|
||||
ApplyDiff(to string, diff io.Reader) (int64, error)
|
||||
|
||||
// ApplyDiffer applies a diff to a layer.
|
||||
// ApplyDiffWithDiffer applies a diff to a layer.
|
||||
// It is the caller responsibility to clean the staging directory if it is not
|
||||
// successfully applied with ApplyDiffFromStagingDirectory.
|
||||
// successfully applied with ApplyStagedLayer.
|
||||
// Deprecated: Use PrepareStagedLayer instead. ApplyDiffWithDiffer is going to be removed in a future release
|
||||
ApplyDiffWithDiffer(to string, options *drivers.ApplyDiffWithDifferOpts, differ drivers.Differ) (*drivers.DriverWithDifferOutput, error)
|
||||
|
||||
// PrepareStagedLayer applies a diff to a layer.
|
||||
// It is the caller responsibility to clean the staging directory if it is not
|
||||
// successfully applied with ApplyStagedLayer.
|
||||
PrepareStagedLayer(options *drivers.ApplyDiffWithDifferOpts, differ drivers.Differ) (*drivers.DriverWithDifferOutput, error)
|
||||
|
||||
// ApplyStagedLayer combines the functions of creating a layer and using the staging
|
||||
// directory to populate it.
|
||||
// It marks the layer for automatic removal if applying the diff fails for any reason.
|
||||
@ -939,9 +947,7 @@ func (s *store) GraphOptions() []string {
|
||||
|
||||
func (s *store) PullOptions() map[string]string {
|
||||
cp := make(map[string]string, len(s.pullOptions))
|
||||
for k, v := range s.pullOptions {
|
||||
cp[k] = v
|
||||
}
|
||||
maps.Copy(cp, s.pullOptions)
|
||||
return cp
|
||||
}
|
||||
|
||||
@ -1464,7 +1470,7 @@ func (s *store) putLayer(rlstore rwLayerStore, rlstores []roLayerStore, id, pare
|
||||
if lOptions != nil {
|
||||
options = *lOptions
|
||||
options.BigData = copyLayerBigDataOptionSlice(lOptions.BigData)
|
||||
options.Flags = copyStringInterfaceMap(lOptions.Flags)
|
||||
options.Flags = maps.Clone(lOptions.Flags)
|
||||
}
|
||||
if options.HostUIDMapping {
|
||||
options.UIDMap = nil
|
||||
@ -1605,7 +1611,7 @@ func (s *store) CreateImage(id string, names []string, layer, metadata string, i
|
||||
CreationDate: i.Created,
|
||||
Digest: i.Digest,
|
||||
Digests: copyDigestSlice(i.Digests),
|
||||
NamesHistory: copyStringSlice(i.NamesHistory),
|
||||
NamesHistory: slices.Clone(i.NamesHistory),
|
||||
}
|
||||
for _, key := range i.BigDataNames {
|
||||
data, err := store.BigData(id, key)
|
||||
@ -1622,7 +1628,7 @@ func (s *store) CreateImage(id string, names []string, layer, metadata string, i
|
||||
Digest: dataDigest,
|
||||
})
|
||||
}
|
||||
namesToAddAfterCreating = dedupeStrings(append(append([]string{}, i.Names...), names...))
|
||||
namesToAddAfterCreating = dedupeStrings(slices.Concat(i.Names, names))
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -1636,18 +1642,16 @@ func (s *store) CreateImage(id string, names []string, layer, metadata string, i
|
||||
if iOptions.Digest != "" {
|
||||
options.Digest = iOptions.Digest
|
||||
}
|
||||
options.Digests = append(options.Digests, copyDigestSlice(iOptions.Digests)...)
|
||||
options.Digests = append(options.Digests, iOptions.Digests...)
|
||||
if iOptions.Metadata != "" {
|
||||
options.Metadata = iOptions.Metadata
|
||||
}
|
||||
options.BigData = append(options.BigData, copyImageBigDataOptionSlice(iOptions.BigData)...)
|
||||
options.NamesHistory = append(options.NamesHistory, copyStringSlice(iOptions.NamesHistory)...)
|
||||
options.NamesHistory = append(options.NamesHistory, iOptions.NamesHistory...)
|
||||
if options.Flags == nil {
|
||||
options.Flags = make(map[string]interface{})
|
||||
}
|
||||
for k, v := range iOptions.Flags {
|
||||
options.Flags[k] = v
|
||||
}
|
||||
maps.Copy(options.Flags, iOptions.Flags)
|
||||
}
|
||||
|
||||
if options.CreationDate.IsZero() {
|
||||
@ -1782,7 +1786,7 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat
|
||||
options.IDMappingOptions.UIDMap = copyIDMap(cOptions.IDMappingOptions.UIDMap)
|
||||
options.IDMappingOptions.GIDMap = copyIDMap(cOptions.IDMappingOptions.GIDMap)
|
||||
options.LabelOpts = copyStringSlice(cOptions.LabelOpts)
|
||||
options.Flags = copyStringInterfaceMap(cOptions.Flags)
|
||||
options.Flags = maps.Clone(cOptions.Flags)
|
||||
options.MountOpts = copyStringSlice(cOptions.MountOpts)
|
||||
options.StorageOpt = copyStringStringMap(cOptions.StorageOpt)
|
||||
options.BigData = copyContainerBigDataOptionSlice(cOptions.BigData)
|
||||
@ -3105,13 +3109,19 @@ func (s *store) CleanupStagedLayer(diffOutput *drivers.DriverWithDifferOutput) e
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *store) PrepareStagedLayer(options *drivers.ApplyDiffWithDifferOpts, differ drivers.Differ) (*drivers.DriverWithDifferOutput, error) {
|
||||
rlstore, err := s.getLayerStore()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rlstore.applyDiffWithDifferNoLock(options, differ)
|
||||
}
|
||||
|
||||
func (s *store) ApplyDiffWithDiffer(to string, options *drivers.ApplyDiffWithDifferOpts, differ drivers.Differ) (*drivers.DriverWithDifferOutput, error) {
|
||||
return writeToLayerStore(s, func(rlstore rwLayerStore) (*drivers.DriverWithDifferOutput, error) {
|
||||
if to != "" && !rlstore.Exists(to) {
|
||||
return nil, ErrLayerUnknown
|
||||
}
|
||||
return rlstore.ApplyDiffWithDiffer(to, options, differ)
|
||||
})
|
||||
if to != "" {
|
||||
return nil, fmt.Errorf("ApplyDiffWithDiffer does not support non-empty 'layer' parameter")
|
||||
}
|
||||
return s.PrepareStagedLayer(options, differ)
|
||||
}
|
||||
|
||||
func (s *store) DifferTarget(id string) (string, error) {
|
||||
@ -3683,22 +3693,6 @@ func copyStringSlice(slice []string) []string {
|
||||
return ret
|
||||
}
|
||||
|
||||
func copyStringInt64Map(m map[string]int64) map[string]int64 {
|
||||
ret := make(map[string]int64, len(m))
|
||||
for k, v := range m {
|
||||
ret[k] = v
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func copyStringDigestMap(m map[string]digest.Digest) map[string]digest.Digest {
|
||||
ret := make(map[string]digest.Digest, len(m))
|
||||
for k, v := range m {
|
||||
ret[k] = v
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func copyStringStringMap(m map[string]string) map[string]string {
|
||||
ret := make(map[string]string, len(m))
|
||||
for k, v := range m {
|
||||
@ -3736,7 +3730,7 @@ func copyImageBigDataOptionSlice(slice []ImageBigDataOption) []ImageBigDataOptio
|
||||
ret := make([]ImageBigDataOption, len(slice))
|
||||
for i := range slice {
|
||||
ret[i].Key = slice[i].Key
|
||||
ret[i].Data = append([]byte{}, slice[i].Data...)
|
||||
ret[i].Data = slices.Clone(slice[i].Data)
|
||||
ret[i].Digest = slice[i].Digest
|
||||
}
|
||||
return ret
|
||||
@ -3746,7 +3740,7 @@ func copyContainerBigDataOptionSlice(slice []ContainerBigDataOption) []Container
|
||||
ret := make([]ContainerBigDataOption, len(slice))
|
||||
for i := range slice {
|
||||
ret[i].Key = slice[i].Key
|
||||
ret[i].Data = append([]byte{}, slice[i].Data...)
|
||||
ret[i].Data = slices.Clone(slice[i].Data)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
@ -3800,10 +3794,8 @@ func GetMountOptions(driver string, graphDriverOptions []string) ([]string, erro
|
||||
return nil, err
|
||||
}
|
||||
key = strings.ToLower(key)
|
||||
for _, m := range mountOpts {
|
||||
if m == key {
|
||||
return strings.Split(val, ","), nil
|
||||
}
|
||||
if slices.Contains(mountOpts, key) {
|
||||
return strings.Split(val, ","), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
@ -3811,11 +3803,8 @@ func GetMountOptions(driver string, graphDriverOptions []string) ([]string, erro
|
||||
|
||||
// Free removes the store from the list of stores
|
||||
func (s *store) Free() {
|
||||
for i := 0; i < len(stores); i++ {
|
||||
if stores[i] == s {
|
||||
stores = append(stores[:i], stores[i+1:]...)
|
||||
return
|
||||
}
|
||||
if i := slices.Index(stores, s); i != -1 {
|
||||
stores = slices.Delete(stores, i, i+1)
|
||||
}
|
||||
}
|
||||
|
||||
|
4
vendor/github.com/containers/storage/types/options.go
generated
vendored
4
vendor/github.com/containers/storage/types/options.go
generated
vendored
@ -344,8 +344,8 @@ func getRootlessStorageOpts(systemOpts StoreOptions) (StoreOptions, error) {
|
||||
dirEntries, err := os.ReadDir(opts.GraphRoot)
|
||||
if err == nil {
|
||||
for _, entry := range dirEntries {
|
||||
if strings.HasSuffix(entry.Name(), "-images") {
|
||||
opts.GraphDriverName = strings.TrimSuffix(entry.Name(), "-images")
|
||||
if name, ok := strings.CutSuffix(entry.Name(), "-images"); ok {
|
||||
opts.GraphDriverName = name
|
||||
break
|
||||
}
|
||||
}
|
||||
|
12
vendor/github.com/containers/storage/userns.go
generated
vendored
12
vendor/github.com/containers/storage/userns.go
generated
vendored
@ -89,7 +89,7 @@ func parseMountedFiles(containerMount, passwdFile, groupFile string) uint32 {
|
||||
passwdFile = filepath.Join(containerMount, "etc/passwd")
|
||||
}
|
||||
if groupFile == "" {
|
||||
groupFile = filepath.Join(groupFile, "etc/group")
|
||||
groupFile = filepath.Join(containerMount, "etc/group")
|
||||
}
|
||||
|
||||
size := 0
|
||||
@ -99,14 +99,14 @@ func parseMountedFiles(containerMount, passwdFile, groupFile string) uint32 {
|
||||
for _, u := range users {
|
||||
// Skip the "nobody" user otherwise we end up with 65536
|
||||
// ids with most images
|
||||
if u.Name == "nobody" {
|
||||
if u.Name == "nobody" || u.Name == "nogroup" {
|
||||
continue
|
||||
}
|
||||
if u.Uid > size && u.Uid != nobodyUser {
|
||||
size = u.Uid
|
||||
size = u.Uid + 1
|
||||
}
|
||||
if u.Gid > size && u.Gid != nobodyUser {
|
||||
size = u.Gid
|
||||
size = u.Gid + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -114,11 +114,11 @@ func parseMountedFiles(containerMount, passwdFile, groupFile string) uint32 {
|
||||
groups, err := libcontainerUser.ParseGroupFile(groupFile)
|
||||
if err == nil {
|
||||
for _, g := range groups {
|
||||
if g.Name == "nobody" {
|
||||
if g.Name == "nobody" || g.Name == "nogroup" {
|
||||
continue
|
||||
}
|
||||
if g.Gid > size && g.Gid != nobodyUser {
|
||||
size = g.Gid
|
||||
size = g.Gid + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
15
vendor/github.com/containers/storage/utils.go
generated
vendored
15
vendor/github.com/containers/storage/utils.go
generated
vendored
@ -2,6 +2,7 @@ package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"github.com/containers/storage/types"
|
||||
)
|
||||
@ -41,22 +42,12 @@ func applyNameOperation(oldNames []string, opParameters []string, op updateNameO
|
||||
// remove given names from old names
|
||||
result = make([]string, 0, len(oldNames))
|
||||
for _, name := range oldNames {
|
||||
// only keep names in final result which do not intersect with input names
|
||||
// basically `result = oldNames - opParameters`
|
||||
nameShouldBeRemoved := false
|
||||
for _, opName := range opParameters {
|
||||
if name == opName {
|
||||
nameShouldBeRemoved = true
|
||||
}
|
||||
}
|
||||
if !nameShouldBeRemoved {
|
||||
if !slices.Contains(opParameters, name) {
|
||||
result = append(result, name)
|
||||
}
|
||||
}
|
||||
case addNames:
|
||||
result = make([]string, 0, len(opParameters)+len(oldNames))
|
||||
result = append(result, opParameters...)
|
||||
result = append(result, oldNames...)
|
||||
result = slices.Concat(opParameters, oldNames)
|
||||
default:
|
||||
return result, errInvalidUpdateNameOperation
|
||||
}
|
||||
|
Reference in New Issue
Block a user