diff options
author | Daniel J Walsh <dwalsh@redhat.com> | 2023-07-14 07:19:56 -0400 |
---|---|---|
committer | Daniel J Walsh <dwalsh@redhat.com> | 2023-07-14 07:19:56 -0400 |
commit | 13a9500166a83989c60e2155d767fc2100773ad2 (patch) | |
tree | 4c3cea2d3cbc7c6cedc8865f3aff35120fed5d19 /vendor/github.com/containers/storage/pkg | |
parent | bb72016f58d4e99bdfafba0ae6c7af61ca28b3e6 (diff) |
Update vendor containers/(common, buildah, image, storage)
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
Diffstat (limited to 'vendor/github.com/containers/storage/pkg')
6 files changed, 133 insertions, 85 deletions
diff --git a/vendor/github.com/containers/storage/pkg/archive/changes_other.go b/vendor/github.com/containers/storage/pkg/archive/changes_other.go index c27930e97..ca272e68f 100644 --- a/vendor/github.com/containers/storage/pkg/archive/changes_other.go +++ b/vendor/github.com/containers/storage/pkg/archive/changes_other.go @@ -92,7 +92,10 @@ func collectFileInfo(sourceDir string, idMappings *idtools.IDMappings) (*FileInf return err } - if s.Dev() != sourceStat.Dev() { + // Don't cross mount points. This ignores file mounts to avoid + // generating a diff which deletes all files following the + // mount. + if s.Dev() != sourceStat.Dev() && s.IsDir() { return filepath.SkipDir } diff --git a/vendor/github.com/containers/storage/pkg/chunked/cache_linux.go b/vendor/github.com/containers/storage/pkg/chunked/cache_linux.go index cd13212e6..56c30e267 100644 --- a/vendor/github.com/containers/storage/pkg/chunked/cache_linux.go +++ b/vendor/github.com/containers/storage/pkg/chunked/cache_linux.go @@ -15,6 +15,7 @@ import ( "unsafe" storage "github.com/containers/storage" + graphdriver "github.com/containers/storage/drivers" "github.com/containers/storage/pkg/chunked/internal" "github.com/containers/storage/pkg/ioutils" jsoniter "github.com/json-iterator/go" @@ -109,7 +110,7 @@ func (c *layersCache) load() error { } bigData, err := c.store.LayerBigData(r.ID, cacheKey) - // if the cache areadly exists, read and use it + // if the cache already exists, read and use it if err == nil { defer bigData.Close() metadata, err := readMetadataFromCache(bigData) @@ -122,6 +123,23 @@ func (c *layersCache) load() error { return err } + var lcd chunkedLayerData + + clFile, err := c.store.LayerBigData(r.ID, chunkedLayerDataKey) + if err != nil && !errors.Is(err, os.ErrNotExist) { + return err + } + if clFile != nil { + cl, err := io.ReadAll(clFile) + if err != nil { + return fmt.Errorf("open manifest file for layer %q: %w", r.ID, err) + } + json := jsoniter.ConfigCompatibleWithStandardLibrary + if err := json.Unmarshal(cl, &lcd); err != nil { + return err + } + } + // otherwise create it from the layer TOC. manifestReader, err := c.store.LayerBigData(r.ID, bigDataKey) if err != nil { @@ -134,7 +152,7 @@ func (c *layersCache) load() error { return fmt.Errorf("open manifest file for layer %q: %w", r.ID, err) } - metadata, err := writeCache(manifest, r.ID, c.store) + metadata, err := writeCache(manifest, lcd.Format, r.ID, c.store) if err == nil { c.addLayer(r.ID, metadata) } @@ -211,13 +229,13 @@ type setBigData interface { // - digest(file.payload)) // - digest(digest(file.payload) + file.UID + file.GID + file.mode + file.xattrs) // - digest(i) for each i in chunks(file payload) -func writeCache(manifest []byte, id string, dest setBigData) (*metadata, error) { +func writeCache(manifest []byte, format graphdriver.DifferOutputFormat, id string, dest setBigData) (*metadata, error) { var vdata bytes.Buffer tagLen := 0 digestLen := 0 var tagsBuffer bytes.Buffer - toc, err := prepareMetadata(manifest) + toc, err := prepareMetadata(manifest, format) if err != nil { return nil, err } @@ -396,7 +414,7 @@ func readMetadataFromCache(bigData io.Reader) (*metadata, error) { }, nil } -func prepareMetadata(manifest []byte) ([]*internal.FileMetadata, error) { +func prepareMetadata(manifest []byte, format graphdriver.DifferOutputFormat) ([]*internal.FileMetadata, error) { toc, err := unmarshalToc(manifest) if err != nil { // ignore errors here. They might be caused by a different manifest format. @@ -404,6 +422,17 @@ func prepareMetadata(manifest []byte) ([]*internal.FileMetadata, error) { return nil, nil //nolint: nilnil } + switch format { + case graphdriver.DifferOutputFormatDir: + case graphdriver.DifferOutputFormatFlat: + toc.Entries, err = makeEntriesFlat(toc.Entries) + if err != nil { + return nil, err + } + default: + return nil, fmt.Errorf("unknown format %q", format) + } + var r []*internal.FileMetadata chunkSeen := make(map[string]bool) for i := range toc.Entries { @@ -420,6 +449,7 @@ func prepareMetadata(manifest []byte) ([]*internal.FileMetadata, error) { chunkSeen[cd] = true } } + return r, nil } diff --git a/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go b/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go index a80b28fb5..f13056082 100644 --- a/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go +++ b/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go @@ -28,6 +28,7 @@ import ( "github.com/containers/storage/pkg/system" "github.com/containers/storage/types" securejoin "github.com/cyphar/filepath-securejoin" + jsoniter "github.com/json-iterator/go" "github.com/klauspost/compress/zstd" "github.com/klauspost/pgzip" digest "github.com/opencontainers/go-digest" @@ -41,6 +42,8 @@ const ( newFileFlags = (unix.O_CREAT | unix.O_TRUNC | unix.O_EXCL | unix.O_WRONLY) containersOverrideXattr = "user.containers.override_stat" bigDataKey = "zstd-chunked-manifest" + chunkedData = "zstd-chunked-data" + chunkedLayerDataKey = "zstd-chunked-layer-data" fileTypeZstdChunked = iota fileTypeEstargz @@ -73,6 +76,11 @@ var xattrsToIgnore = map[string]interface{}{ "security.selinux": true, } +// chunkedLayerData is used to store additional information about the layer +type chunkedLayerData struct { + Format graphdriver.DifferOutputFormat `json:"format"` +} + func timeToTimespec(time *time.Time) (ts unix.Timespec) { if time == nil || time.IsZero() { // Return UTIME_OMIT special value @@ -241,7 +249,7 @@ func copyFileFromOtherLayer(file *internal.FileMetadata, source string, name str srcFile, err := openFileUnderRoot(name, srcDirfd, unix.O_RDONLY, 0) if err != nil { - return false, nil, 0, fmt.Errorf("open source file under target rootfs: %w", err) + return false, nil, 0, fmt.Errorf("open source file under target rootfs (%s): %w", name, err) } defer srcFile.Close() @@ -844,7 +852,14 @@ func openDestinationFile(dirfd int, metadata *internal.FileMetadata, options *ar }, nil } -func (d *destinationFile) Close() error { +func (d *destinationFile) Close() (Err error) { + defer func() { + err := d.file.Close() + if Err == nil { + Err = err + } + }() + manifestChecksum, err := digest.Parse(d.metadata.Digest) if err != nil { return err @@ -1317,7 +1332,39 @@ func (c *chunkedDiffer) findAndCopyFile(dirfd int, r *internal.FileMetadata, cop return false, nil } -func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions) (graphdriver.DriverWithDifferOutput, error) { +func makeEntriesFlat(mergedEntries []internal.FileMetadata) ([]internal.FileMetadata, error) { + var new []internal.FileMetadata + + hashes := make(map[string]string) + for i := range mergedEntries { + if mergedEntries[i].Type != TypeReg { + continue + } + if mergedEntries[i].Digest == "" { + if mergedEntries[i].Size != 0 { + return nil, fmt.Errorf("missing digest for %q", mergedEntries[i].Name) + } + continue + } + digest, err := digest.Parse(mergedEntries[i].Digest) + if err != nil { + return nil, err + } + d := digest.Encoded() + + if hashes[d] != "" { + continue + } + hashes[d] = d + + mergedEntries[i].Name = fmt.Sprintf("%s/%s", d[0:2], d[2:]) + + new = append(new, mergedEntries[i]) + } + return new, nil +} + +func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions, differOpts *graphdriver.DifferOptions) (graphdriver.DriverWithDifferOutput, error) { defer c.layersCache.release() defer func() { if c.zstdReader != nil { @@ -1325,11 +1372,21 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions) (gra } }() + lcd := chunkedLayerData{ + Format: differOpts.Format, + } + + json := jsoniter.ConfigCompatibleWithStandardLibrary + lcdBigData, err := json.Marshal(lcd) + if err != nil { + return graphdriver.DriverWithDifferOutput{}, err + } output := graphdriver.DriverWithDifferOutput{ Differ: c, TarSplit: c.tarSplit, BigData: map[string][]byte{ - bigDataKey: c.manifest, + bigDataKey: c.manifest, + chunkedLayerDataKey: lcdBigData, }, TOCDigest: c.tocDigest, } @@ -1389,6 +1446,21 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions) (gra } defer unix.Close(dirfd) + if differOpts != nil && differOpts.Format == graphdriver.DifferOutputFormatFlat { + mergedEntries, err = makeEntriesFlat(mergedEntries) + if err != nil { + return output, err + } + createdDirs := make(map[string]struct{}) + for _, e := range mergedEntries { + d := e.Name[0:2] + if _, found := createdDirs[d]; !found { + unix.Mkdirat(dirfd, d, 0o755) + createdDirs[d] = struct{}{} + } + } + } + // hardlinks can point to missing files. So create them after all files // are retrieved var hardLinks []hardLinkToCreate diff --git a/vendor/github.com/containers/storage/pkg/idmap/idmapped_utils.go b/vendor/github.com/containers/storage/pkg/idmap/idmapped_utils.go index 68c8c867d..87484d95b 100644 --- a/vendor/github.com/containers/storage/pkg/idmap/idmapped_utils.go +++ b/vendor/github.com/containers/storage/pkg/idmap/idmapped_utils.go @@ -8,75 +8,11 @@ import ( "os" "runtime" "syscall" - "unsafe" "github.com/containers/storage/pkg/idtools" "golang.org/x/sys/unix" ) -type attr struct { - attrSet uint64 - attrClr uint64 - propagation uint64 - userNs uint64 -} - -// openTree is a wrapper for the open_tree syscall -func openTree(path string, flags int) (fd int, err error) { - var _p0 *byte - - if _p0, err = syscall.BytePtrFromString(path); err != nil { - return 0, err - } - - r, _, e1 := syscall.Syscall6(uintptr(unix.SYS_OPEN_TREE), uintptr(0), uintptr(unsafe.Pointer(_p0)), - uintptr(flags), 0, 0, 0) - if e1 != 0 { - err = e1 - } - return int(r), err -} - -// moveMount is a wrapper for the move_mount syscall. -func moveMount(fdTree int, target string) (err error) { - var _p0, _p1 *byte - - empty := "" - - if _p0, err = syscall.BytePtrFromString(target); err != nil { - return err - } - if _p1, err = syscall.BytePtrFromString(empty); err != nil { - return err - } - - flags := unix.MOVE_MOUNT_F_EMPTY_PATH - - _, _, e1 := syscall.Syscall6(uintptr(unix.SYS_MOVE_MOUNT), - uintptr(fdTree), uintptr(unsafe.Pointer(_p1)), - 0, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) - if e1 != 0 { - err = e1 - } - return -} - -// mountSetAttr is a wrapper for the mount_setattr syscall -func mountSetAttr(dfd int, path string, flags uint, attr *attr, size uint) (err error) { - var _p0 *byte - - if _p0, err = syscall.BytePtrFromString(path); err != nil { - return err - } - - _, _, e1 := syscall.Syscall6(uintptr(unix.SYS_MOUNT_SETATTR), uintptr(dfd), uintptr(unsafe.Pointer(_p0)), - uintptr(flags), uintptr(unsafe.Pointer(attr)), uintptr(size), 0) - if e1 != 0 { - err = e1 - } - return -} - // CreateIDMappedMount creates a IDMapped bind mount from SOURCE to TARGET using the user namespace // for the PID process. func CreateIDMappedMount(source, target string, pid int) error { @@ -85,29 +21,26 @@ func CreateIDMappedMount(source, target string, pid int) error { if err != nil { return fmt.Errorf("unable to get user ns file descriptor for %q: %w", path, err) } - - var attr attr - attr.attrSet = unix.MOUNT_ATTR_IDMAP - attr.attrClr = 0 - attr.propagation = 0 - attr.userNs = uint64(userNsFile.Fd()) - defer userNsFile.Close() - targetDirFd, err := openTree(source, unix.OPEN_TREE_CLONE) + targetDirFd, err := unix.OpenTree(0, source, unix.OPEN_TREE_CLONE) if err != nil { return err } defer unix.Close(targetDirFd) - if err := mountSetAttr(targetDirFd, "", unix.AT_EMPTY_PATH|unix.AT_RECURSIVE, - &attr, uint(unsafe.Sizeof(attr))); err != nil { + if err := unix.MountSetattr(targetDirFd, "", unix.AT_EMPTY_PATH|unix.AT_RECURSIVE, + &unix.MountAttr{ + Attr_set: unix.MOUNT_ATTR_IDMAP, + Userns_fd: uint64(userNsFile.Fd()), + }); err != nil { return err } if err := os.Mkdir(target, 0o700); err != nil && !os.IsExist(err) { return err } - return moveMount(targetDirFd, target) + + return unix.MoveMount(targetDirFd, "", 0, target, unix.MOVE_MOUNT_F_EMPTY_PATH) } // CreateUsernsProcess forks the current process and creates a user namespace using the specified diff --git a/vendor/github.com/containers/storage/pkg/system/stat_unix.go b/vendor/github.com/containers/storage/pkg/system/stat_unix.go index 47ae899f8..e552e91d7 100644 --- a/vendor/github.com/containers/storage/pkg/system/stat_unix.go +++ b/vendor/github.com/containers/storage/pkg/system/stat_unix.go @@ -7,6 +7,8 @@ import ( "os" "strconv" "syscall" + + "golang.org/x/sys/unix" ) // StatT type contains status of a file. It contains metadata @@ -57,6 +59,10 @@ func (s StatT) Dev() uint64 { return s.dev } +func (s StatT) IsDir() bool { + return (s.mode & unix.S_IFDIR) != 0 +} + // Stat takes a path to a file and returns // a system.StatT type pertaining to that file. // diff --git a/vendor/github.com/containers/storage/pkg/system/stat_windows.go b/vendor/github.com/containers/storage/pkg/system/stat_windows.go index 6d5c6c142..828be2088 100644 --- a/vendor/github.com/containers/storage/pkg/system/stat_windows.go +++ b/vendor/github.com/containers/storage/pkg/system/stat_windows.go @@ -48,6 +48,10 @@ func (s StatT) Dev() uint64 { return 0 } +func (s StatT) IsDir() bool { + return s.Mode().IsDir() +} + // Stat takes a path to a file and returns // a system.StatT type pertaining to that file. // |