c880caae4e
Currently when overlay creates a whiteout file then the overlay2 layer is archived, the correct tar header will be created for the whiteout file, but the tar logic will then attempt to open the file causing a failure. When tar encounters such failures the file is skipped and excluded for the archive, causing the whiteout to be ignored. By skipping the copy of empty files, no open attempt will be made on whiteout files. Fixes #23863 Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
90 lines
2.4 KiB
Go
90 lines
2.4 KiB
Go
package archive
|
|
|
|
import (
|
|
"archive/tar"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"syscall"
|
|
|
|
"github.com/docker/docker/pkg/system"
|
|
)
|
|
|
|
func getWhiteoutConverter(format WhiteoutFormat) tarWhiteoutConverter {
|
|
if format == OverlayWhiteoutFormat {
|
|
return overlayWhiteoutConverter{}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type overlayWhiteoutConverter struct{}
|
|
|
|
func (overlayWhiteoutConverter) ConvertWrite(hdr *tar.Header, path string, fi os.FileInfo) error {
|
|
// convert whiteouts to AUFS format
|
|
if fi.Mode()&os.ModeCharDevice != 0 && hdr.Devmajor == 0 && hdr.Devminor == 0 {
|
|
// we just rename the file and make it normal
|
|
hdr.Name = WhiteoutPrefix + hdr.Name
|
|
hdr.Mode = 0600
|
|
hdr.Typeflag = tar.TypeReg
|
|
hdr.Size = 0
|
|
}
|
|
|
|
if fi.Mode()&os.ModeDir != 0 {
|
|
// convert opaque dirs to AUFS format by writing an empty file with the prefix
|
|
opaque, err := system.Lgetxattr(path, "trusted.overlay.opaque")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if opaque != nil && len(opaque) == 1 && opaque[0] == 'y' {
|
|
// create a header for the whiteout file
|
|
// it should inherit some properties from the parent, but be a regular file
|
|
*hdr = tar.Header{
|
|
Typeflag: tar.TypeReg,
|
|
Mode: hdr.Mode & int64(os.ModePerm),
|
|
Name: filepath.Join(hdr.Name, WhiteoutOpaqueDir),
|
|
Size: 0,
|
|
Uid: hdr.Uid,
|
|
Uname: hdr.Uname,
|
|
Gid: hdr.Gid,
|
|
Gname: hdr.Gname,
|
|
AccessTime: hdr.AccessTime,
|
|
ChangeTime: hdr.ChangeTime,
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (overlayWhiteoutConverter) ConvertRead(hdr *tar.Header, path string) (bool, error) {
|
|
base := filepath.Base(path)
|
|
dir := filepath.Dir(path)
|
|
|
|
// if a directory is marked as opaque by the AUFS special file, we need to translate that to overlay
|
|
if base == WhiteoutOpaqueDir {
|
|
if err := syscall.Setxattr(dir, "trusted.overlay.opaque", []byte{'y'}, 0); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
// don't write the file itself
|
|
return false, nil
|
|
}
|
|
|
|
// 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):]
|
|
originalPath := filepath.Join(dir, originalBase)
|
|
|
|
if err := syscall.Mknod(originalPath, syscall.S_IFCHR, 0); err != nil {
|
|
return false, err
|
|
}
|
|
if err := os.Chown(originalPath, hdr.Uid, hdr.Gid); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
// don't write the file itself
|
|
return false, nil
|
|
}
|
|
|
|
return true, nil
|
|
}
|