@@ -72,10 +72,8 @@ pub fn read_tree_entries(data: &[u8]) -> TreeEntryIterator {
72
72
73
73
pub fn read_tree_entry ( data : & [ u8 ] ) -> io:: Result < ( TreeEntry , usize ) > {
74
74
if data. len ( ) < TREE_ENTRY_MIN_SIZE {
75
- let err_kind = std:: io:: ErrorKind :: InvalidData ;
76
75
let err_msg = format ! ( "remaining tree data is too small to actually fit a tree entry" ) ;
77
- let err = std:: io:: Error :: new ( err_kind, err_msg) ;
78
- return Err ( err) ;
76
+ return Err ( Error :: new ( ErrorKind :: InvalidData , err_msg) ) ;
79
77
}
80
78
81
79
let filename_len =
@@ -99,10 +97,8 @@ pub fn read_tree_entry(data: &[u8]) -> io::Result<(TreeEntry, usize)> {
99
97
Ok ( filename)
100
98
} ,
101
99
Err ( _) => {
102
- let err_kind = std:: io:: ErrorKind :: InvalidData ;
103
100
let err_msg = format ! ( "cannot decode filename as ASCII" ) ;
104
- let err = std:: io:: Error :: new ( err_kind, err_msg) ;
105
- Err ( err)
101
+ Err ( Error :: new ( ErrorKind :: InvalidData , err_msg) )
106
102
}
107
103
} ?;
108
104
@@ -142,41 +138,33 @@ fn mmap_dat(dat_path_str: &str) -> io::Result<Mmap> {
142
138
let dat_file = File :: open ( dat_path) ?;
143
139
unsafe { Mmap :: map ( & dat_file) }
144
140
} else {
145
- let err_kind = std:: io:: ErrorKind :: NotFound ;
146
141
let err_msg = format ! ( "{}: no such file" , dat_path_str) ;
147
- let err = std:: io:: Error :: new ( err_kind, err_msg) ;
148
- return Err ( err) ;
142
+ return Err ( Error :: new ( ErrorKind :: NotFound , err_msg) ) ;
149
143
}
150
144
}
151
145
152
146
fn find_entries ( dat_file : & [ u8 ] ) -> io:: Result < TreeEntryIterator > {
153
147
let len = dat_file. len ( ) ;
154
148
155
149
if len < DAT_FILE_MIN_SIZE {
156
- let err_kind = std:: io:: ErrorKind :: InvalidData ;
157
150
let err_msg = format ! ( "is too small: must be at least 8 bytes long" ) ;
158
- let err = std:: io:: Error :: new ( err_kind, err_msg) ;
159
- return Err ( err) ;
151
+ return Err ( Error :: new ( ErrorKind :: InvalidData , err_msg) ) ;
160
152
}
161
153
162
154
let file_size =
163
155
LittleEndian :: read_u32 ( & dat_file[ len-4 ..len] ) as usize ;
164
156
165
157
if file_size != len {
166
- let err_kind = std:: io:: ErrorKind :: InvalidData ;
167
158
let err_msg = format ! ( "size on disk ({}) doesn't match size from dat_file size field ({})" , len, file_size) ;
168
- let err = std:: io:: Error :: new ( err_kind, err_msg) ;
169
- return Err ( err) ;
159
+ return Err ( Error :: new ( ErrorKind :: InvalidData , err_msg) ) ;
170
160
}
171
161
172
162
let tree_size =
173
163
LittleEndian :: read_u32 ( & dat_file[ len-8 ..len-4 ] ) as usize ;
174
164
175
165
if tree_size + DAT_FILE_FOOTER_BYTES > file_size {
176
- let err_kind = std:: io:: ErrorKind :: InvalidData ;
177
166
let err_msg = format ! ( "size on disk ({}) is too small to fit the tree data ({}) plus footers" , len, tree_size) ;
178
- let err = std:: io:: Error :: new ( err_kind, err_msg) ;
179
- return Err ( err) ;
167
+ return Err ( Error :: new ( ErrorKind :: InvalidData , err_msg) ) ;
180
168
}
181
169
182
170
let tree_entries_start = len - tree_size - 4 ;
@@ -187,65 +175,50 @@ fn find_entries(dat_file: &[u8]) -> io::Result<TreeEntryIterator> {
187
175
Ok ( read_tree_entries ( tree_entries_data) )
188
176
}
189
177
190
- pub fn extract_all_entries ( dat_path : & str , output_path : & str ) -> io:: Result < ( ) > {
191
- let output_path = Path :: new ( & output_path ) ;
178
+ pub fn extract_all_entries ( dat_path : & str , output_dir : & str ) -> io:: Result < ( ) > {
179
+ let output_dir = Path :: new ( & output_dir ) ;
192
180
193
- if !output_path. exists ( ) {
194
- let err_kind = std:: io:: ErrorKind :: NotFound ;
195
- let err_msg = format ! ( "{}: no such directory" , output_path. to_str( ) . unwrap( ) ) ;
196
- let err = std:: io:: Error :: new ( err_kind, err_msg) ;
197
- return Err ( err) ;
198
- } else if !output_path. is_dir ( ) {
199
- let err_kind = std:: io:: ErrorKind :: InvalidInput ;
200
- let err_msg = format ! ( "{}: not a directory" , output_path. to_str( ) . unwrap( ) ) ;
201
- let err = std:: io:: Error :: new ( err_kind, err_msg) ;
202
- return Err ( err) ;
181
+ if !output_dir. exists ( ) {
182
+ let err_msg = format ! ( "{}: no such directory" , output_dir. to_str( ) . unwrap( ) ) ;
183
+ return Err ( Error :: new ( ErrorKind :: NotFound , err_msg) ) ;
184
+ } else if !output_dir. is_dir ( ) {
185
+ let err_msg = format ! ( "{}: not a directory" , output_dir. to_str( ) . unwrap( ) ) ;
186
+ return Err ( Error :: new ( ErrorKind :: InvalidInput , err_msg) ) ;
203
187
} else {
204
188
let dat_data = mmap_dat ( dat_path) ?;
205
189
let tree_entries = find_entries ( & dat_data) ?;
206
190
207
191
for tree_entry in tree_entries {
208
192
let tree_entry = tree_entry?;
209
- extract_entry ( & dat_data, & output_path, tree_entry) ?;
193
+ let entry_data = get_entry_data ( & dat_data, & tree_entry) ?;
194
+ let output_path = output_dir. join ( & tree_entry. filename ) ;
195
+ write_data ( & entry_data, & output_path) ?;
210
196
}
211
197
}
212
198
213
199
Ok ( ( ) )
214
200
}
215
201
216
- fn get_data_slice_for_entry < ' a > ( dat_data : & ' a [ u8 ] , entry : & TreeEntry ) -> io:: Result < & ' a [ u8 ] > {
217
- let start = entry. offset ;
218
- let end = entry . offset + entry. packed_size ;
202
+ fn get_entry_data < ' a > ( dat_data : & ' a [ u8 ] , entry : & TreeEntry ) -> io:: Result < & ' a [ u8 ] > {
203
+ let data_start = entry. offset ;
204
+ let data_end = data_start + entry. packed_size ;
219
205
220
- if start > dat_data. len ( ) {
221
- let err_msg = format ! ( "{}: start offset ({}) is outside of the data's bounds" , entry . filename . to_str ( ) . unwrap ( ) , entry . offset ) ;
222
- Err ( Error :: new ( ErrorKind :: InvalidData , err_msg ) )
223
- } else if end > dat_data . len ( ) {
224
- let err_msg = format ! ( "{}: end index({}) is outside the data's bounds" , entry . filename . to_str ( ) . unwrap ( ) , entry . offset + entry . packed_size ) ;
225
- Err ( Error :: new ( ErrorKind :: InvalidData , err_msg ) )
226
- } else {
227
- Ok ( & dat_data [ start..end ] )
206
+ match dat_data. get ( data_start..data_end ) {
207
+ Some ( entry_data ) => {
208
+ Ok ( entry_data )
209
+ } ,
210
+ None => {
211
+ let err_msg = format ! ( "{}: data range ({}-{}) is out of bounds" , entry . filename . to_str ( ) . unwrap ( ) , data_start , data_end ) ;
212
+ Err ( Error :: new ( ErrorKind :: InvalidData , err_msg ) )
213
+ }
228
214
}
229
215
}
230
216
231
- fn extract_entry ( dat_data : & [ u8 ] , output_dir : & Path , entry : TreeEntry ) -> io:: Result < ( ) > {
232
- let entry_data = get_data_slice_for_entry ( & dat_data, & entry) ?;
233
- let output_path = output_dir. join ( & entry. filename ) ;
234
-
217
+ fn write_data ( entry_data : & [ u8 ] , output_path : & Path ) -> io:: Result < ( ) > {
235
218
if let Some ( parent) = output_path. parent ( ) {
236
219
std:: fs:: create_dir_all ( parent) ?;
237
220
}
238
221
239
- if output_path. exists ( ) {
240
- eprintln ! ( "{}: already exists: skipping" , output_path. to_str( ) . unwrap( ) ) ;
241
- } else {
242
- write_entry_data_to_output ( & entry_data, & output_path) ?;
243
- }
244
-
245
- Ok ( ( ) )
246
- }
247
-
248
- fn write_entry_data_to_output ( entry_data : & [ u8 ] , output_path : & Path ) -> io:: Result < ( ) > {
249
222
let mut output_file = File :: create ( & output_path) ?;
250
223
251
224
if is_zlib_compressed ( & entry_data) {
0 commit comments