The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/7056

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
- Adds support for resetting hard link map.
- Adds support for custom file names in tarball.
From cbe0c96f28ff79f6ce1514ddd6a6e0b7682ff767 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 18 Mar 2020 11:14:09 +0000
Subject: [PATCH 1/5] shared/containerwriter: Renames to instancewriter

And uses errors package for error wrapping

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 .../instance_tar_writer.go}                   | 62 +++++++++----------
 1 file changed, 30 insertions(+), 32 deletions(-)
 rename shared/{containerwriter/container_tar_writer.go => 
instancewriter/instance_tar_writer.go} (51%)

diff --git a/shared/containerwriter/container_tar_writer.go 
b/shared/instancewriter/instance_tar_writer.go
similarity index 51%
rename from shared/containerwriter/container_tar_writer.go
rename to shared/instancewriter/instance_tar_writer.go
index 7ebbf43546..2199cbadfe 100644
--- a/shared/containerwriter/container_tar_writer.go
+++ b/shared/instancewriter/instance_tar_writer.go
@@ -1,35 +1,35 @@
-package containerwriter
+package instancewriter
 
 import (
        "archive/tar"
-       "fmt"
        "io"
        "os"
        "strings"
 
+       "github.com/pkg/errors"
+
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/idmap"
 )
 
