github.com/olljanat/moby@v1.13.1/pkg/archive/archive_linux.go (about)

     1  package archive
     2  
     3  import (
     4  	"archive/tar"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  	"syscall"
     9  
    10  	"github.com/docker/docker/pkg/system"
    11  )
    12  
    13  func getWhiteoutConverter(format WhiteoutFormat) tarWhiteoutConverter {
    14  	if format == OverlayWhiteoutFormat {
    15  		return overlayWhiteoutConverter{}
    16  	}
    17  	return nil
    18  }
    19  
    20  type overlayWhiteoutConverter struct{}
    21  
    22  func (overlayWhiteoutConverter) ConvertWrite(hdr *tar.Header, path string, fi os.FileInfo) (wo *tar.Header, err error) {
    23  	// convert whiteouts to AUFS format
    24  	if fi.Mode()&os.ModeCharDevice != 0 && hdr.Devmajor == 0 && hdr.Devminor == 0 {
    25  		// we just rename the file and make it normal
    26  		dir, filename := filepath.Split(hdr.Name)
    27  		hdr.Name = filepath.Join(dir, WhiteoutPrefix+filename)
    28  		hdr.Mode = 0600
    29  		hdr.Typeflag = tar.TypeReg
    30  		hdr.Size = 0
    31  	}
    32  
    33  	if fi.Mode()&os.ModeDir != 0 {
    34  		// convert opaque dirs to AUFS format by writing an empty file with the prefix
    35  		opaque, err := system.Lgetxattr(path, "trusted.overlay.opaque")
    36  		if err != nil {
    37  			return nil, err
    38  		}
    39  		if len(opaque) == 1 && opaque[0] == 'y' {
    40  			if hdr.Xattrs != nil {
    41  				delete(hdr.Xattrs, "trusted.overlay.opaque")
    42  			}
    43  
    44  			// create a header for the whiteout file
    45  			// it should inherit some properties from the parent, but be a regular file
    46  			wo = &tar.Header{
    47  				Typeflag:   tar.TypeReg,
    48  				Mode:       hdr.Mode & int64(os.ModePerm),
    49  				Name:       filepath.Join(hdr.Name, WhiteoutOpaqueDir),
    50  				Size:       0,
    51  				Uid:        hdr.Uid,
    52  				Uname:      hdr.Uname,
    53  				Gid:        hdr.Gid,
    54  				Gname:      hdr.Gname,
    55  				AccessTime: hdr.AccessTime,
    56  				ChangeTime: hdr.ChangeTime,
    57  			}
    58  		}
    59  	}
    60  
    61  	return
    62  }
    63  
    64  func (overlayWhiteoutConverter) ConvertRead(hdr *tar.Header, path string) (bool, error) {
    65  	base := filepath.Base(path)
    66  	dir := filepath.Dir(path)
    67  
    68  	// if a directory is marked as opaque by the AUFS special file, we need to translate that to overlay
    69  	if base == WhiteoutOpaqueDir {
    70  		if err := syscall.Setxattr(dir, "trusted.overlay.opaque", []byte{'y'}, 0); err != nil {
    71  			return false, err
    72  		}
    73  
    74  		// don't write the file itself
    75  		return false, nil
    76  	}
    77  
    78  	// if a file was deleted and we are using overlay, we need to create a character device
    79  	if strings.HasPrefix(base, WhiteoutPrefix) {
    80  		originalBase := base[len(WhiteoutPrefix):]
    81  		originalPath := filepath.Join(dir, originalBase)
    82  
    83  		if err := syscall.Mknod(originalPath, syscall.S_IFCHR, 0); err != nil {
    84  			return false, err
    85  		}
    86  		if err := os.Chown(originalPath, hdr.Uid, hdr.Gid); err != nil {
    87  			return false, err
    88  		}
    89  
    90  		// don't write the file itself
    91  		return false, nil
    92  	}
    93  
    94  	return true, nil
    95  }