Skip to content

Commit ab6d760

Browse files
committed
builder/dockerfile: ADD with best-effort xattrs
Archives being unpacked by Dockerfiles may have been created on other OSes with different conventions and semantics for xattrs, making them impossible to apply when extracting. Restore the old best-effort xattr behaviour users have come to depend on in the classic builder. Signed-off-by: Cory Snider <[email protected]>
1 parent c87e0ad commit ab6d760

3 files changed

Lines changed: 26 additions & 9 deletions

File tree

builder/dockerfile/copy.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ func performCopyForInfo(dest copyInfo, source copyInfo, options copyFileOptions)
472472
return copyDirectory(archiver, srcPath, destPath, options.identity)
473473
}
474474
if options.decompress && archive.IsArchivePath(srcPath) && !source.noDecompress {
475-
return archiver.UntarPath(srcPath, destPath)
475+
return archiver.UntarPath(srcPath, destPath, archive.WithBestEffortXattrs(true))
476476
}
477477

478478
destExistsAsDir, err := isExistingDirectory(destPath)

layer/layer_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222
func init() {
2323
graphdriver.ApplyUncompressedLayer = archive.UnpackLayer
2424
defaultArchiver := archive.NewDefaultArchiver()
25-
vfs.CopyDir = defaultArchiver.CopyWithTar
25+
vfs.CopyDir = func(src, dst string) error { return defaultArchiver.CopyWithTar(src, dst) }
2626
}
2727

2828
func newVFSGraphDriver(td string) (graphdriver.Driver, error) {

pkg/archive/archive.go

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,7 +1275,7 @@ func untarHandler(tarArchive io.Reader, dest string, options *TarOptions, decomp
12751275

12761276
// TarUntar is a convenience function which calls Tar and Untar, with the output of one piped into the other.
12771277
// If either Tar or Untar fails, TarUntar aborts and returns the error.
1278-
func (archiver *Archiver) TarUntar(src, dst string) error {
1278+
func (archiver *Archiver) TarUntar(src, dst string, opts ...func(*TarOptions)) error {
12791279
archive, err := TarWithOptions(src, &TarOptions{Compression: Uncompressed})
12801280
if err != nil {
12811281
return err
@@ -1284,11 +1284,14 @@ func (archiver *Archiver) TarUntar(src, dst string) error {
12841284
options := &TarOptions{
12851285
IDMap: archiver.IDMapping,
12861286
}
1287+
for _, o := range opts {
1288+
o(options)
1289+
}
12871290
return archiver.Untar(archive, dst, options)
12881291
}
12891292

12901293
// UntarPath untar a file from path to a destination, src is the source tar file path.
1291-
func (archiver *Archiver) UntarPath(src, dst string) error {
1294+
func (archiver *Archiver) UntarPath(src, dst string, opts ...func(*TarOptions)) error {
12921295
archive, err := os.Open(src)
12931296
if err != nil {
12941297
return err
@@ -1297,20 +1300,23 @@ func (archiver *Archiver) UntarPath(src, dst string) error {
12971300
options := &TarOptions{
12981301
IDMap: archiver.IDMapping,
12991302
}
1303+
for _, o := range opts {
1304+
o(options)
1305+
}
13001306
return archiver.Untar(archive, dst, options)
13011307
}
13021308

13031309
// CopyWithTar creates a tar archive of filesystem path `src`, and
13041310
// unpacks it at filesystem path `dst`.
13051311
// The archive is streamed directly with fixed buffering and no
13061312
// intermediary disk IO.
1307-
func (archiver *Archiver) CopyWithTar(src, dst string) error {
1313+
func (archiver *Archiver) CopyWithTar(src, dst string, opts ...func(*TarOptions)) error {
13081314
srcSt, err := os.Stat(src)
13091315
if err != nil {
13101316
return err
13111317
}
13121318
if !srcSt.IsDir() {
1313-
return archiver.CopyFileWithTar(src, dst)
1319+
return archiver.CopyFileWithTar(src, dst, opts...)
13141320
}
13151321

13161322
// if this Archiver is set up with ID mapping we need to create
@@ -1321,13 +1327,13 @@ func (archiver *Archiver) CopyWithTar(src, dst string) error {
13211327
if err := idtools.MkdirAllAndChownNew(dst, 0o755, rootIDs); err != nil {
13221328
return err
13231329
}
1324-
return archiver.TarUntar(src, dst)
1330+
return archiver.TarUntar(src, dst, opts...)
13251331
}
13261332

13271333
// CopyFileWithTar emulates the behavior of the 'cp' command-line
13281334
// for a single file. It copies a regular file from path `src` to
13291335
// path `dst`, and preserves all its metadata.
1330-
func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
1336+
func (archiver *Archiver) CopyFileWithTar(src, dst string, opts ...func(*TarOptions)) (err error) {
13311337
srcSt, err := os.Stat(src)
13321338
if err != nil {
13331339
return err
@@ -1394,7 +1400,11 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
13941400
}
13951401
}()
13961402

1397-
err = archiver.Untar(r, filepath.Dir(dst), nil)
1403+
var options TarOptions
1404+
for _, o := range opts {
1405+
o(&options)
1406+
}
1407+
err = archiver.Untar(r, filepath.Dir(dst), &options)
13981408
if err != nil {
13991409
r.CloseWithError(err)
14001410
}
@@ -1406,6 +1416,13 @@ func (archiver *Archiver) IdentityMapping() idtools.IdentityMapping {
14061416
return archiver.IDMapping
14071417
}
14081418

1419+
// WithBestEffortXattrs sets the BestEffortXattrs option for the Archiver operation.
1420+
func WithBestEffortXattrs(v bool) func(*TarOptions) {
1421+
return func(opts *TarOptions) {
1422+
opts.BestEffortXattrs = v
1423+
}
1424+
}
1425+
14091426
func remapIDs(idMapping idtools.IdentityMapping, hdr *tar.Header) error {
14101427
ids, err := idMapping.ToHost(idtools.Identity{UID: hdr.Uid, GID: hdr.Gid})
14111428
hdr.Uid, hdr.Gid = ids.UID, ids.GID

0 commit comments

Comments
 (0)