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.
This commit is contained in:
Michael Eischer 2020-10-24 18:38:30 +02:00
parent e21dcb0eea
commit 1e3c9a2c11
1 changed files with 27 additions and 1 deletions

View File

@ -4,6 +4,7 @@ import (
"archive/tar" "archive/tar"
"context" "context"
"io" "io"
"os"
"path" "path"
"path/filepath" "path/filepath"
"strings" "strings"
@ -65,6 +66,15 @@ func tarTree(ctx context.Context, repo restic.Repository, rootNode *restic.Node,
return err 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 { func tarNode(ctx context.Context, tw *tar.Writer, node *restic.Node, repo restic.Repository) error {
relPath, err := filepath.Rel("/", node.Path) relPath, err := filepath.Rel("/", node.Path)
if err != nil { if err != nil {
@ -74,7 +84,7 @@ func tarNode(ctx context.Context, tw *tar.Writer, node *restic.Node, repo restic
header := &tar.Header{ header := &tar.Header{
Name: filepath.ToSlash(relPath), Name: filepath.ToSlash(relPath),
Size: int64(node.Size), Size: int64(node.Size),
Mode: int64(node.Mode), Mode: int64(node.Mode.Perm()), // c_IS* constants are added later
Uid: int(node.UID), Uid: int(node.UID),
Gid: int(node.GID), Gid: int(node.GID),
ModTime: node.ModTime, ModTime: node.ModTime,
@ -83,6 +93,21 @@ func tarNode(ctx context.Context, tw *tar.Writer, node *restic.Node, repo restic
PAXRecords: parseXattrs(node.ExtendedAttributes), 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) { if IsLink(node) {
header.Typeflag = tar.TypeSymlink header.Typeflag = tar.TypeSymlink
header.Linkname = node.LinkTarget header.Linkname = node.LinkTarget
@ -90,6 +115,7 @@ func tarNode(ctx context.Context, tw *tar.Writer, node *restic.Node, repo restic
if IsDir(node) { if IsDir(node) {
header.Typeflag = tar.TypeDir header.Typeflag = tar.TypeDir
header.Name += "/"
} }
err = tw.WriteHeader(header) err = tw.WriteHeader(header)