archive: preserve hardlinks in Tar and Untar

* integration test for preserving hardlinks

Signed-off-by: Vincent Batts <vbatts@redhat.com>
Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
This commit is contained in:
Vincent Batts 2014-09-15 14:45:53 -04:00
parent 0f0aef0590
commit b17f754fff
3 changed files with 108 additions and 20 deletions

View file

@ -368,11 +368,15 @@ func minor(device uint64) uint64 {
// ExportChanges produces an Archive from the provided changes, relative to dir.
func ExportChanges(dir string, changes []Change) (Archive, error) {
reader, writer := io.Pipe()
tw := tar.NewWriter(writer)
go func() {
twBuf := pools.BufioWriter32KPool.Get(nil)
defer pools.BufioWriter32KPool.Put(twBuf)
ta := &tarAppender{
TarWriter: tar.NewWriter(writer),
Buffer: pools.BufioWriter32KPool.Get(nil),
SeenFiles: make(map[uint64]string),
}
// this buffer is needed for the duration of this piped stream
defer pools.BufioWriter32KPool.Put(ta.Buffer)
// In general we log errors here but ignore them because
// during e.g. a diff operation the container can continue
// mutating the filesystem and we can see transient errors
@ -390,19 +394,19 @@ func ExportChanges(dir string, changes []Change) (Archive, error) {
AccessTime: timestamp,
ChangeTime: timestamp,
}
if err := tw.WriteHeader(hdr); err != nil {
if err := ta.TarWriter.WriteHeader(hdr); err != nil {
log.Debugf("Can't write whiteout header: %s", err)
}
} else {
path := filepath.Join(dir, change.Path)
if err := addTarFile(path, change.Path[1:], tw, twBuf); err != nil {
if err := ta.addTarFile(path, change.Path[1:]); err != nil {
log.Debugf("Can't add file %s to tar: %s", path, err)
}
}
}
// Make sure to check the error on Close.
if err := tw.Close(); err != nil {
if err := ta.TarWriter.Close(); err != nil {
log.Debugf("Can't close layer: %s", err)
}
writer.Close()