forked from Velocidex/velociraptor
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwrapper.go
103 lines (80 loc) · 2.05 KB
/
wrapper.go
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package simple
import (
"context"
"errors"
"github.com/Velocidex/ordereddict"
"www.velocidex.com/golang/velociraptor/result_sets"
)
// A wrapper that allows us to read a range from a larger result set.
type ResultSetReaderWrapper struct {
result_sets.ResultSetReader
start_idx, end_idx uint64
offset int64
}
func (self *ResultSetReaderWrapper) SeekToRow(start int64) error {
self.offset = start
return self.ResultSetReader.SeekToRow(start + int64(self.start_idx))
}
func (self *ResultSetReaderWrapper) TotalRows() int64 {
return int64(self.end_idx - self.start_idx)
}
func (self *ResultSetReaderWrapper) JSON(ctx context.Context) (<-chan []byte, error) {
return nil, errors.New("ResultSetReaderWrapper.JSON Not implemented")
}
func (self *ResultSetReaderWrapper) Rows(ctx context.Context) <-chan *ordereddict.Dict {
output := make(chan *ordereddict.Dict)
// Our initial row relative to the delegate
count := self.start_idx + uint64(self.offset)
go func() {
defer close(output)
if self.start_idx == self.end_idx {
return
}
subctx, cancel := context.WithCancel(ctx)
defer cancel()
row_chan := self.ResultSetReader.Rows(subctx)
for {
select {
case <-subctx.Done():
return
case row, ok := <-row_chan:
if !ok {
return
}
select {
case <-ctx.Done():
return
case output <- row:
}
count++
if self.end_idx > 0 && count >= self.end_idx {
return
}
}
}
}()
return output
}
func WrapReaderForRange(
reader result_sets.ResultSetReader,
start_idx, end_idx uint64) (result_sets.ResultSetReader, error) {
if end_idx < start_idx {
return nil, errors.New("Invalid range for reader wrapper")
}
// No need to wrap it
if start_idx == 0 && end_idx == 0 {
return reader, nil
}
if end_idx > uint64(reader.TotalRows()) {
end_idx = uint64(reader.TotalRows())
}
err := reader.SeekToRow(int64(start_idx))
if err != nil {
return nil, err
}
return &ResultSetReaderWrapper{
ResultSetReader: reader,
start_idx: start_idx,
end_idx: end_idx,
}, nil
}