Skip to content

Commit fdaeb08

Browse files
committed
fix: backup tar creation for long filenames and special file types
1 parent 22add55 commit fdaeb08

File tree

1 file changed

+25
-2
lines changed

1 file changed

+25
-2
lines changed

src/server/backup/rustic.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"time"
1818

1919
"emperror.dev/errors"
20+
"github.com/apex/log"
2021

2122
"github.com/pyrohost/elytra/src/config"
2223
"github.com/pyrohost/elytra/src/internal/rustic"
@@ -611,17 +612,23 @@ func createTarGzArchive(sourceDir string, writer io.Writer) error {
611612
tarWriter := tar.NewWriter(gzWriter)
612613
defer tarWriter.Close()
613614

615+
fileCount := 0
616+
dirCount := 0
617+
614618
// Walk the source directory and add files to the archive
615-
return filepath.Walk(sourceDir, func(path string, info fs.FileInfo, err error) error {
619+
err := filepath.Walk(sourceDir, func(path string, info fs.FileInfo, err error) error {
616620
if err != nil {
617621
return err
618622
}
619623

620624
// Skip directories
621625
if info.IsDir() {
626+
dirCount++
622627
return nil
623628
}
624629

630+
fileCount++
631+
625632
// Calculate relative path
626633
relPath, err := filepath.Rel(sourceDir, path)
627634
if err != nil {
@@ -640,9 +647,22 @@ func createTarGzArchive(sourceDir string, writer io.Writer) error {
640647
}
641648
header.Name = relPath
642649

650+
// Use FormatUnknown to let tar writer choose the best format for each entry
651+
// This will automatically use PAX or GNU format for long filenames
652+
header.Format = tar.FormatUnknown
653+
643654
// Write header
644655
if err := tarWriter.WriteHeader(header); err != nil {
645-
return err
656+
log.WithField("file", relPath).WithField("name_length", len(relPath)).WithError(err).Error("Failed to write tar header")
657+
// Don't fail the entire backup for one file, just log and skip
658+
log.WithField("file", relPath).Warn("Skipping file due to tar header error")
659+
return nil
660+
}
661+
662+
// Only copy content for regular files (not symlinks, devices, etc.)
663+
// FileInfoHeader doesn't set Size for non-regular files, causing "write too long" errors
664+
if !info.Mode().IsRegular() {
665+
return nil
646666
}
647667

648668
// Open and copy file content
@@ -655,4 +675,7 @@ func createTarGzArchive(sourceDir string, writer io.Writer) error {
655675
_, err = io.Copy(tarWriter, file)
656676
return err
657677
})
678+
679+
log.WithField("file_count", fileCount).WithField("dir_count", dirCount).Info("backup tar archive created successfully")
680+
return err
658681
}

0 commit comments

Comments
 (0)