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 }