-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtablereader.go
124 lines (104 loc) · 2.21 KB
/
tablereader.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package squashfs
import (
"fmt"
"io"
)
// TODO add buf cache to allow multiple accesses to same block without re-reading
type tableReader struct {
sb *Superblock
buf []byte
offt int64
tofft int64 // position of table block list (when blocks aren't one after another)
}
func (sb *Superblock) newInodeReader(ino inodeRef) (*tableReader, error) {
return sb.newTableReader(int64(sb.InodeTableStart)+int64(ino.Index()), int(ino.Offset()))
}
func (sb *Superblock) newTableReader(base int64, start int) (*tableReader, error) {
ir := &tableReader{
sb: sb,
offt: base,
}
err := ir.readBlock()
if err != nil {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return nil, fmt.Errorf("failed to read initial block: %w", err)
}
if start != 0 {
// need to cut offset
ir.buf = ir.buf[start:]
}
return ir, nil
}
func (sb *Superblock) newIndirectTableReader(base int64, start int) (*tableReader, error) {
ir := &tableReader{
sb: sb,
tofft: base,
}
err := ir.readBlock()
if err != nil {
return nil, err
}
if start != 0 {
// need to cut offset
ir.buf = ir.buf[start:]
}
return ir, nil
}
func (i *tableReader) readBlock() error {
if i.tofft != 0 {
// tofft mode
buf := make([]byte, 8)
_, err := i.sb.fs.ReadAt(buf, i.tofft)
if err != nil {
return err
}
i.offt = int64(i.sb.order.Uint64(buf))
}
buf := make([]byte, 2)
_, err := i.sb.fs.ReadAt(buf, i.offt)
if err != nil {
return err
}
lenN := i.sb.order.Uint16(buf)
nocompressFlag := false
if lenN&0x8000 == 0x8000 {
// not compressed
nocompressFlag = true
lenN = lenN & 0x7fff
}
buf = make([]byte, int(lenN))
// read data
_, err = i.sb.fs.ReadAt(buf, i.offt+2)
if err != nil {
return err
}
i.offt += int64(lenN) + 2
if !nocompressFlag {
// decompress
buf, err = i.sb.Comp.decompress(buf)
if err != nil {
//log.Printf("squashfs: failed to read compressed data: %s", err)
return err
}
}
i.buf = buf
return nil
}
func (i *tableReader) Read(p []byte) (int, error) {
// read from buf, if empty call readBlock()
if i.buf == nil {
err := i.readBlock()
if err != nil {
return 0, err
}
}
n := copy(p, i.buf)
if n == len(i.buf) {
i.buf = nil
} else {
i.buf = i.buf[n:]
}
return n, nil
}