Skip to content

Commit

Permalink
layer unpack: fix whiteout errors on AUFS
Browse files Browse the repository at this point in the history
lstat(2) returns EPERM if you try to get information about a whiteout
path. This is one of the reasons I think that matching the AUFS
semantics is insane.

Ref: opencontainers/image-spec#24
Signed-off-by: Aleksa Sarai <asarai@suse.com>
  • Loading branch information
cyphar committed Nov 11, 2016
1 parent 22401eb commit 2a42128
Showing 1 changed file with 25 additions and 23 deletions.
48 changes: 25 additions & 23 deletions image/layer/tar_extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,27 +138,6 @@ func unpackEntry(root string, hdr *tar.Header, r io.Reader) error {
}()
}

// FIXME: Currently we cannot use os.Link because we have to wait until the
// entire archive has been extracted to be sure that hardlinks will
// work. There are a few ways of solving this, one of which is to
// keep an inode index. For now we don't have any other option than
// to "fake" hardlinks with symlinks.
if hdr.Typeflag == tar.TypeLink {
hdr.Typeflag = tar.TypeSymlink
}

// Get information about the path.
hdrFi := hdr.FileInfo()
fi, err := os.Lstat(path)
if err != nil {
if !os.IsNotExist(err) {
return err
}

// File doesn't exist, just switch fi to the file header.
fi = hdr.FileInfo()
}

// Currently the spec doesn't specify what the hdr.Typeflag of whiteout
// files is meant to be. We specifically only produce regular files
// ('\x00') but it could be possible that someone produces a different
Expand All @@ -173,16 +152,39 @@ func unpackEntry(root string, hdr *tar.Header, r io.Reader) error {
// first place.
if _, err := os.Lstat(path); err != nil {
if os.IsNotExist(err) {
err = fmt.Errorf("unpack entry: encountered whiteout %s: %s", hdr.Name, err)
err = fmt.Errorf("unpack entry: encountered invalid whiteout %s: %s", hdr.Name, err)
}
return err
return fmt.Errorf("unpack entry: error checking whiteout path %s: %s", path, err)
}

// Just remove the path. The defer will reapply the correct parent
// metadata. We have nothing left to do here.
return os.RemoveAll(path)
}

// FIXME: Currently we cannot use os.Link because we have to wait until the
// entire archive has been extracted to be sure that hardlinks will
// work. There are a few ways of solving this, one of which is to
// keep an inode index. For now we don't have any other option than
// to "fake" hardlinks with symlinks.
if hdr.Typeflag == tar.TypeLink {
hdr.Typeflag = tar.TypeSymlink
}

// Get information about the path. This has to be done after we've dealt
// with whiteouts because it turns out that lstat(2) will return EPERM if
// you try to stat a whiteout on AUFS.
hdrFi := hdr.FileInfo()
fi, err := os.Lstat(path)
if err != nil {
if !os.IsNotExist(err) {
return err
}

// File doesn't exist, just switch fi to the file header.
fi = hdr.FileInfo()
}

// If the type of the file has changed, there's nothing we can do other
// than just remove the old path and replace it.
// XXX Is this actually valid according to the spec? Do you need to have a
Expand Down

0 comments on commit 2a42128

Please sign in to comment.