summaryrefslogtreecommitdiff
path: root/vendor/github.com/projectatomic/buildah/util.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/projectatomic/buildah/util.go')
-rw-r--r--vendor/github.com/projectatomic/buildah/util.go182
1 files changed, 175 insertions, 7 deletions
diff --git a/vendor/github.com/projectatomic/buildah/util.go b/vendor/github.com/projectatomic/buildah/util.go
index 33b5b9e83..0d05aa8a2 100644
--- a/vendor/github.com/projectatomic/buildah/util.go
+++ b/vendor/github.com/projectatomic/buildah/util.go
@@ -1,15 +1,18 @@
package buildah
import (
+ "bufio"
+ "io"
+ "os"
+ "strconv"
+ "strings"
+
+ "github.com/containers/storage/pkg/archive"
"github.com/containers/storage/pkg/chrootarchive"
+ "github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/reexec"
-)
-
-var (
- // CopyWithTar defines the copy method to use.
- copyWithTar = chrootarchive.NewArchiver(nil).CopyWithTar
- copyFileWithTar = chrootarchive.NewArchiver(nil).CopyFileWithTar
- untarPath = chrootarchive.NewArchiver(nil).UntarPath
+ rspec "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/pkg/errors"
)
// InitReexec is a wrapper for reexec.Init(). It should be called at
@@ -32,3 +35,168 @@ func copyStringSlice(s []string) []string {
copy(t, s)
return t
}
+
+func stringInSlice(s string, slice []string) bool {
+ for _, v := range slice {
+ if v == s {
+ return true
+ }
+ }
+ return false
+}
+
+func convertStorageIDMaps(UIDMap, GIDMap []idtools.IDMap) ([]rspec.LinuxIDMapping, []rspec.LinuxIDMapping) {
+ uidmap := make([]rspec.LinuxIDMapping, 0, len(UIDMap))
+ gidmap := make([]rspec.LinuxIDMapping, 0, len(GIDMap))
+ for _, m := range UIDMap {
+ uidmap = append(uidmap, rspec.LinuxIDMapping{
+ HostID: uint32(m.HostID),
+ ContainerID: uint32(m.ContainerID),
+ Size: uint32(m.Size),
+ })
+ }
+ for _, m := range GIDMap {
+ gidmap = append(gidmap, rspec.LinuxIDMapping{
+ HostID: uint32(m.HostID),
+ ContainerID: uint32(m.ContainerID),
+ Size: uint32(m.Size),
+ })
+ }
+ return uidmap, gidmap
+}
+
+func convertRuntimeIDMaps(UIDMap, GIDMap []rspec.LinuxIDMapping) ([]idtools.IDMap, []idtools.IDMap) {
+ uidmap := make([]idtools.IDMap, 0, len(UIDMap))
+ gidmap := make([]idtools.IDMap, 0, len(GIDMap))
+ for _, m := range UIDMap {
+ uidmap = append(uidmap, idtools.IDMap{
+ HostID: int(m.HostID),
+ ContainerID: int(m.ContainerID),
+ Size: int(m.Size),
+ })
+ }
+ for _, m := range GIDMap {
+ gidmap = append(gidmap, idtools.IDMap{
+ HostID: int(m.HostID),
+ ContainerID: int(m.ContainerID),
+ Size: int(m.Size),
+ })
+ }
+ return uidmap, gidmap
+}
+
+// copyFileWithTar returns a function which copies a single file from outside
+// of any container into our working container, mapping permissions using the
+// container's ID maps, possibly overridden using the passed-in chownOpts
+func (b *Builder) copyFileWithTar(chownOpts *idtools.IDPair) func(src, dest string) error {
+ convertedUIDMap, convertedGIDMap := convertRuntimeIDMaps(b.IDMappingOptions.UIDMap, b.IDMappingOptions.GIDMap)
+ untarMappings := idtools.NewIDMappingsFromMaps(convertedUIDMap, convertedGIDMap)
+ archiver := chrootarchive.NewArchiverWithChown(nil, chownOpts, untarMappings)
+ return archiver.CopyFileWithTar
+}
+
+// copyWithTar returns a function which copies a directory tree from outside of
+// any container into our working container, mapping permissions using the
+// container's ID maps, possibly overridden using the passed-in chownOpts
+func (b *Builder) copyWithTar(chownOpts *idtools.IDPair) func(src, dest string) error {
+ convertedUIDMap, convertedGIDMap := convertRuntimeIDMaps(b.IDMappingOptions.UIDMap, b.IDMappingOptions.GIDMap)
+ untarMappings := idtools.NewIDMappingsFromMaps(convertedUIDMap, convertedGIDMap)
+ archiver := chrootarchive.NewArchiverWithChown(nil, chownOpts, untarMappings)
+ return archiver.CopyWithTar
+}
+
+// untarPath returns a function which extracts an archive in a specified
+// location into our working container, mapping permissions using the
+// container's ID maps, possibly overridden using the passed-in chownOpts
+func (b *Builder) untarPath(chownOpts *idtools.IDPair) func(src, dest string) error {
+ convertedUIDMap, convertedGIDMap := convertRuntimeIDMaps(b.IDMappingOptions.UIDMap, b.IDMappingOptions.GIDMap)
+ untarMappings := idtools.NewIDMappingsFromMaps(convertedUIDMap, convertedGIDMap)
+ archiver := chrootarchive.NewArchiverWithChown(nil, chownOpts, untarMappings)
+ return archiver.UntarPath
+}
+
+// tarPath returns a function which creates an archive of a specified
+// location in the container's filesystem, mapping permissions using the
+// container's ID maps
+func (b *Builder) tarPath() func(path string) (io.ReadCloser, error) {
+ convertedUIDMap, convertedGIDMap := convertRuntimeIDMaps(b.IDMappingOptions.UIDMap, b.IDMappingOptions.GIDMap)
+ tarMappings := idtools.NewIDMappingsFromMaps(convertedUIDMap, convertedGIDMap)
+ return func(path string) (io.ReadCloser, error) {
+ return archive.TarWithOptions(path, &archive.TarOptions{
+ Compression: archive.Uncompressed,
+ UIDMaps: tarMappings.UIDs(),
+ GIDMaps: tarMappings.GIDs(),
+ })
+ }
+}
+
+// getProcIDMappings reads mappings from the named node under /proc.
+func getProcIDMappings(path string) ([]rspec.LinuxIDMapping, error) {
+ var mappings []rspec.LinuxIDMapping
+ f, err := os.Open(path)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error reading ID mappings from %q", path)
+ }
+ defer f.Close()
+ scanner := bufio.NewScanner(f)
+ for scanner.Scan() {
+ line := scanner.Text()
+ fields := strings.Fields(line)
+ if len(fields) != 3 {
+ return nil, errors.Errorf("line %q from %q has %d fields, not 3", line, path, len(fields))
+ }
+ cid, err := strconv.ParseUint(fields[0], 10, 32)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error parsing container ID value %q from line %q in %q", fields[0], line, path)
+ }
+ hid, err := strconv.ParseUint(fields[1], 10, 32)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error parsing host ID value %q from line %q in %q", fields[1], line, path)
+ }
+ size, err := strconv.ParseUint(fields[2], 10, 32)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error parsing size value %q from line %q in %q", fields[2], line, path)
+ }
+ mappings = append(mappings, rspec.LinuxIDMapping{ContainerID: uint32(cid), HostID: uint32(hid), Size: uint32(size)})
+ }
+ return mappings, nil
+}
+
+// getHostIDs uses ID mappings to compute the host-level IDs that will
+// correspond to a UID/GID pair in the container.
+func getHostIDs(uidmap, gidmap []rspec.LinuxIDMapping, uid, gid uint32) (uint32, uint32, error) {
+ uidMapped := true
+ for _, m := range uidmap {
+ uidMapped = false
+ if uid >= m.ContainerID && uid < m.ContainerID+m.Size {
+ uid = (uid - m.ContainerID) + m.HostID
+ uidMapped = true
+ break
+ }
+ }
+ if !uidMapped {
+ return 0, 0, errors.Errorf("container uses ID mappings, but doesn't map UID %d", uid)
+ }
+ gidMapped := true
+ for _, m := range gidmap {
+ gidMapped = false
+ if gid >= m.ContainerID && gid < m.ContainerID+m.Size {
+ gid = (gid - m.ContainerID) + m.HostID
+ gidMapped = true
+ break
+ }
+ }
+ if !gidMapped {
+ return 0, 0, errors.Errorf("container uses ID mappings, but doesn't map GID %d", gid)
+ }
+ return uid, gid, nil
+}
+
+// getHostRootIDs uses ID mappings in spec to compute the host-level IDs that will
+// correspond to UID/GID 0/0 in the container.
+func getHostRootIDs(spec *rspec.Spec) (uint32, uint32, error) {
+ if spec.Linux == nil {
+ return 0, 0, nil
+ }
+ return getHostIDs(spec.Linux.UIDMappings, spec.Linux.GIDMappings, 0, 0)
+}