-// ContainerTarWriter provides a TarWriter implementation that handles
-// ID shifting and hardlink tracking for containers
-type ContainerTarWriter struct {
+// InstanceTarWriter provides a TarWriter implementation that handles ID 
shifting and hardlink tracking.
+type InstanceTarWriter struct {
        tarWriter *tar.Writer
        idmapSet  *idmap.IdmapSet
        linkMap   map[uint64]string
 }
 
-// NewContainerTarWriter returns a ContainerTarWriter for the provided target 
Writer and id map
-func NewContainerTarWriter(writer io.Writer, idmapSet *idmap.IdmapSet) 
*ContainerTarWriter {
-       ctw := new(ContainerTarWriter)
+// NewInstanceTarWriter returns a ContainerTarWriter for the provided target 
Writer and id map.
+func NewInstanceTarWriter(writer io.Writer, idmapSet *idmap.IdmapSet) 
*InstanceTarWriter {
+       ctw := new(InstanceTarWriter)
        ctw.tarWriter = tar.NewWriter(writer)
        ctw.idmapSet = idmapSet
        ctw.linkMap = map[uint64]string{}
        return ctw
 }
 
-// WriteFile adds a file to the tarball
-func (ctw *ContainerTarWriter) WriteFile(offset int, path string, fi 
os.FileInfo) error {
+// WriteFile adds a file to the tarball.
+func (ctw *InstanceTarWriter) WriteFile(offset int, path string, fi 
os.FileInfo) error {
        var err error
        var major, minor uint32
        var nlink int
@@ -39,18 +39,18 @@ func (ctw *ContainerTarWriter) WriteFile(offset int, path 
string, fi os.FileInfo
        if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
                link, err = os.Readlink(path)
                if err != nil {
-                       return fmt.Errorf("failed to resolve symlink: %s", err)
+                       return errors.Wrap(err, "Failed to resolve symlink")
                }
        }
 
-       // Sockets cannot be stored in tarballs, just skip them (consistent 
with tar)
+       // Sockets cannot be stored in tarballs, just skip them (consistent 
with tar).
        if fi.Mode()&os.ModeSocket == os.ModeSocket {
                return nil
        }
 
        hdr, err := tar.FileInfoHeader(fi, link)
        if err != nil {
-               return fmt.Errorf("failed to create tar info header: %s", err)
+               return errors.Wrap(err, "Failed to create tar info header")
        }
 
        hdr.Name = path[offset:]
@@ -62,25 +62,23 @@ func (ctw *ContainerTarWriter) WriteFile(offset int, path 
string, fi os.FileInfo
 
        hdr.Uid, hdr.Gid, major, minor, ino, nlink, err = 
shared.GetFileStat(path)
        if err != nil {
-               return fmt.Errorf("failed to get file stat: %s", err)
+               return errors.Wrap(err, "Failed to get file stat")
        }
 
-       // Unshift the id under rootfs/ for unpriv containers
-       if strings.HasPrefix(hdr.Name, "rootfs") {
-               if ctw.idmapSet != nil {
-                       hUID, hGID := ctw.idmapSet.ShiftFromNs(int64(hdr.Uid), 
int64(hdr.Gid))
-                       hdr.Uid = int(hUID)
-                       hdr.Gid = int(hGID)
-                       if hdr.Uid == -1 || hdr.Gid == -1 {
-                               return nil
-                       }
+       // Unshift the id under rootfs/ for unpriv containers.
+       if strings.HasPrefix(hdr.Name, "rootfs") && ctw.idmapSet != nil {
+               hUID, hGID := ctw.idmapSet.ShiftFromNs(int64(hdr.Uid), 
int64(hdr.Gid))
+               hdr.Uid = int(hUID)
+               hdr.Gid = int(hGID)
+               if hdr.Uid == -1 || hdr.Gid == -1 {
+                       return nil
                }
        }
 
        hdr.Devmajor = int64(major)
        hdr.Devminor = int64(minor)
 
-       // If it's a hardlink we've already seen use the old name
+       // If it's a hardlink we've already seen use the old name.
        if fi.Mode().IsRegular() && nlink > 1 {
                if firstPath, found := ctw.linkMap[ino]; found {
                        hdr.Typeflag = tar.TypeLink
@@ -91,38 +89,38 @@ func (ctw *ContainerTarWriter) WriteFile(offset int, path 
string, fi os.FileInfo
                }
        }
 
-       // Handle xattrs (for real files only)
+       // Handle xattrs (for real files only).
        if link == "" {
                hdr.Xattrs, err = shared.GetAllXattr(path)
                if err != nil {
-                       return fmt.Errorf("failed to read xattr for '%s': %s", 
path, err)
+                       return errors.Wrapf(err, "Failed to read xattr for %q", 
path)
                }
        }
 
        if err := ctw.tarWriter.WriteHeader(hdr); err != nil {
-               return fmt.Errorf("failed to write tar header: %s", err)
+               return errors.Wrap(err, "Failed to write tar header")
        }
 
        if hdr.Typeflag == tar.TypeReg {
                f, err := os.Open(path)
                if err != nil {
-                       return fmt.Errorf("failed to open the file: %s", err)
+                       return errors.Wrap(err, "Failed to open the file")
                }
                defer f.Close()
 
                if _, err := io.Copy(ctw.tarWriter, f); err != nil {
-                       return fmt.Errorf("failed to copy file content: %s", 
err)
+                       return errors.Wrap(err, "Failed to copy file content")
                }
        }
 
        return nil
 }
 
-// Close finishes writing the tarball
-func (ctw *ContainerTarWriter) Close() error {
+// Close finishes writing the tarball.
+func (ctw *InstanceTarWriter) Close() error {
        err := ctw.tarWriter.Close()
        if err != nil {
-               return fmt.Errorf("failed to close tar writer: %s", err)
+               return errors.Wrap(err, "Failed to close tar writer")
        }
        return nil
 }

From f15d07c0f588e12ed8123acdbb32e9275afb078f Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 18 Mar 2020 11:20:42 +0000
Subject: [PATCH 2/5] lxd/instance/drivers: instancetarwriter usage

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/instance/drivers/driver_lxc.go  | 40 +++++++++++++--------------
 lxd/instance/drivers/driver_qemu.go | 42 ++++++++++++++---------------
 2 files changed, 41 insertions(+), 41 deletions(-)

diff --git a/lxd/instance/drivers/driver_lxc.go 
b/lxd/instance/drivers/driver_lxc.go
index 0507b5be8a..6b052edf60 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -48,8 +48,8 @@ import (
        "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
-       "github.com/lxc/lxd/shared/containerwriter"
        "github.com/lxc/lxd/shared/idmap"
+       "github.com/lxc/lxd/shared/instancewriter"
        log "github.com/lxc/lxd/shared/log15"
        "github.com/lxc/lxd/shared/logger"
        "github.com/lxc/lxd/shared/netutils"
@@ -4561,7 +4561,7 @@ func (c *lxc) Export(w io.Writer, properties 
map[string]string) error {
        }
 
        // Create the tarball.
-       ctw := containerwriter.NewContainerTarWriter(w, idmap)
+       tarWriter := instancewriter.NewInstanceTarWriter(w, idmap)
 
        // Keep track of the first path we saw for each path with nlink>1.
        cDir := c.Path()
@@ -4574,7 +4574,7 @@ func (c *lxc) Export(w io.Writer, properties 
map[string]string) error {
                        return err
                }
 
-               err = ctw.WriteFile(offset, path, fi)
+               err = tarWriter.WriteFile(offset, path, fi)
                if err != nil {
                        logger.Debugf("Error tarring up %s: %s", path, err)
                        return err
@@ -4588,7 +4588,7 @@ func (c *lxc) Export(w io.Writer, properties 
map[string]string) error {
                // Generate a new metadata.yaml.
                tempDir, err := ioutil.TempDir("", "lxd_lxd_metadata_")
                if err != nil {
-                       ctw.Close()
+                       tarWriter.Close()
                        logger.Error("Failed exporting instance", ctxMap)
                        return err
                }
@@ -4600,7 +4600,7 @@ func (c *lxc) Export(w io.Writer, properties 
map[string]string) error {
                        parentName, _, _ := 
shared.InstanceGetParentAndSnapshotName(c.name)
                        parent, err := instance.LoadByProjectAndName(c.state, 
c.project, parentName)
                        if err != nil {
-                               ctw.Close()
+                               tarWriter.Close()
                                logger.Error("Failed exporting instance", 
ctxMap)
                                return err
                        }
@@ -4626,7 +4626,7 @@ func (c *lxc) Export(w io.Writer, properties 
map[string]string) error {
 
                data, err := yaml.Marshal(&meta)
                if err != nil {
-                       ctw.Close()
+                       tarWriter.Close()
                        logger.Error("Failed exporting instance", ctxMap)
                        return err
                }
@@ -4635,21 +4635,21 @@ func (c *lxc) Export(w io.Writer, properties 
map[string]string) error {
                fnam = filepath.Join(tempDir, "metadata.yaml")
                err = ioutil.WriteFile(fnam, data, 0644)
                if err != nil {
-                       ctw.Close()
+                       tarWriter.Close()
                        logger.Error("Failed exporting instance", ctxMap)
                        return err
                }
 
                fi, err := os.Lstat(fnam)
                if err != nil {
-                       ctw.Close()
+                       tarWriter.Close()
                        logger.Error("Failed exporting instance", ctxMap)
                        return err
                }
 
                tmpOffset := len(path.Dir(fnam)) + 1
-               if err := ctw.WriteFile(tmpOffset, fnam, fi); err != nil {
-                       ctw.Close()
+               if err := tarWriter.WriteFile(tmpOffset, fnam, fi); err != nil {
+                       tarWriter.Close()
                        logger.Debugf("Error writing to tarfile: %s", err)
                        logger.Error("Failed exporting instance", ctxMap)
                        return err
@@ -4659,7 +4659,7 @@ func (c *lxc) Export(w io.Writer, properties 
map[string]string) error {
                        // Parse the metadata.
                        content, err := ioutil.ReadFile(fnam)
                        if err != nil {
-                               ctw.Close()
+                               tarWriter.Close()
                                logger.Error("Failed exporting instance", 
ctxMap)
                                return err
                        }
@@ -4667,7 +4667,7 @@ func (c *lxc) Export(w io.Writer, properties 
map[string]string) error {
                        metadata := new(api.ImageMetadata)
                        err = yaml.Unmarshal(content, &metadata)
                        if err != nil {
-                               ctw.Close()
+                               tarWriter.Close()
                                logger.Error("Failed exporting instance", 
ctxMap)
                                return err
                        }
@@ -4676,7 +4676,7 @@ func (c *lxc) Export(w io.Writer, properties 
map[string]string) error {
                        // Generate a new metadata.yaml.
                        tempDir, err := ioutil.TempDir("", "lxd_lxd_metadata_")
                        if err != nil {
-                               ctw.Close()
+                               tarWriter.Close()
                                logger.Error("Failed exporting instance", 
ctxMap)
                                return err
                        }
@@ -4684,7 +4684,7 @@ func (c *lxc) Export(w io.Writer, properties 
map[string]string) error {
 
                        data, err := yaml.Marshal(&metadata)
                        if err != nil {
-                               ctw.Close()
+                               tarWriter.Close()
                                logger.Error("Failed exporting instance", 
ctxMap)
                                return err
                        }
@@ -4693,7 +4693,7 @@ func (c *lxc) Export(w io.Writer, properties 
map[string]string) error {
                        fnam = filepath.Join(tempDir, "metadata.yaml")
                        err = ioutil.WriteFile(fnam, data, 0644)
                        if err != nil {
-                               ctw.Close()
+                               tarWriter.Close()
                                logger.Error("Failed exporting instance", 
ctxMap)
                                return err
                        }
@@ -4702,7 +4702,7 @@ func (c *lxc) Export(w io.Writer, properties 
map[string]string) error {
                // Include metadata.yaml in the tarball.
                fi, err := os.Lstat(fnam)
                if err != nil {
-                       ctw.Close()
+                       tarWriter.Close()
                        logger.Debugf("Error statting %s during export", fnam)
                        logger.Error("Failed exporting instance", ctxMap)
                        return err
@@ -4710,12 +4710,12 @@ func (c *lxc) Export(w io.Writer, properties 
map[string]string) error {
 
                if properties != nil {
                        tmpOffset := len(path.Dir(fnam)) + 1
-                       err = ctw.WriteFile(tmpOffset, fnam, fi)
+                       err = tarWriter.WriteFile(tmpOffset, fnam, fi)
                } else {
-                       err = ctw.WriteFile(offset, fnam, fi)
+                       err = tarWriter.WriteFile(offset, fnam, fi)
                }
                if err != nil {
-                       ctw.Close()
+                       tarWriter.Close()
                        logger.Debugf("Error writing to tarfile: %s", err)
                        logger.Error("Failed exporting instance", ctxMap)
                        return err
@@ -4740,7 +4740,7 @@ func (c *lxc) Export(w io.Writer, properties 
map[string]string) error {
                }
        }
 
-       err = ctw.Close()
+       err = tarWriter.Close()
        if err != nil {
                logger.Error("Failed exporting instance", ctxMap)
                return err
diff --git a/lxd/instance/drivers/driver_qemu.go 
b/lxd/instance/drivers/driver_qemu.go
index 10d1b86c29..8cf04c6fb0 100644
--- a/lxd/instance/drivers/driver_qemu.go
+++ b/lxd/instance/drivers/driver_qemu.go
@@ -50,7 +50,7 @@ import (
        "github.com/lxc/lxd/lxd/vsock"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
-       "github.com/lxc/lxd/shared/containerwriter"
+       "github.com/lxc/lxd/shared/instancewriter"
        log "github.com/lxc/lxd/shared/log15"
        "github.com/lxc/lxd/shared/logger"
        "github.com/lxc/lxd/shared/osarch"
@@ -2986,7 +2986,7 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
        }
 
        // Create the tarball.
-       ctw := containerwriter.NewContainerTarWriter(w, nil)
+       tarWriter := instancewriter.NewInstanceTarWriter(w, nil)
 
        // Path inside the tar image is the pathname starting after cDir.
        cDir := vm.Path()
@@ -2997,7 +2997,7 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
                        return err
                }
 
-               err = ctw.WriteFile(offset, path, fi)
+               err = tarWriter.WriteFile(offset, path, fi)
                if err != nil {
                        logger.Debugf("Error tarring up %s: %s", path, err)
                        return err
@@ -3012,7 +3012,7 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
                // Generate a new metadata.yaml.
                tempDir, err := ioutil.TempDir("", "lxd_lxd_metadata_")
                if err != nil {
-                       ctw.Close()
+                       tarWriter.Close()
                        logger.Error("Failed exporting instance", ctxMap)
                        return err
                }
@@ -3024,7 +3024,7 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
                        parentName, _, _ := 
shared.InstanceGetParentAndSnapshotName(vm.name)
                        parent, err := instance.LoadByProjectAndName(vm.state, 
vm.project, parentName)
                        if err != nil {
-                               ctw.Close()
+                               tarWriter.Close()
                                logger.Error("Failed exporting instance", 
ctxMap)
                                return err
                        }
@@ -3050,7 +3050,7 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
 
                data, err := yaml.Marshal(&meta)
                if err != nil {
-                       ctw.Close()
+                       tarWriter.Close()
                        logger.Error("Failed exporting instance", ctxMap)
                        return err
                }
@@ -3059,21 +3059,21 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
                fnam = filepath.Join(tempDir, "metadata.yaml")
                err = ioutil.WriteFile(fnam, data, 0644)
                if err != nil {
-                       ctw.Close()
+                       tarWriter.Close()
                        logger.Error("Failed exporting instance", ctxMap)
                        return err
                }
 
                fi, err := os.Lstat(fnam)
                if err != nil {
-                       ctw.Close()
+                       tarWriter.Close()
                        logger.Error("Failed exporting instance", ctxMap)
                        return err
                }
 
                tmpOffset := len(filepath.Dir(fnam)) + 1
-               if err := ctw.WriteFile(tmpOffset, fnam, fi); err != nil {
-                       ctw.Close()
+               if err := tarWriter.WriteFile(tmpOffset, fnam, fi); err != nil {
+                       tarWriter.Close()
                        logger.Error("Failed exporting instance", ctxMap)
                        return err
                }
@@ -3082,7 +3082,7 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
                        // Parse the metadata.
                        content, err := ioutil.ReadFile(fnam)
                        if err != nil {
-                               ctw.Close()
+                               tarWriter.Close()
                                logger.Error("Failed exporting instance", 
ctxMap)
                                return err
                        }
@@ -3090,7 +3090,7 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
                        metadata := new(api.ImageMetadata)
                        err = yaml.Unmarshal(content, &metadata)
                        if err != nil {
-                               ctw.Close()
+                               tarWriter.Close()
                                logger.Error("Failed exporting instance", 
ctxMap)
                                return err
                        }
@@ -3099,7 +3099,7 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
                        // Generate a new metadata.yaml.
                        tempDir, err := ioutil.TempDir("", "lxd_lxd_metadata_")
                        if err != nil {
-                               ctw.Close()
+                               tarWriter.Close()
                                logger.Error("Failed exporting instance", 
ctxMap)
                                return err
                        }
@@ -3107,7 +3107,7 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
 
                        data, err := yaml.Marshal(&metadata)
                        if err != nil {
-                               ctw.Close()
+                               tarWriter.Close()
                                logger.Error("Failed exporting instance", 
ctxMap)
                                return err
                        }
@@ -3116,7 +3116,7 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
                        fnam = filepath.Join(tempDir, "metadata.yaml")
                        err = ioutil.WriteFile(fnam, data, 0644)
                        if err != nil {
-                               ctw.Close()
+                               tarWriter.Close()
                                logger.Error("Failed exporting instance", 
ctxMap)
                                return err
                        }
@@ -3125,7 +3125,7 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
                // Include metadata.yaml in the tarball.
                fi, err := os.Lstat(fnam)
                if err != nil {
-                       ctw.Close()
+                       tarWriter.Close()
                        logger.Debugf("Error statting %s during export", fnam)
                        logger.Error("Failed exporting instance", ctxMap)
                        return err
@@ -3133,12 +3133,12 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
 
                if properties != nil {
                        tmpOffset := len(filepath.Dir(fnam)) + 1
-                       err = ctw.WriteFile(tmpOffset, fnam, fi)
+                       err = tarWriter.WriteFile(tmpOffset, fnam, fi)
                } else {
-                       err = ctw.WriteFile(offset, fnam, fi)
+                       err = tarWriter.WriteFile(offset, fnam, fi)
                }
                if err != nil {
-                       ctw.Close()
+                       tarWriter.Close()
                        logger.Debugf("Error writing to tarfile: %s", err)
                        logger.Error("Failed exporting instance", ctxMap)
                        return err
@@ -3174,7 +3174,7 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
                return err
        }
 
-       err = ctw.WriteFile(len(tmpPath)+1, fPath, fi)
+       err = tarWriter.WriteFile(len(tmpPath)+1, fPath, fi)
        if err != nil {
                return err
        }
@@ -3189,7 +3189,7 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
                }
        }
 
-       err = ctw.Close()
+       err = tarWriter.Close()
        if err != nil {
                logger.Error("Failed exporting instance", ctxMap)
                return err

From f0705d11e03f0b93da204d03774b91e08f23c0d2 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 19 Mar 2020 13:29:22 +0000
Subject: [PATCH 3/5] shared/instancewriter/instance/tar/writer: Modifies
 WriteFile to accept a file name arg

Rather than an offset location from the srcPath name.

This way files can be added to the tarball using an arbitrary name.

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 shared/instancewriter/instance_tar_writer.go | 24 ++++++++++----------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/shared/instancewriter/instance_tar_writer.go 
b/shared/instancewriter/instance_tar_writer.go
index 2199cbadfe..f0390eeed7 100644
--- a/shared/instancewriter/instance_tar_writer.go
+++ b/shared/instancewriter/instance_tar_writer.go
@@ -28,8 +28,8 @@ func NewInstanceTarWriter(writer io.Writer, idmapSet 
*idmap.IdmapSet) *InstanceT
        return ctw
 }
 
-// WriteFile adds a file to the tarball.
-func (ctw *InstanceTarWriter) WriteFile(offset int, path string, fi 
os.FileInfo) error {
+// WriteFile adds a file to the tarball with the specified name using the 
srcPath file as the contents of the file.
+func (ctw *InstanceTarWriter) WriteFile(name string, srcPath string, fi 
os.FileInfo) error {
        var err error
        var major, minor uint32
        var nlink int
@@ -37,9 +37,9 @@ func (ctw *InstanceTarWriter) WriteFile(offset int, path 
string, fi os.FileInfo)
 
        link := ""
        if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
-               link, err = os.Readlink(path)
+               link, err = os.Readlink(srcPath)
                if err != nil {
-                       return errors.Wrap(err, "Failed to resolve symlink")
+                       return errors.Wrapf(err, "Failed to resolve symlink for 
%q", srcPath)
                }
        }
 
@@ -53,16 +53,16 @@ func (ctw *InstanceTarWriter) WriteFile(offset int, path 
string, fi os.FileInfo)
                return errors.Wrap(err, "Failed to create tar info header")
        }
 
-       hdr.Name = path[offset:]
+       hdr.Name = name
        if fi.IsDir() || fi.Mode()&os.ModeSymlink == os.ModeSymlink {
                hdr.Size = 0
        } else {
                hdr.Size = fi.Size()
        }
 
-       hdr.Uid, hdr.Gid, major, minor, ino, nlink, err = 
shared.GetFileStat(path)
+       hdr.Uid, hdr.Gid, major, minor, ino, nlink, err = 
shared.GetFileStat(srcPath)
        if err != nil {
-               return errors.Wrap(err, "Failed to get file stat")
+               return errors.Wrapf(err, "Failed to get file stat %q", srcPath)
        }
 
        // Unshift the id under rootfs/ for unpriv containers.
@@ -91,9 +91,9 @@ func (ctw *InstanceTarWriter) WriteFile(offset int, path 
string, fi os.FileInfo)
 
        // Handle xattrs (for real files only).
        if link == "" {
-               hdr.Xattrs, err = shared.GetAllXattr(path)
+               hdr.Xattrs, err = shared.GetAllXattr(srcPath)
                if err != nil {
-                       return errors.Wrapf(err, "Failed to read xattr for %q", 
path)
+                       return errors.Wrapf(err, "Failed to read xattr for %q", 
srcPath)
                }
        }
 
@@ -102,14 +102,14 @@ func (ctw *InstanceTarWriter) WriteFile(offset int, path 
string, fi os.FileInfo)
        }
 
        if hdr.Typeflag == tar.TypeReg {
-               f, err := os.Open(path)
+               f, err := os.Open(srcPath)
                if err != nil {
-                       return errors.Wrap(err, "Failed to open the file")
+                       return errors.Wrapf(err, "Failed to open file %q", 
srcPath)
                }
                defer f.Close()
 
                if _, err := io.Copy(ctw.tarWriter, f); err != nil {
-                       return errors.Wrap(err, "Failed to copy file content")
+                       return errors.Wrapf(err, "Failed to copy file content 
%q", srcPath)
                }
        }
 

From b52ee57769b9c996f4aaf1332d8ba29efd440f1e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 19 Mar 2020 13:30:11 +0000
Subject: [PATCH 4/5] shared/instancewriter/instance/tar/writer: Adds
 ResetHardLinkMap function

Allows multiple instances and/or snapshots to be added to same tarball 
correctly by allowing the hardlink map to be reset between volumes.

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 shared/instancewriter/instance_tar_writer.go | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/shared/instancewriter/instance_tar_writer.go 
b/shared/instancewriter/instance_tar_writer.go
index f0390eeed7..52a422f9ab 100644
--- a/shared/instancewriter/instance_tar_writer.go
+++ b/shared/instancewriter/instance_tar_writer.go
@@ -28,6 +28,12 @@ func NewInstanceTarWriter(writer io.Writer, idmapSet 
*idmap.IdmapSet) *InstanceT
        return ctw
 }
 
+// ResetHardLinkMap resets the hard link map. Use when copying multiple 
instances (or snapshots) into a tarball.
+// So that the hard link map doesn't work across different instances/snapshots.
+func (ctw *InstanceTarWriter) ResetHardLinkMap() {
+       ctw.linkMap = map[uint64]string{}
+}
+
 // WriteFile adds a file to the tarball with the specified name using the 
srcPath file as the contents of the file.
 func (ctw *InstanceTarWriter) WriteFile(name string, srcPath string, fi 
os.FileInfo) error {
        var err error

From e964ea702dca62a1a8eb71b18b60384acbd3ae13 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 19 Mar 2020 13:53:29 +0000
Subject: [PATCH 5/5] lxd/instance/drivers: instancetarwriter.WriteFile name
 arg usage

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/instance/drivers/driver_lxc.go  |  8 ++++----
 lxd/instance/drivers/driver_qemu.go | 11 ++++++-----
 2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/lxd/instance/drivers/driver_lxc.go 
b/lxd/instance/drivers/driver_lxc.go
index 6b052edf60..4f1e2af9ad 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -4574,7 +4574,7 @@ func (c *lxc) Export(w io.Writer, properties 
map[string]string) error {
                        return err
                }
 
-               err = tarWriter.WriteFile(offset, path, fi)
+               err = tarWriter.WriteFile(path[offset:], path, fi)
                if err != nil {
                        logger.Debugf("Error tarring up %s: %s", path, err)
                        return err
@@ -4648,7 +4648,7 @@ func (c *lxc) Export(w io.Writer, properties 
map[string]string) error {
                }
 
                tmpOffset := len(path.Dir(fnam)) + 1
-               if err := tarWriter.WriteFile(tmpOffset, fnam, fi); err != nil {
+               if err := tarWriter.WriteFile(fnam[tmpOffset:], fnam, fi); err 
!= nil {
                        tarWriter.Close()
                        logger.Debugf("Error writing to tarfile: %s", err)
                        logger.Error("Failed exporting instance", ctxMap)
@@ -4710,9 +4710,9 @@ func (c *lxc) Export(w io.Writer, properties 
map[string]string) error {
 
                if properties != nil {
                        tmpOffset := len(path.Dir(fnam)) + 1
-                       err = tarWriter.WriteFile(tmpOffset, fnam, fi)
+                       err = tarWriter.WriteFile(fnam[tmpOffset:], fnam, fi)
                } else {
-                       err = tarWriter.WriteFile(offset, fnam, fi)
+                       err = tarWriter.WriteFile(fnam[offset:], fnam, fi)
                }
                if err != nil {
                        tarWriter.Close()
diff --git a/lxd/instance/drivers/driver_qemu.go 
b/lxd/instance/drivers/driver_qemu.go
index 8cf04c6fb0..d89ff7d6eb 100644
--- a/lxd/instance/drivers/driver_qemu.go
+++ b/lxd/instance/drivers/driver_qemu.go
@@ -2997,7 +2997,7 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
                        return err
                }
 
-               err = tarWriter.WriteFile(offset, path, fi)
+               err = tarWriter.WriteFile(path[offset:], path, fi)
                if err != nil {
                        logger.Debugf("Error tarring up %s: %s", path, err)
                        return err
@@ -3072,7 +3072,7 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
                }
 
                tmpOffset := len(filepath.Dir(fnam)) + 1
-               if err := tarWriter.WriteFile(tmpOffset, fnam, fi); err != nil {
+               if err := tarWriter.WriteFile(fnam[tmpOffset:], fnam, fi); err 
!= nil {
                        tarWriter.Close()
                        logger.Error("Failed exporting instance", ctxMap)
                        return err
@@ -3133,9 +3133,9 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
 
                if properties != nil {
                        tmpOffset := len(filepath.Dir(fnam)) + 1
-                       err = tarWriter.WriteFile(tmpOffset, fnam, fi)
+                       err = tarWriter.WriteFile(fnam[tmpOffset:], fnam, fi)
                } else {
-                       err = tarWriter.WriteFile(offset, fnam, fi)
+                       err = tarWriter.WriteFile(fnam[offset:], fnam, fi)
                }
                if err != nil {
                        tarWriter.Close()
@@ -3174,7 +3174,8 @@ func (vm *qemu) Export(w io.Writer, properties 
map[string]string) error {
                return err
        }
 
-       err = tarWriter.WriteFile(len(tmpPath)+1, fPath, fi)
+       imgOffset := len(tmpPath) + 1
+       err = tarWriter.WriteFile(fPath[imgOffset:], fPath, fi)
        if err != nil {
                return err
        }
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to