From 1e3c9a2c11552a995d1f42c336f5c1edb30a582c Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sat, 24 Oct 2020 18:38:30 +0200 Subject: [PATCH] dump: Fix file permission to tar mapping The file permissions included a go specific directory bit which accidentially forced the usage of the GNU header format. This leads to problems with 7zip on Windows or when extended attributes are used. --- internal/dump/tar.go | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/internal/dump/tar.go b/internal/dump/tar.go index 86786654a..fe08e8825 100644 --- a/internal/dump/tar.go +++ b/internal/dump/tar.go @@ -4,6 +4,7 @@ import ( "archive/tar" "context" "io" + "os" "path" "path/filepath" "strings" @@ -65,6 +66,15 @@ func tarTree(ctx context.Context, repo restic.Repository, rootNode *restic.Node, return err } +// copied from archive/tar.FileInfoHeader +const ( + // Mode constants from the USTAR spec: + // See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_06 + c_ISUID = 04000 // Set uid + c_ISGID = 02000 // Set gid + c_ISVTX = 01000 // Save text (sticky bit) +) + func tarNode(ctx context.Context, tw *tar.Writer, node *restic.Node, repo restic.Repository) error { relPath, err := filepath.Rel("/", node.Path) if err != nil { @@ -74,7 +84,7 @@ func tarNode(ctx context.Context, tw *tar.Writer, node *restic.Node, repo restic header := &tar.Header{ Name: filepath.ToSlash(relPath), Size: int64(node.Size), - Mode: int64(node.Mode), + Mode: int64(node.Mode.Perm()), // c_IS* constants are added later Uid: int(node.UID), Gid: int(node.GID), ModTime: node.ModTime, @@ -83,6 +93,21 @@ func tarNode(ctx context.Context, tw *tar.Writer, node *restic.Node, repo restic PAXRecords: parseXattrs(node.ExtendedAttributes), } + // adapted from archive/tar.FileInfoHeader + if node.Mode&os.ModeSetuid != 0 { + header.Mode |= c_ISUID + } + if node.Mode&os.ModeSetgid != 0 { + header.Mode |= c_ISGID + } + if node.Mode&os.ModeSticky != 0 { + header.Mode |= c_ISVTX + } + + if IsFile(node) { + header.Typeflag = tar.TypeReg + } + if IsLink(node) { header.Typeflag = tar.TypeSymlink header.Linkname = node.LinkTarget @@ -90,6 +115,7 @@ func tarNode(ctx context.Context, tw *tar.Writer, node *restic.Node, repo restic if IsDir(node) { header.Typeflag = tar.TypeDir + header.Name += "/" } err = tw.WriteHeader(header)