X-Git-Url: https://git.giacomolli.uk/onechat/blobdiff_plain/f5c601f1801aaa276f8c335fcb51c373edc0b50c..b961d7cdc59213673c3e4f86d3dae99daf0a1935:/backup_archive.go diff --git a/backup_archive.go b/backup_archive.go index 35a389c..f68cb70 100644 --- a/backup_archive.go +++ b/backup_archive.go @@ -101,6 +101,7 @@ func backupArchive(ctx context.Context, root, path string) (size int64, err erro return nil }) + err = errors.Join(err, archive.Close(), compressed.Close()) if err != nil { return 0, fmt.Errorf("write archive: %w", err) @@ -124,6 +125,29 @@ func backupArchive(ctx context.Context, root, path string) (size int64, err erro return info.Size(), nil } +// backupCopyFile copies the size fixed at the snapshot of path. Growth after +// that point is not part of the copy, and a shorter file is an error. +func backupCopyFile(ctx context.Context, out io.Writer, path string, size int64) (err error) { + file, err := os.Open(path) + if err != nil { + return fmt.Errorf("open backup file: %w", err) + } + + defer func() { + err = errors.Join(err, file.Close()) + }() + + _, err = io.CopyN(out, BackupReader{ + ctx: ctx, + reader: file, + }, size) + if err != nil { + return fmt.Errorf("copy backup file: %w", err) + } + + return nil +} + // backupExtract restores regular files and directories in an empty staging // directory. Links, duplicate entries, unsafe names, and special modes fail. // Directory modes apply last so a read-only directory can hold files. @@ -150,6 +174,7 @@ func backupExtract(ctx context.Context, path, root string) (err error) { ctx: ctx, reader: compressed, }) + seen := make(map[string]bool) var directories []*tar.Header @@ -216,27 +241,19 @@ func backupExtract(ctx context.Context, path, root string) (err error) { return nil } -// backupCopyFile copies the size fixed at the snapshot of path. Growth after -// that point is not part of the copy, and a shorter file is an error. -func backupCopyFile(ctx context.Context, out io.Writer, path string, size int64) (err error) { - file, err := os.Open(path) - if err != nil { - return fmt.Errorf("open backup file: %w", err) +// backupExcluded keeps runtime locks, sockets, probe files, and import copies +// out of the snapshot. +func backupExcluded(name string) bool { + first, _, _ := strings.Cut(filepath.ToSlash(name), "/") + if first == socketFileName || first == tokenLockFileName || first == "probe" || strings.HasPrefix(first, "agent-backup-") { + return true } - defer func() { - err = errors.Join(err, file.Close()) - }() - - _, err = io.CopyN(out, BackupReader{ - ctx: ctx, - reader: file, - }, size) - if err != nil { - return fmt.Errorf("copy backup file: %w", err) + if filepath.Base(name) == "lock" || (first == imageDirName && strings.HasPrefix(filepath.Base(name), ".image-")) || (first == voiceDirName && (strings.HasPrefix(filepath.Base(name), ".voice-") || strings.HasPrefix(filepath.Base(name), ".transcript-"))) { + return true } - return nil + return false } func backupExtractFile(in io.Reader, path string, mode os.FileMode) (err error) { @@ -261,18 +278,3 @@ func backupExtractFile(in io.Reader, path string, mode os.FileMode) (err error) return nil } - -// backupExcluded keeps runtime locks, sockets, probe files, and import copies -// out of the snapshot. -func backupExcluded(name string) bool { - first, _, _ := strings.Cut(filepath.ToSlash(name), "/") - if first == socketFileName || first == tokenLockFileName || first == "probe" || strings.HasPrefix(first, "agent-backup-") { - return true - } - - if filepath.Base(name) == "lock" || (first == imageDirName && strings.HasPrefix(filepath.Base(name), ".image-")) || (first == voiceDirName && (strings.HasPrefix(filepath.Base(name), ".voice-") || strings.HasPrefix(filepath.Base(name), ".transcript-"))) { - return true - } - - return false -}