4
4
"bytes"
5
5
"encoding/binary"
6
6
"fmt"
7
+ "github.com/Sirupsen/logrus"
7
8
"io"
8
9
)
9
10
@@ -26,17 +27,115 @@ func (er *Reader) GetInode(n uint32) (inode Inode, err error) {
26
27
return
27
28
}
28
29
30
+ var log = logrus .New ()
31
+
29
32
func (er * Reader ) GetInodeReader (inode Inode ) (io.Reader , error ) {
30
33
indr := inodeDataReader {
31
34
er : er ,
32
35
length : int64 (inode .Size ()),
33
36
}
34
- extents , err := er .GetExtents (inode )
37
+ if inode .Flags & InodeFlagExtents > 0 {
38
+ extents , err := er .GetExtents (inode )
39
+ if err != nil {
40
+ return nil , err
41
+ }
42
+ indr .extents = extents
43
+ return & indr , nil
44
+ } else {
45
+ log .Infoln ("Trying to read block map" )
46
+
47
+ blocks , err := er .readBlockMap (inode )
48
+ if err != nil {
49
+ return nil , err
50
+ }
51
+ log .Infof (" block pointers: %+v" , blocks )
52
+ for i , p := range blocks {
53
+ indr .extents = append (indr .extents , Extent {
54
+ Block : uint32 (i ),
55
+ Len : 1 ,
56
+ StartLo : p ,
57
+ StartHi : 0 ,
58
+ })
59
+ }
60
+ return & indr , nil
61
+ }
62
+ }
63
+
64
+ func (er * Reader ) readBlockMap (inode Inode ) ([]uint32 , error ) {
65
+ // the inode block map is layed out as 12 direct pointers to
66
+ // blocks, followed by three indirect pointers with increasing
67
+ // levels of indirection. The first 0-pointer encountered walking
68
+ // the structure indicates the end of the pointer array.
69
+ // See https://en.wikipedia.org/wiki/Inode_pointer_structure
70
+
71
+ nodeData := inode .GetDataReader ()
72
+ blocks := make ([]uint32 , 12 )
73
+ err := binary .Read (nodeData , binary .LittleEndian , & blocks )
35
74
if err != nil {
36
75
return nil , err
37
76
}
38
- indr .extents = extents
39
- return & indr , nil
77
+ log .Infof (" direct block pointers: %+v" , blocks )
78
+ for i , b := range blocks {
79
+ if b == 0 {
80
+ return blocks [:i ], nil
81
+ }
82
+ }
83
+
84
+ // if no 0-pointer encountered, then dig into indirect pointers
85
+ pointers := make ([]uint32 , 3 )
86
+ if err := binary .Read (nodeData , binary .LittleEndian , & pointers ); err != nil {
87
+ return nil , err
88
+ }
89
+ for i , p := range pointers {
90
+ if p == 0 {
91
+ break
92
+ }
93
+ indirectblocks , err , done := er .readIndirectBlockMap (p , i + 1 )
94
+ if err != nil {
95
+ return nil , err
96
+ }
97
+ blocks = append (blocks , indirectblocks ... )
98
+ if done {
99
+ break
100
+ }
101
+ }
102
+
103
+ for i , b := range blocks {
104
+ if b == 0 {
105
+ return blocks [:i ], nil
106
+ }
107
+ }
108
+ return blocks , nil
109
+ }
110
+
111
+ func (er * Reader ) readIndirectBlockMap (pointer uint32 , level int ) ([]uint32 , error , bool ) {
112
+ if level == 0 {
113
+ if pointer == 0 {
114
+ return []uint32 {}, nil , true
115
+ }
116
+ return []uint32 {pointer }, nil , false
117
+ }
118
+ log .Infof (" reading one block of indirect block pointers with indirection level %d" , level )
119
+ pointers := make ([]uint32 , er .super .blockSize ())
120
+ if _ , err := er .s .Seek (er .blockOffset (int64 (pointer )), 0 ); err != nil {
121
+ return nil , err , false
122
+ }
123
+ if err := binary .Read (er .s , binary .LittleEndian , & pointers ); err != nil {
124
+ return nil , err , false
125
+ }
126
+ var blocks []uint32
127
+ for i , p := range pointers {
128
+ indirectblocks , err , done := er .readIndirectBlockMap (p , level - 1 )
129
+ if err != nil {
130
+ return nil , err , false
131
+ }
132
+ blocks = append (blocks , indirectblocks ... )
133
+ if done {
134
+ log .Infof (" end of block map found after following %d pointers at level %d" , i , level )
135
+ return blocks , nil , done
136
+ }
137
+ }
138
+ return blocks , nil , false
40
139
}
41
140
42
141
func (er * Reader ) GetInodeContent (inode Inode ) ([]byte , error ) {
0 commit comments