Files
2026-10-05 20:16:01 +02:00

74 lines
1.8 KiB
Go

package pcap
import (
"errors"
"io"
)
// SplitLimit bounds each output file of Split. Zero means no limit.
type SplitLimit struct {
Packets int // maximum packets per file
Bytes int64 // maximum file size, including the file and record headers
}
// SplitStats summarizes a Split.
type SplitStats struct {
Packets int // packets copied
Parts int // files created
Truncated bool // the input ended with an incomplete packet record, which was dropped
}
// Split copies the pcap file read from r into consecutive parts, each starting
// with the input's file header and holding whole packet records, so that no
// part exceeds the limit. A packet that is bigger than the size limit on its
// own goes into a part by itself. create is called to open part 1, 2, ...
func Split(r io.Reader, limit SplitLimit, create func(part int) (io.Writer, error)) (SplitStats, error) {
var st SplitStats
pr, err := NewReader(r)
if err != nil {
return st, err
}
var (
w io.Writer
nPackets int
nBytes int64
)
for {
rec, err := pr.Next()
if err == io.EOF {
break
}
if errors.Is(err, ErrTruncated) {
st.Truncated = true
break
}
if err != nil {
return st, err
}
full := limit.Packets > 0 && nPackets >= limit.Packets ||
limit.Bytes > 0 && nPackets > 0 && nBytes+int64(len(rec)) > limit.Bytes
if w == nil || full {
st.Parts++
if w, err = create(st.Parts); err != nil {
return st, err
}
if _, err := w.Write(pr.Header()); err != nil {
return st, err
}
nPackets, nBytes = 0, int64(len(pr.Header()))
}
if _, err := w.Write(rec); err != nil {
return st, err
}
nPackets++
nBytes += int64(len(rec))
st.Packets++
}
if st.Packets == 0 {
return st, errors.New("the pcap file contains no packets")
}
return st, nil
}