From 10fa5cde0a29476cfcfbd0a4fc597563792c3de7 Mon Sep 17 00:00:00 2001 From: Panagiotis Cheilaris Date: Tue, 27 Dec 2022 16:36:04 +0100 Subject: [PATCH 1/4] in tar dump, convert uid, gid of value -1 to zero --- changelog/unreleased/issue-4103 | 12 ++++++++++++ internal/dump/tar.go | 13 +++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 changelog/unreleased/issue-4103 diff --git a/changelog/unreleased/issue-4103 b/changelog/unreleased/issue-4103 new file mode 100644 index 000000000..78d0b2ae1 --- /dev/null +++ b/changelog/unreleased/issue-4103 @@ -0,0 +1,12 @@ +Bugfix: fix restic dump of tar file with 32-bit binary + +In restic up to 0.14.0, the restic dump from a 32-bit binary of a +snapshot of standard input that was created in Windows has as a +result a tar file whose content has a negative uid and gid. As a +result, gnu tar exits with failure status whenever it tries to +access such a tar file. With this fix, the tar file that is now +dumped from a 32-bit binary has content with non-negative uid and +gid. + +https://github.com/restic/restic/issues/4103 +https://github.com/restic/restic/pull/4104 diff --git a/internal/dump/tar.go b/internal/dump/tar.go index 65b68ee5b..0e4b83290 100644 --- a/internal/dump/tar.go +++ b/internal/dump/tar.go @@ -3,6 +3,7 @@ package dump import ( "archive/tar" "context" + "math" "os" "path/filepath" "strings" @@ -38,6 +39,14 @@ const ( cISVTX = 0o1000 // Save text (sticky bit) ) +// substitute a uid or gid of -1 (which is converted to 2^32 - 1) with zero +func tarId(id uint32) int { + if id == math.MaxUint32 { + return 0 + } + return int(id) +} + func (d *Dumper) dumpNodeTar(ctx context.Context, node *restic.Node, w *tar.Writer) error { relPath, err := filepath.Rel("/", node.Path) if err != nil { @@ -48,8 +57,8 @@ func (d *Dumper) dumpNodeTar(ctx context.Context, node *restic.Node, w *tar.Writ Name: filepath.ToSlash(relPath), Size: int64(node.Size), Mode: int64(node.Mode.Perm()), // cIS* constants are added later - Uid: int(node.UID), - Gid: int(node.GID), + Uid: tarId(node.UID), + Gid: tarId(node.GID), Uname: node.User, Gname: node.Group, ModTime: node.ModTime, From 050ed616ae4ed68d75a5e9b7453caa1310f842d5 Mon Sep 17 00:00:00 2001 From: Panagiotis Cheilaris Date: Wed, 28 Dec 2022 18:44:36 +0100 Subject: [PATCH 2/4] be more explicit with uid or gid of value -1 --- internal/dump/tar.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/internal/dump/tar.go b/internal/dump/tar.go index 0e4b83290..aa8064fe1 100644 --- a/internal/dump/tar.go +++ b/internal/dump/tar.go @@ -3,7 +3,6 @@ package dump import ( "archive/tar" "context" - "math" "os" "path/filepath" "strings" @@ -39,9 +38,9 @@ const ( cISVTX = 0o1000 // Save text (sticky bit) ) -// substitute a uid or gid of -1 (which is converted to 2^32 - 1) with zero +// substitute a uid or gid of -1 (which was converted to 2^32 - 1) with zero func tarId(id uint32) int { - if id == math.MaxUint32 { + if int32(id) == -1 { return 0 } return int(id) From a86a56cf3bef3fb427e03fecd12abbc71501702e Mon Sep 17 00:00:00 2001 From: Panagiotis Cheilaris Date: Wed, 28 Dec 2022 18:46:58 +0100 Subject: [PATCH 3/4] fix lint issue with function name 'tarId' See https://github.com/golang/lint/issues/89 and https://github.com/golang/lint/issues/124 --- internal/dump/tar.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/dump/tar.go b/internal/dump/tar.go index aa8064fe1..1a68331d2 100644 --- a/internal/dump/tar.go +++ b/internal/dump/tar.go @@ -39,7 +39,7 @@ const ( ) // substitute a uid or gid of -1 (which was converted to 2^32 - 1) with zero -func tarId(id uint32) int { +func tarIdentifier(id uint32) int { if int32(id) == -1 { return 0 } @@ -56,8 +56,8 @@ func (d *Dumper) dumpNodeTar(ctx context.Context, node *restic.Node, w *tar.Writ Name: filepath.ToSlash(relPath), Size: int64(node.Size), Mode: int64(node.Mode.Perm()), // cIS* constants are added later - Uid: tarId(node.UID), - Gid: tarId(node.GID), + Uid: tarIdentifier(node.UID), + Gid: tarIdentifier(node.GID), Uname: node.User, Gname: node.Group, ModTime: node.ModTime, From 3b516d4b700243f086fec3ef46c8d5da104089f5 Mon Sep 17 00:00:00 2001 From: Panagiotis Cheilaris Date: Fri, 30 Dec 2022 18:12:12 +0100 Subject: [PATCH 4/4] convert uid/gid -1 to 0 only in 32-bit tar dump Only for a 32-bit build of restic, convert a uid or gid value of -1 to 0. --- changelog/unreleased/issue-4103 | 11 ++++------- internal/dump/tar.go | 5 +++-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/changelog/unreleased/issue-4103 b/changelog/unreleased/issue-4103 index 78d0b2ae1..5b152f992 100644 --- a/changelog/unreleased/issue-4103 +++ b/changelog/unreleased/issue-4103 @@ -1,12 +1,9 @@ Bugfix: fix restic dump of tar file with 32-bit binary -In restic up to 0.14.0, the restic dump from a 32-bit binary of a -snapshot of standard input that was created in Windows has as a -result a tar file whose content has a negative uid and gid. As a -result, gnu tar exits with failure status whenever it tries to -access such a tar file. With this fix, the tar file that is now -dumped from a 32-bit binary has content with non-negative uid and -gid. +When using a 32-bit build of restic, the `restic dump` command could in some +cases create tar files containing negative uid and gid. These files cannot be +read by gnu tar. This corner case especially applies to backups from stdin on Windows. +We have changed the dump command to create valid tar files in this case. https://github.com/restic/restic/issues/4103 https://github.com/restic/restic/pull/4104 diff --git a/internal/dump/tar.go b/internal/dump/tar.go index 1a68331d2..6e87aabe5 100644 --- a/internal/dump/tar.go +++ b/internal/dump/tar.go @@ -38,9 +38,10 @@ const ( cISVTX = 0o1000 // Save text (sticky bit) ) -// substitute a uid or gid of -1 (which was converted to 2^32 - 1) with zero +// in a 32-bit build of restic: +// substitute a uid or gid of -1 (which was converted to 2^32 - 1) with 0 func tarIdentifier(id uint32) int { - if int32(id) == -1 { + if int(id) == -1 { return 0 } return int(id)