8
8
9
9
class IndexGroup :
10
10
def __init__ (self , index_root , index_allocation ):
11
- self .inited = True
12
11
self .index_root = index_root
13
12
self .index_allocation = index_allocation
14
13
@@ -21,7 +20,7 @@ def iterator(self):
21
20
for o in self .index_root .iterator ():
22
21
if DEBUG & 8 : log ("Internal entry" , o .FileName )
23
22
yield o
24
- if self .index_allocation :
23
+ if self .index_allocation and self . index_allocation . valid :
25
24
for o in self .index_allocation .iterator ():
26
25
if DEBUG & 8 : log ("External entry" , o .FileName )
27
26
yield o
@@ -33,16 +32,14 @@ def find(self, name):
33
32
return None
34
33
35
34
class Index :
36
- def __init__ (self , indxstream , bitmap , size , resident = 0 ):
37
- #~ print('Index.init called',indxstream, bitmap, size , resident)
38
- self .inited = False
39
- self .block_size = size
35
+ def __init__ (self , indxstream , bitmap , block_size , resident = 0 ):
36
+ #~ print('Index.init called',indxstream, bitmap, block_size , resident)
37
+ self .valid = False
38
+ self .block_size = block_size
40
39
self ._stream = indxstream
41
- self ._bitmap = bitmap # only $INDEX_ALLOCATION has one!
40
+ self ._bitmap = bitmap # in $INDEX_ALLOCATION (bit set if INDX in use)
42
41
self ._pos = self ._stream .tell ()
43
42
self ._resident = resident
44
- # $Bitmap shows free Index clusters
45
- # Last free clusters do not require INDX marker
46
43
self ._buf = self ._stream .read (self .block_size )
47
44
if resident :
48
45
#~ print('DBG: initing resident INDX')
@@ -55,22 +52,22 @@ def __init__ (self, indxstream, bitmap, size, resident=0):
55
52
#~ print("New INDEX_HEADER:", self._indxh)
56
53
else :
57
54
#~ print('DBG: initing non resident INDX')
58
- #~ self._stream.seek(0)
59
- #~ open('INDX.BIN', 'wb').write(self._stream.read())
55
+ # Sometimes an $INDEX_ALLOCATION has empty stream: full dir contents deletion?
56
+ if not self ._buf :
57
+ if DEBUG & 8 : log ("Empty INDX block @%X/%X" , self ._pos , self ._stream .size )
58
+ #~ print('Empty INDX block', self._pos, self._stream.size, self._stream)
59
+ return
60
60
block = Index_Block (self ._buf )
61
61
if not block :
62
- if self ._bitmap and not self ._bitmap .isset (self ._pos // self .block_size ):
63
- if DEBUG & 8 : log ("Cluster INDX %d non used but zeroed" , self ._pos // self .block_size )
64
- #~ print("Cluster INDX %d non used but zeroed"% self._pos//self.block_size)
65
- return
62
+ raise NTFSException ('INDX initialization failed' )
66
63
if DEBUG & 8 : log ("decoded INDEX_BLOCK:\n %s" , block )
67
64
#~ print("decoded INDEX_BLOCK:\n%s"% block)
68
65
self ._indxh = Index_Header (self ._buf , 24 )
69
66
if DEBUG & 8 : log ("decoded INDEX_HEADER:\n %s" , self ._indxh )
70
67
#~ print("decoded INDEX_HEADER:\n%s"% self._indxh)
71
- self .inited = True
68
+ self .valid = True
72
69
73
- def __str__ (self ): return "Index (inited=%d) @%x\n %s" % (self . inited , self ._pos , self ._indxh )
70
+ def __str__ (self ): return "Index @%x\n %s" % (self ._pos , self ._indxh )
74
71
75
72
__getattr__ = utils .common_getattr
76
73
@@ -83,16 +80,12 @@ def find(self, name):
83
80
84
81
def iterator (self ):
85
82
"Iterates through index entries"
86
- if not self .inited :
87
- #~ print(self._pos)
88
- raise NTFSException ("Can't scan an INDX block not initialized" )
89
83
while 1 :
90
84
i = self ._indxh .dwEntriesOffset
91
85
while i < self ._indxh .dwIndexLength :
92
86
e = Index_Entry (self ._buf , i + self ._indxh ._i )
93
87
if e :
94
- #~ print('DBG: Index.iterator yielding', e)
95
- # An entry with no name signals the INDX block end
88
+ # An entry with wFlags & 2, or unnamed, signals the INDX block end
96
89
if e .FileName : yield e
97
90
if e .wFlags & 0x2 :
98
91
if DEBUG & 8 : log ("last entry in current INDX block" )
@@ -105,16 +98,22 @@ def iterator(self):
105
98
#~ print("DBG: end of resident INDX")
106
99
break
107
100
if not self ._resident :
101
+ # Stops at end of Index stream
102
+ if self ._stream .tell () >= self ._stream .size :
103
+ #~ print("DBG: end of non resident INDX stream")
104
+ break
105
+ # Searches for the next used INDX
106
+ while not self ._bitmap .isset (self ._stream .tell () // self .block_size ):
107
+ self ._stream .seek (self .block_size , 1 )
108
+ if self ._stream .tell () >= self ._stream .size :
109
+ return
108
110
if self ._stream .tell () >= self ._stream .size :
109
111
#~ print("DBG: end of non resident INDX stream")
110
112
break
111
- # Loads the next INDX block or stops
113
+ # Loads the next INDX block and continues iteration
112
114
#~ print('DBG: tell', self._stream.tell())
115
+ #~ print('DBG: loading next INDX @', self._stream.tell(), self._stream.size)
113
116
self .__init__ (self ._stream , self ._bitmap , self .block_size , 0 )
114
- if not self .inited :
115
- #~ print('DBG: could not init next non-resident INDX block, stop scanning')
116
- return
117
- #~ print('New INDX block inited')
118
117
119
118
class Index_Block :
120
119
layout = {
@@ -131,7 +130,9 @@ def __init__ (self, indx):
131
130
self ._vk = {} # { nome: offset}
132
131
for k , v in self ._kv .items ():
133
132
self ._vk [v [0 ]] = k
134
- if self .sMagic != b'INDX' : raise BadIndex
133
+ # Unused blocks can be zeroed (=no INDX marker)
134
+ if self .sMagic != b'INDX' :
135
+ raise BadIndex
135
136
self .fixup ()
136
137
137
138
__getattr__ = utils .common_getattr
0 commit comments