@@ -10,7 +10,6 @@ use crate::checksum::Checksum;
10
10
use crate :: error:: { CorruptKind , Ext4Error } ;
11
11
use crate :: journal:: superblock:: JournalSuperblock ;
12
12
use crate :: util:: { read_u32be, u64_from_hilo} ;
13
- use alloc:: vec:: Vec ;
14
13
use bitflags:: bitflags;
15
14
16
15
pub ( super ) fn is_descriptor_block_checksum_valid (
@@ -54,14 +53,14 @@ impl DescriptorBlockTag {
54
53
}
55
54
}
56
55
57
- pub ( super ) fn read_bytes ( bytes : & [ u8 ] ) -> Result < Self , Ext4Error > {
56
+ pub ( super ) fn read_bytes ( bytes : & [ u8 ] ) -> Option < Self > {
58
57
// Note: the tag format depends on feature flags in the journal
59
58
// superblock. The code in this function is only correct if the
60
59
// `CHECKSUM_V3` feature is enabled (this is checked when
61
60
// loading the superblock).
62
61
63
62
if bytes. len ( ) < Self :: SIZE_WITHOUT_UUID {
64
- return Err ( CorruptKind :: JournalDescriptorTagTruncated . into ( ) ) ;
63
+ return None ;
65
64
}
66
65
67
66
let t_blocknr = read_u32be ( bytes, 0 ) ;
@@ -74,42 +73,67 @@ impl DescriptorBlockTag {
74
73
if !flags. contains ( DescriptorBlockTagFlags :: UUID_OMITTED )
75
74
&& bytes. len ( ) < Self :: SIZE_WITH_UUID
76
75
{
77
- return Err ( CorruptKind :: JournalDescriptorTagTruncated . into ( ) ) ;
76
+ return None ;
78
77
}
79
78
80
- Ok ( Self {
79
+ Some ( Self {
81
80
block_number : u64_from_hilo ( t_blocknr_high, t_blocknr) ,
82
81
flags,
83
82
checksum : t_checksum,
84
83
} )
85
84
}
85
+ }
86
+
87
+ pub ( super ) struct DescriptorBlockTagIter < ' a > {
88
+ bytes : & ' a [ u8 ] ,
89
+ is_done : bool ,
90
+ }
86
91
87
- // TODO: this could be an iterator instead of allocating.
88
- pub ( super ) fn read_bytes_to_vec (
89
- mut bytes : & [ u8 ] ,
90
- ) -> Result < Vec < Self > , Ext4Error > {
91
- let mut v = Vec :: new ( ) ;
92
+ impl < ' a > DescriptorBlockTagIter < ' a > {
93
+ pub ( super ) fn new ( bytes : & ' a [ u8 ] ) -> Self {
94
+ Self {
95
+ bytes,
96
+ is_done : false ,
97
+ }
98
+ }
99
+ }
92
100
93
- while !bytes. is_empty ( ) {
94
- let tag = Self :: read_bytes ( bytes) ?;
95
- let is_end = tag. flags . contains ( DescriptorBlockTagFlags :: LAST_TAG ) ;
96
- let size = tag. encoded_size ( ) ;
97
- v. push ( tag) ;
101
+ impl Iterator for DescriptorBlockTagIter < ' _ > {
102
+ type Item = Result < DescriptorBlockTag , Ext4Error > ;
98
103
99
- if is_end {
100
- return Ok ( v) ;
101
- }
104
+ fn next ( & mut self ) -> Option < Self :: Item > {
105
+ if self . is_done {
106
+ return None ;
107
+ }
102
108
103
- bytes = & bytes[ size..] ;
109
+ let tag = if let Some ( tag) = DescriptorBlockTag :: read_bytes ( self . bytes )
110
+ {
111
+ tag
112
+ } else {
113
+ // If there were not enough bytes left to read the next tag,
114
+ // then the expected tag with the LAST_TAG flag set is missing.
115
+ self . is_done = true ;
116
+ return Some ( Err (
117
+ CorruptKind :: JournalDescriptorBlockMissingLastTag . into ( ) ,
118
+ ) ) ;
119
+ } ;
120
+
121
+ if tag. flags . contains ( DescriptorBlockTagFlags :: LAST_TAG ) {
122
+ // Last tag reached, nothing more to read.
123
+ self . is_done = true ;
124
+ return Some ( Ok ( tag) ) ;
104
125
}
105
126
106
- Err ( CorruptKind :: JournalDescriptorBlockMissingLastTag . into ( ) )
127
+ // Update the remaining bytes.
128
+ self . bytes = & self . bytes [ tag. encoded_size ( ) ..] ;
129
+
130
+ Some ( Ok ( tag) )
107
131
}
108
132
}
109
133
110
134
bitflags ! {
111
135
#[ derive( Clone , Copy , Debug , Eq , PartialEq , Ord , PartialOrd , Hash ) ]
112
- pub struct DescriptorBlockTagFlags : u32 {
136
+ pub ( crate ) struct DescriptorBlockTagFlags : u32 {
113
137
const ESCAPED = 0x1 ;
114
138
const UUID_OMITTED = 0x2 ;
115
139
const DELETED = 0x4 ;
@@ -128,10 +152,6 @@ mod tests {
128
152
#[ test]
129
153
fn test_journal_descriptor_block_tags ( ) {
130
154
let mut bytes = vec ! [ ] ;
131
- assert_eq ! (
132
- DescriptorBlockTag :: read_bytes_to_vec( & bytes) . unwrap_err( ) ,
133
- CorruptKind :: JournalDescriptorBlockMissingLastTag
134
- ) ;
135
155
136
156
// Block number low.
137
157
push_u32be ( & mut bytes, 0x1000 ) ;
@@ -154,8 +174,10 @@ mod tests {
154
174
bytes. extend ( [ 0 ; 16 ] ) ;
155
175
156
176
assert_eq ! (
157
- DescriptorBlockTag :: read_bytes_to_vec( & bytes) . unwrap( ) ,
158
- vec![
177
+ DescriptorBlockTagIter :: new( & bytes)
178
+ . map( Result :: unwrap)
179
+ . collect:: <Vec <_>>( ) ,
180
+ [
159
181
DescriptorBlockTag {
160
182
block_number: 0xa000_0000_1000 ,
161
183
flags: DescriptorBlockTagFlags :: UUID_OMITTED ,
0 commit comments