File: iterate.go

package info (click to toggle)
golang-github-vbatts-tar-split 0.11.6-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental, forky, sid, trixie
  • size: 744 kB
  • sloc: makefile: 2
file content (57 lines) | stat: -rw-r--r-- 1,770 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package asm

import (
	"bytes"
	"fmt"
	"io"

	"github.com/vbatts/tar-split/archive/tar"
	"github.com/vbatts/tar-split/tar/storage"
)

// IterateHeaders calls handler for each tar header provided by Unpacker
func IterateHeaders(unpacker storage.Unpacker, handler func(hdr *tar.Header) error) error {
	// We assume about NewInputTarStream:
	// - There is a separate SegmentType entry for every tar header, but only one SegmentType entry for the full header incl. any extensions
	// - (There is a FileType entry for every tar header, we ignore it)
	// - Trailing padding of a file, if any, is included in the next SegmentType entry
	// - At the end, there may be SegmentType entries just for the terminating zero blocks.

	var pendingPadding int64 = 0
	for {
		tsEntry, err := unpacker.Next()
		if err != nil {
			if err == io.EOF {
				return nil
			}
			return fmt.Errorf("reading tar-split entries: %w", err)
		}
		switch tsEntry.Type {
		case storage.SegmentType:
			payload := tsEntry.Payload
			if int64(len(payload)) < pendingPadding {
				return fmt.Errorf("expected %d bytes of padding after previous file, but next SegmentType only has %d bytes", pendingPadding, len(payload))
			}
			payload = payload[pendingPadding:]
			pendingPadding = 0

			tr := tar.NewReader(bytes.NewReader(payload))
			hdr, err := tr.Next()
			if err != nil {
				if err == io.EOF { // Probably the last entry, but let’s let the unpacker drive that.
					break
				}
				return fmt.Errorf("decoding a tar header from a tar-split entry: %w", err)
			}
			if err := handler(hdr); err != nil {
				return err
			}
			pendingPadding = tr.ExpectedPadding()

		case storage.FileType:
			// Nothing
		default:
			return fmt.Errorf("unexpected tar-split entry type %q", tsEntry.Type)
		}
	}
}