/src/libfsext/libfsext/libfsext_group_descriptor.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Group descriptor functions |
3 | | * |
4 | | * Copyright (C) 2010-2024, Joachim Metz <joachim.metz@gmail.com> |
5 | | * |
6 | | * Refer to AUTHORS for acknowledgements. |
7 | | * |
8 | | * This program is free software: you can redistribute it and/or modify |
9 | | * it under the terms of the GNU Lesser General Public License as published by |
10 | | * the Free Software Foundation, either version 3 of the License, or |
11 | | * (at your option) any later version. |
12 | | * |
13 | | * This program is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | * GNU General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU Lesser General Public License |
19 | | * along with this program. If not, see <https://www.gnu.org/licenses/>. |
20 | | */ |
21 | | |
22 | | #include <common.h> |
23 | | #include <byte_stream.h> |
24 | | #include <memory.h> |
25 | | #include <types.h> |
26 | | |
27 | | #include "libfsext_checksum.h" |
28 | | #include "libfsext_definitions.h" |
29 | | #include "libfsext_group_descriptor.h" |
30 | | #include "libfsext_io_handle.h" |
31 | | #include "libfsext_libbfio.h" |
32 | | #include "libfsext_libcerror.h" |
33 | | #include "libfsext_libcnotify.h" |
34 | | |
35 | | #include "fsext_group_descriptor.h" |
36 | | |
37 | | /* Creates a group descriptor |
38 | | * Make sure the value group_descriptor is referencing, is set to NULL |
39 | | * Returns 1 if successful or -1 on error |
40 | | */ |
41 | | int libfsext_group_descriptor_initialize( |
42 | | libfsext_group_descriptor_t **group_descriptor, |
43 | | libcerror_error_t **error ) |
44 | 4.88M | { |
45 | 4.88M | static char *function = "libfsext_group_descriptor_initialize"; |
46 | | |
47 | 4.88M | if( group_descriptor == NULL ) |
48 | 0 | { |
49 | 0 | libcerror_error_set( |
50 | 0 | error, |
51 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
52 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
53 | 0 | "%s: invalid group descriptor.", |
54 | 0 | function ); |
55 | |
|
56 | 0 | return( -1 ); |
57 | 0 | } |
58 | 4.88M | if( *group_descriptor != NULL ) |
59 | 0 | { |
60 | 0 | libcerror_error_set( |
61 | 0 | error, |
62 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
63 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
64 | 0 | "%s: invalid group descriptor value already set.", |
65 | 0 | function ); |
66 | |
|
67 | 0 | return( -1 ); |
68 | 0 | } |
69 | 4.88M | *group_descriptor = memory_allocate_structure( |
70 | 4.88M | libfsext_group_descriptor_t ); |
71 | | |
72 | 4.88M | if( *group_descriptor == NULL ) |
73 | 0 | { |
74 | 0 | libcerror_error_set( |
75 | 0 | error, |
76 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
77 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
78 | 0 | "%s: unable to create group descriptor.", |
79 | 0 | function ); |
80 | |
|
81 | 0 | goto on_error; |
82 | 0 | } |
83 | 4.88M | if( memory_set( |
84 | 4.88M | *group_descriptor, |
85 | 4.88M | 0, |
86 | 4.88M | sizeof( libfsext_group_descriptor_t ) ) == NULL ) |
87 | 0 | { |
88 | 0 | libcerror_error_set( |
89 | 0 | error, |
90 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
91 | 0 | LIBCERROR_MEMORY_ERROR_SET_FAILED, |
92 | 0 | "%s: unable to clear group descriptor.", |
93 | 0 | function ); |
94 | |
|
95 | 0 | goto on_error; |
96 | 0 | } |
97 | 4.88M | return( 1 ); |
98 | | |
99 | 0 | on_error: |
100 | 0 | if( *group_descriptor != NULL ) |
101 | 0 | { |
102 | 0 | memory_free( |
103 | 0 | *group_descriptor ); |
104 | |
|
105 | 0 | *group_descriptor = NULL; |
106 | 0 | } |
107 | 0 | return( -1 ); |
108 | 4.88M | } |
109 | | |
110 | | /* Frees a group descriptor |
111 | | * Returns 1 if successful or -1 on error |
112 | | */ |
113 | | int libfsext_group_descriptor_free( |
114 | | libfsext_group_descriptor_t **group_descriptor, |
115 | | libcerror_error_t **error ) |
116 | 4.88M | { |
117 | 4.88M | static char *function = "libfsext_group_descriptor_free"; |
118 | | |
119 | 4.88M | if( group_descriptor == NULL ) |
120 | 0 | { |
121 | 0 | libcerror_error_set( |
122 | 0 | error, |
123 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
124 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
125 | 0 | "%s: invalid group descriptor.", |
126 | 0 | function ); |
127 | |
|
128 | 0 | return( -1 ); |
129 | 0 | } |
130 | 4.88M | if( *group_descriptor != NULL ) |
131 | 4.88M | { |
132 | 4.88M | memory_free( |
133 | 4.88M | *group_descriptor ); |
134 | | |
135 | 4.88M | *group_descriptor = NULL; |
136 | 4.88M | } |
137 | 4.88M | return( 1 ); |
138 | 4.88M | } |
139 | | |
140 | | /* Reads the group descriptor data |
141 | | * Returns 1 if successful or -1 on error |
142 | | */ |
143 | | int libfsext_group_descriptor_read_data( |
144 | | libfsext_group_descriptor_t *group_descriptor, |
145 | | libfsext_io_handle_t *io_handle, |
146 | | const uint8_t *data, |
147 | | size_t data_size, |
148 | | libcerror_error_t **error ) |
149 | 4.88M | { |
150 | 4.88M | uint8_t checksum_data[ 4 ]; |
151 | 4.88M | uint8_t empty_checksum_data[ 2 ] = { 0, 0 }; |
152 | | |
153 | 4.88M | static char *function = "libfsext_group_descriptor_read_data"; |
154 | 4.88M | size_t group_descriptor_data_size = 0; |
155 | 4.88M | uint64_t value_64bit = 0; |
156 | 4.88M | uint32_t calculated_checksum = 0; |
157 | 4.88M | uint32_t stored_checksum = 0; |
158 | 4.88M | uint32_t value_32bit = 0; |
159 | 4.88M | uint16_t value_16bit = 0; |
160 | | |
161 | 4.88M | if( group_descriptor == NULL ) |
162 | 0 | { |
163 | 0 | libcerror_error_set( |
164 | 0 | error, |
165 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
166 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
167 | 0 | "%s: invalid group descriptor.", |
168 | 0 | function ); |
169 | |
|
170 | 0 | return( -1 ); |
171 | 0 | } |
172 | 4.88M | if( io_handle == NULL ) |
173 | 0 | { |
174 | 0 | libcerror_error_set( |
175 | 0 | error, |
176 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
177 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
178 | 0 | "%s: invalid IO handle.", |
179 | 0 | function ); |
180 | |
|
181 | 0 | return( -1 ); |
182 | 0 | } |
183 | 4.88M | if( io_handle->format_version < 4 ) |
184 | 716k | { |
185 | 716k | group_descriptor_data_size = sizeof( fsext_group_descriptor_ext2_t ); |
186 | 716k | } |
187 | 4.17M | else if( ( ( io_handle->incompatible_features_flags & LIBFSEXT_INCOMPATIBLE_FEATURES_FLAG_64BIT_SUPPORT ) != 0 ) |
188 | 4.17M | && ( io_handle->group_descriptor_size > 32 ) ) |
189 | 53.6k | { |
190 | 53.6k | group_descriptor_data_size = 64; |
191 | 53.6k | } |
192 | 4.11M | else |
193 | 4.11M | { |
194 | 4.11M | group_descriptor_data_size = 32; |
195 | 4.11M | } |
196 | 4.88M | if( data == NULL ) |
197 | 0 | { |
198 | 0 | libcerror_error_set( |
199 | 0 | error, |
200 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
201 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
202 | 0 | "%s: invalid data.", |
203 | 0 | function ); |
204 | |
|
205 | 0 | return( -1 ); |
206 | 0 | } |
207 | 4.88M | if( data_size < group_descriptor_data_size ) |
208 | 0 | { |
209 | 0 | libcerror_error_set( |
210 | 0 | error, |
211 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
212 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, |
213 | 0 | "%s: invalid data size value too small.", |
214 | 0 | function ); |
215 | |
|
216 | 0 | return( -1 ); |
217 | 0 | } |
218 | 4.88M | if( data_size > (size_t) SSIZE_MAX ) |
219 | 0 | { |
220 | 0 | libcerror_error_set( |
221 | 0 | error, |
222 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
223 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, |
224 | 0 | "%s: invalid data size value exceeds maximum.", |
225 | 0 | function ); |
226 | |
|
227 | 0 | return( -1 ); |
228 | 0 | } |
229 | | #if defined( HAVE_DEBUG_OUTPUT ) |
230 | | if( libcnotify_verbose != 0 ) |
231 | | { |
232 | | libcnotify_printf( |
233 | | "%s: group descriptor data:\n", |
234 | | function ); |
235 | | libcnotify_print_data( |
236 | | data, |
237 | | group_descriptor_data_size, |
238 | | 0 ); |
239 | | } |
240 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
241 | | |
242 | 4.88M | byte_stream_copy_to_uint32_little_endian( |
243 | 4.88M | ( (fsext_group_descriptor_ext2_t *) data )->block_bitmap_block_number, |
244 | 4.88M | group_descriptor->block_bitmap_block_number ); |
245 | | |
246 | 4.88M | byte_stream_copy_to_uint32_little_endian( |
247 | 4.88M | ( (fsext_group_descriptor_ext2_t *) data )->inode_bitmap_block_number, |
248 | 4.88M | group_descriptor->inode_bitmap_block_number ); |
249 | | |
250 | 4.88M | byte_stream_copy_to_uint32_little_endian( |
251 | 4.88M | ( (fsext_group_descriptor_ext2_t *) data )->inode_table_block_number, |
252 | 4.88M | group_descriptor->inode_table_block_number ); |
253 | | |
254 | 4.88M | byte_stream_copy_to_uint16_little_endian( |
255 | 4.88M | ( (fsext_group_descriptor_ext2_t *) data )->number_of_unallocated_blocks, |
256 | 4.88M | group_descriptor->number_of_unallocated_blocks ); |
257 | | |
258 | 4.88M | byte_stream_copy_to_uint16_little_endian( |
259 | 4.88M | ( (fsext_group_descriptor_ext2_t *) data )->number_of_unallocated_inodes, |
260 | 4.88M | group_descriptor->number_of_unallocated_inodes ); |
261 | | |
262 | 4.88M | byte_stream_copy_to_uint16_little_endian( |
263 | 4.88M | ( (fsext_group_descriptor_ext2_t *) data )->number_of_directories, |
264 | 4.88M | group_descriptor->number_of_directories ); |
265 | | |
266 | 4.88M | if( io_handle->format_version < 4 ) |
267 | 716k | { |
268 | | #if defined( HAVE_DEBUG_OUTPUT ) |
269 | | if( libcnotify_verbose != 0 ) |
270 | | { |
271 | | libcnotify_printf( |
272 | | "%s: block bitmap block number\t\t: %" PRIu64 "\n", |
273 | | function, |
274 | | group_descriptor->block_bitmap_block_number ); |
275 | | |
276 | | libcnotify_printf( |
277 | | "%s: inode bitmap block number\t\t: %" PRIu64 "\n", |
278 | | function, |
279 | | group_descriptor->inode_bitmap_block_number ); |
280 | | |
281 | | libcnotify_printf( |
282 | | "%s: inode table block number\t\t: %" PRIu64 "\n", |
283 | | function, |
284 | | group_descriptor->inode_table_block_number ); |
285 | | |
286 | | libcnotify_printf( |
287 | | "%s: number of unallocated blocks\t: %" PRIu32 "\n", |
288 | | function, |
289 | | group_descriptor->number_of_unallocated_blocks ); |
290 | | |
291 | | libcnotify_printf( |
292 | | "%s: number of unallocated inodes\t: %" PRIu32 "\n", |
293 | | function, |
294 | | group_descriptor->number_of_unallocated_inodes ); |
295 | | |
296 | | libcnotify_printf( |
297 | | "%s: number of directories\t\t: %" PRIu32 "\n", |
298 | | function, |
299 | | group_descriptor->number_of_directories ); |
300 | | |
301 | | libcnotify_printf( |
302 | | "%s: padding1:\n", |
303 | | function ); |
304 | | libcnotify_print_data( |
305 | | ( (fsext_group_descriptor_ext2_t *) data )->padding1, |
306 | | 2, |
307 | | 0 ); |
308 | | |
309 | | libcnotify_printf( |
310 | | "%s: unknown1:\n", |
311 | | function ); |
312 | | libcnotify_print_data( |
313 | | ( (fsext_group_descriptor_ext2_t *) data )->unknown1, |
314 | | 12, |
315 | | 0 ); |
316 | | } |
317 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
318 | 716k | } |
319 | 4.17M | else |
320 | 4.17M | { |
321 | 4.17M | byte_stream_copy_to_uint32_little_endian( |
322 | 4.17M | ( (fsext_group_descriptor_ext4_t *) data )->exclude_bitmap_block_number_lower, |
323 | 4.17M | group_descriptor->exclude_bitmap_block_number ); |
324 | | |
325 | 4.17M | byte_stream_copy_to_uint16_little_endian( |
326 | 4.17M | ( (fsext_group_descriptor_ext4_t *) data )->block_bitmap_checksum_lower, |
327 | 4.17M | group_descriptor->block_bitmap_checksum ); |
328 | | |
329 | 4.17M | byte_stream_copy_to_uint16_little_endian( |
330 | 4.17M | ( (fsext_group_descriptor_ext4_t *) data )->inode_bitmap_checksum_lower, |
331 | 4.17M | group_descriptor->inode_bitmap_checksum ); |
332 | | |
333 | 4.17M | byte_stream_copy_to_uint16_little_endian( |
334 | 4.17M | ( (fsext_group_descriptor_ext4_t *) data )->number_of_unused_inodes_lower, |
335 | 4.17M | group_descriptor->number_of_unused_inodes ); |
336 | | |
337 | 4.17M | byte_stream_copy_to_uint16_little_endian( |
338 | 4.17M | ( (fsext_group_descriptor_ext4_t *) data )->checksum, |
339 | 4.17M | value_16bit ); |
340 | | |
341 | 4.17M | stored_checksum = value_16bit; |
342 | | |
343 | | #if defined( HAVE_DEBUG_OUTPUT ) |
344 | | if( libcnotify_verbose != 0 ) |
345 | | { |
346 | | libcnotify_printf( |
347 | | "%s: block bitmap block number (lower)\t\t: %" PRIu64 "\n", |
348 | | function, |
349 | | group_descriptor->block_bitmap_block_number ); |
350 | | |
351 | | libcnotify_printf( |
352 | | "%s: inode bitmap block number (lower)\t\t: %" PRIu64 "\n", |
353 | | function, |
354 | | group_descriptor->inode_bitmap_block_number ); |
355 | | |
356 | | libcnotify_printf( |
357 | | "%s: inode table block number (lower)\t\t: %" PRIu64 "\n", |
358 | | function, |
359 | | group_descriptor->inode_table_block_number ); |
360 | | |
361 | | libcnotify_printf( |
362 | | "%s: number of unallocated blocks (lower)\t: %" PRIu32 "\n", |
363 | | function, |
364 | | group_descriptor->number_of_unallocated_blocks ); |
365 | | |
366 | | libcnotify_printf( |
367 | | "%s: number of unallocated inodes (lower)\t: %" PRIu32 "\n", |
368 | | function, |
369 | | group_descriptor->number_of_unallocated_inodes ); |
370 | | |
371 | | libcnotify_printf( |
372 | | "%s: number of directories (lower)\t\t: %" PRIu32 "\n", |
373 | | function, |
374 | | group_descriptor->number_of_directories ); |
375 | | |
376 | | libcnotify_printf( |
377 | | "%s: exclude bitmap block number (lower)\t: %" PRIu64 "\n", |
378 | | function, |
379 | | group_descriptor->exclude_bitmap_block_number ); |
380 | | |
381 | | libcnotify_printf( |
382 | | "%s: block bitmap checksum (lower)\t\t: 0x%04" PRIx32 "\n", |
383 | | function, |
384 | | group_descriptor->block_bitmap_checksum ); |
385 | | |
386 | | libcnotify_printf( |
387 | | "%s: inode bitmap checksum (lower)\t\t: 0x%04" PRIx32 "\n", |
388 | | function, |
389 | | group_descriptor->inode_bitmap_checksum ); |
390 | | |
391 | | libcnotify_printf( |
392 | | "%s: number of unused inodes (lower)\t\t: %" PRIu32 "\n", |
393 | | function, |
394 | | group_descriptor->number_of_unused_inodes ); |
395 | | |
396 | | byte_stream_copy_to_uint16_little_endian( |
397 | | ( (fsext_group_descriptor_ext4_t *) data )->checksum, |
398 | | value_16bit ); |
399 | | libcnotify_printf( |
400 | | "%s: checksum\t\t\t\t\t: 0x%04" PRIx16 "\n", |
401 | | function, |
402 | | value_16bit ); |
403 | | } |
404 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
405 | 4.17M | if( ( ( io_handle->incompatible_features_flags & LIBFSEXT_INCOMPATIBLE_FEATURES_FLAG_64BIT_SUPPORT ) != 0 ) |
406 | 4.17M | && ( io_handle->group_descriptor_size > 32 ) ) |
407 | 53.6k | { |
408 | | #if defined( HAVE_DEBUG_OUTPUT ) |
409 | | if( libcnotify_verbose != 0 ) |
410 | | { |
411 | | byte_stream_copy_to_uint32_little_endian( |
412 | | ( (fsext_group_descriptor_ext4_t *) data )->block_bitmap_block_number_upper, |
413 | | value_32bit ); |
414 | | libcnotify_printf( |
415 | | "%s: block bitmap block number (upper)\t\t: %" PRIu32 "\n", |
416 | | function, |
417 | | value_32bit ); |
418 | | |
419 | | byte_stream_copy_to_uint32_little_endian( |
420 | | ( (fsext_group_descriptor_ext4_t *) data )->inode_bitmap_block_number_upper, |
421 | | value_32bit ); |
422 | | libcnotify_printf( |
423 | | "%s: inode bitmap block number (upper)\t\t: %" PRIu32 "\n", |
424 | | function, |
425 | | value_32bit ); |
426 | | |
427 | | byte_stream_copy_to_uint32_little_endian( |
428 | | ( (fsext_group_descriptor_ext4_t *) data )->inode_table_block_number_upper, |
429 | | value_32bit ); |
430 | | libcnotify_printf( |
431 | | "%s: inode table block number (upper)\t\t: %" PRIu32 "\n", |
432 | | function, |
433 | | value_32bit ); |
434 | | |
435 | | byte_stream_copy_to_uint16_little_endian( |
436 | | ( (fsext_group_descriptor_ext4_t *) data )->number_of_unallocated_blocks_upper, |
437 | | value_16bit ); |
438 | | libcnotify_printf( |
439 | | "%s: number of unallocated blocks (upper)\t: %" PRIu16 "\n", |
440 | | function, |
441 | | value_16bit ); |
442 | | |
443 | | byte_stream_copy_to_uint16_little_endian( |
444 | | ( (fsext_group_descriptor_ext4_t *) data )->number_of_unallocated_inodes_upper, |
445 | | value_16bit ); |
446 | | libcnotify_printf( |
447 | | "%s: number of unallocated inodes (upper)\t: %" PRIu16 "\n", |
448 | | function, |
449 | | value_16bit ); |
450 | | |
451 | | byte_stream_copy_to_uint16_little_endian( |
452 | | ( (fsext_group_descriptor_ext4_t *) data )->number_of_directories_upper, |
453 | | value_16bit ); |
454 | | libcnotify_printf( |
455 | | "%s: number of directories (upper)\t\t: %" PRIu16 "\n", |
456 | | function, |
457 | | value_16bit ); |
458 | | |
459 | | byte_stream_copy_to_uint16_little_endian( |
460 | | ( (fsext_group_descriptor_ext4_t *) data )->number_of_unused_inodes_upper, |
461 | | value_16bit ); |
462 | | libcnotify_printf( |
463 | | "%s: number of unused inodes (upper)\t\t: %" PRIu16 "\n", |
464 | | function, |
465 | | value_16bit ); |
466 | | |
467 | | byte_stream_copy_to_uint32_little_endian( |
468 | | ( (fsext_group_descriptor_ext4_t *) data )->exclude_bitmap_block_number_upper, |
469 | | value_32bit ); |
470 | | libcnotify_printf( |
471 | | "%s: exclude bitmap block number (upper)\t: %" PRIu32 "\n", |
472 | | function, |
473 | | value_32bit ); |
474 | | |
475 | | byte_stream_copy_to_uint16_little_endian( |
476 | | ( (fsext_group_descriptor_ext4_t *) data )->block_bitmap_checksum_upper, |
477 | | value_16bit ); |
478 | | libcnotify_printf( |
479 | | "%s: block bitmap checksum (upper)\t\t: 0x%04" PRIx16 "\n", |
480 | | function, |
481 | | value_16bit ); |
482 | | |
483 | | byte_stream_copy_to_uint16_little_endian( |
484 | | ( (fsext_group_descriptor_ext4_t *) data )->inode_bitmap_checksum_upper, |
485 | | value_16bit ); |
486 | | libcnotify_printf( |
487 | | "%s: inode bitmap checksum (upper)\t\t: 0x%04" PRIx16 "\n", |
488 | | function, |
489 | | value_16bit ); |
490 | | |
491 | | libcnotify_printf( |
492 | | "%s: unknown1:\n", |
493 | | function ); |
494 | | libcnotify_print_data( |
495 | | ( (fsext_group_descriptor_ext4_t *) data )->unknown1, |
496 | | 4, |
497 | | 0 ); |
498 | | } |
499 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
500 | | |
501 | 53.6k | byte_stream_copy_to_uint32_little_endian( |
502 | 53.6k | ( (fsext_group_descriptor_ext4_t *) data )->block_bitmap_block_number_upper, |
503 | 53.6k | value_64bit ); |
504 | | |
505 | 53.6k | group_descriptor->block_bitmap_block_number |= value_64bit << 32; |
506 | | |
507 | 53.6k | byte_stream_copy_to_uint32_little_endian( |
508 | 53.6k | ( (fsext_group_descriptor_ext4_t *) data )->inode_bitmap_block_number_upper, |
509 | 53.6k | value_64bit ); |
510 | | |
511 | 53.6k | group_descriptor->inode_bitmap_block_number |= value_64bit << 32; |
512 | | |
513 | 53.6k | byte_stream_copy_to_uint32_little_endian( |
514 | 53.6k | ( (fsext_group_descriptor_ext4_t *) data )->inode_table_block_number_upper, |
515 | 53.6k | value_64bit ); |
516 | | |
517 | 53.6k | group_descriptor->inode_table_block_number |= value_64bit << 32; |
518 | | |
519 | 53.6k | byte_stream_copy_to_uint16_little_endian( |
520 | 53.6k | ( (fsext_group_descriptor_ext4_t *) data )->number_of_unallocated_blocks_upper, |
521 | 53.6k | value_32bit ); |
522 | | |
523 | 53.6k | group_descriptor->number_of_unallocated_blocks |= value_32bit << 16; |
524 | | |
525 | 53.6k | byte_stream_copy_to_uint16_little_endian( |
526 | 53.6k | ( (fsext_group_descriptor_ext4_t *) data )->number_of_unallocated_inodes_upper, |
527 | 53.6k | value_32bit ); |
528 | | |
529 | 53.6k | group_descriptor->number_of_unallocated_inodes |= value_32bit << 16; |
530 | | |
531 | 53.6k | byte_stream_copy_to_uint16_little_endian( |
532 | 53.6k | ( (fsext_group_descriptor_ext4_t *) data )->number_of_directories_upper, |
533 | 53.6k | value_32bit ); |
534 | | |
535 | 53.6k | group_descriptor->number_of_directories |= value_32bit << 16; |
536 | | |
537 | 53.6k | byte_stream_copy_to_uint16_little_endian( |
538 | 53.6k | ( (fsext_group_descriptor_ext4_t *) data )->number_of_unused_inodes_upper, |
539 | 53.6k | value_32bit ); |
540 | | |
541 | 53.6k | group_descriptor->number_of_unused_inodes |= value_32bit << 16; |
542 | | |
543 | 53.6k | byte_stream_copy_to_uint32_little_endian( |
544 | 53.6k | ( (fsext_group_descriptor_ext4_t *) data )->exclude_bitmap_block_number_upper, |
545 | 53.6k | value_64bit ); |
546 | | |
547 | 53.6k | group_descriptor->exclude_bitmap_block_number |= value_64bit << 32; |
548 | | |
549 | 53.6k | byte_stream_copy_to_uint16_little_endian( |
550 | 53.6k | ( (fsext_group_descriptor_ext4_t *) data )->block_bitmap_checksum_upper, |
551 | 53.6k | value_32bit ); |
552 | | |
553 | 53.6k | group_descriptor->block_bitmap_checksum |= value_32bit << 16; |
554 | | |
555 | 53.6k | byte_stream_copy_to_uint16_little_endian( |
556 | 53.6k | ( (fsext_group_descriptor_ext4_t *) data )->inode_bitmap_checksum_upper, |
557 | 53.6k | value_32bit ); |
558 | | |
559 | 53.6k | group_descriptor->inode_bitmap_checksum |= value_32bit << 16; |
560 | 53.6k | } |
561 | | #if defined( HAVE_DEBUG_OUTPUT ) |
562 | | if( libcnotify_verbose != 0 ) |
563 | | { |
564 | | libcnotify_printf( |
565 | | "%s: block bitmap block number\t\t\t: %" PRIu64 "\n", |
566 | | function, |
567 | | group_descriptor->block_bitmap_block_number ); |
568 | | |
569 | | libcnotify_printf( |
570 | | "%s: inode bitmap block number\t\t\t: %" PRIu64 "\n", |
571 | | function, |
572 | | group_descriptor->inode_bitmap_block_number ); |
573 | | |
574 | | libcnotify_printf( |
575 | | "%s: inode table block number\t\t\t: %" PRIu64 "\n", |
576 | | function, |
577 | | group_descriptor->inode_table_block_number ); |
578 | | |
579 | | libcnotify_printf( |
580 | | "%s: number of unallocated blocks\t\t: %" PRIu32 "\n", |
581 | | function, |
582 | | group_descriptor->number_of_unallocated_blocks ); |
583 | | |
584 | | libcnotify_printf( |
585 | | "%s: number of unallocated inodes\t\t: %" PRIu32 "\n", |
586 | | function, |
587 | | group_descriptor->number_of_unallocated_inodes ); |
588 | | |
589 | | libcnotify_printf( |
590 | | "%s: number of directories\t\t\t: %" PRIu32 "\n", |
591 | | function, |
592 | | group_descriptor->number_of_directories ); |
593 | | |
594 | | libcnotify_printf( |
595 | | "%s: number of unused inodes\t\t\t: %" PRIu32 "\n", |
596 | | function, |
597 | | group_descriptor->number_of_unused_inodes ); |
598 | | |
599 | | if( ( io_handle->read_only_compatible_features_flags & LIBFSEXT_READ_ONLY_COMPATIBLE_FEATURES_FLAG_METADATA_CHECKSUM ) != 0 ) |
600 | | { |
601 | | libcnotify_printf( |
602 | | "%s: block bitmap checksum\t\t\t: 0x%08" PRIx32 "\n", |
603 | | function, |
604 | | group_descriptor->block_bitmap_checksum ); |
605 | | |
606 | | libcnotify_printf( |
607 | | "%s: inode bitmap checksum\t\t\t: 0x%08" PRIx32 "\n", |
608 | | function, |
609 | | group_descriptor->inode_bitmap_checksum ); |
610 | | } |
611 | | else |
612 | | { |
613 | | libcnotify_printf( |
614 | | "%s: block bitmap checksum\t\t\t: 0x%04" PRIx32 "\n", |
615 | | function, |
616 | | group_descriptor->block_bitmap_checksum ); |
617 | | |
618 | | libcnotify_printf( |
619 | | "%s: inode bitmap checksum\t\t\t: 0x%04" PRIx32 "\n", |
620 | | function, |
621 | | group_descriptor->inode_bitmap_checksum ); |
622 | | } |
623 | | libcnotify_printf( |
624 | | "\n" ); |
625 | | } |
626 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
627 | 4.17M | } |
628 | | /* TODO add support for crc16 checksum */ |
629 | 4.88M | if( ( io_handle->read_only_compatible_features_flags & LIBFSEXT_READ_ONLY_COMPATIBLE_FEATURES_FLAG_METADATA_CHECKSUM ) != 0 ) |
630 | 261k | { |
631 | 261k | byte_stream_copy_from_uint32_little_endian( |
632 | 261k | checksum_data, |
633 | 261k | group_descriptor->group_number ); |
634 | | |
635 | 261k | if( libfsext_checksum_calculate_crc32( |
636 | 261k | &calculated_checksum, |
637 | 261k | checksum_data, |
638 | 261k | 4, |
639 | 261k | io_handle->metadata_checksum_seed, |
640 | 261k | error ) != 1 ) |
641 | 0 | { |
642 | 0 | libcerror_error_set( |
643 | 0 | error, |
644 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
645 | 0 | LIBCERROR_RUNTIME_ERROR_SET_FAILED, |
646 | 0 | "%s: unable to calculate CRC-32.", |
647 | 0 | function ); |
648 | |
|
649 | 0 | return( -1 ); |
650 | 0 | } |
651 | 261k | if( libfsext_checksum_calculate_crc32( |
652 | 261k | &calculated_checksum, |
653 | 261k | data, |
654 | 261k | 30, |
655 | 261k | calculated_checksum, |
656 | 261k | error ) != 1 ) |
657 | 0 | { |
658 | 0 | libcerror_error_set( |
659 | 0 | error, |
660 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
661 | 0 | LIBCERROR_RUNTIME_ERROR_SET_FAILED, |
662 | 0 | "%s: unable to calculate CRC-32.", |
663 | 0 | function ); |
664 | |
|
665 | 0 | return( -1 ); |
666 | 0 | } |
667 | 261k | if( libfsext_checksum_calculate_crc32( |
668 | 261k | &calculated_checksum, |
669 | 261k | empty_checksum_data, |
670 | 261k | 2, |
671 | 261k | calculated_checksum, |
672 | 261k | error ) != 1 ) |
673 | 0 | { |
674 | 0 | libcerror_error_set( |
675 | 0 | error, |
676 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
677 | 0 | LIBCERROR_RUNTIME_ERROR_SET_FAILED, |
678 | 0 | "%s: unable to calculate CRC-32.", |
679 | 0 | function ); |
680 | |
|
681 | 0 | return( -1 ); |
682 | 0 | } |
683 | 261k | if( libfsext_checksum_calculate_crc32( |
684 | 261k | &calculated_checksum, |
685 | 261k | &( data[ 32 ] ), |
686 | 261k | data_size - 32, |
687 | 261k | calculated_checksum, |
688 | 261k | error ) != 1 ) |
689 | 0 | { |
690 | 0 | libcerror_error_set( |
691 | 0 | error, |
692 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
693 | 0 | LIBCERROR_RUNTIME_ERROR_SET_FAILED, |
694 | 0 | "%s: unable to calculate CRC-32.", |
695 | 0 | function ); |
696 | |
|
697 | 0 | return( -1 ); |
698 | 0 | } |
699 | 261k | calculated_checksum = ( 0xffffffffUL - calculated_checksum ) & 0x0000ffffUL; |
700 | | |
701 | 261k | if( ( stored_checksum != 0 ) |
702 | 261k | && ( stored_checksum != calculated_checksum ) ) |
703 | 131k | { |
704 | | #if defined( HAVE_DEBUG_OUTPUT ) |
705 | | if( libcnotify_verbose != 0 ) |
706 | | { |
707 | | libcnotify_printf( |
708 | | "%s: mismatch in checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).\n", |
709 | | function, |
710 | | stored_checksum, |
711 | | calculated_checksum ); |
712 | | } |
713 | | #endif |
714 | 131k | } |
715 | 261k | } |
716 | 4.88M | return( 1 ); |
717 | 4.88M | } |
718 | | |
719 | | /* Reads the group descriptor from a Basic File IO (bfio) handle |
720 | | * Returns 1 if successful or -1 on error |
721 | | */ |
722 | | int libfsext_group_descriptor_read_file_io_handle( |
723 | | libfsext_group_descriptor_t *group_descriptor, |
724 | | libfsext_io_handle_t *io_handle, |
725 | | libbfio_handle_t *file_io_handle, |
726 | | libcerror_error_t **error ) |
727 | 4.88M | { |
728 | 4.88M | uint8_t *data = NULL; |
729 | 4.88M | static char *function = "libfsext_group_descriptor_read_file_io_handle"; |
730 | 4.88M | size_t group_descriptor_data_size = 0; |
731 | 4.88M | ssize_t read_count = 0; |
732 | | |
733 | 4.88M | if( io_handle == NULL ) |
734 | 0 | { |
735 | 0 | libcerror_error_set( |
736 | 0 | error, |
737 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
738 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
739 | 0 | "%s: invalid IO handle.", |
740 | 0 | function ); |
741 | |
|
742 | 0 | return( -1 ); |
743 | 0 | } |
744 | 4.88M | if( io_handle == NULL ) |
745 | 0 | { |
746 | 0 | libcerror_error_set( |
747 | 0 | error, |
748 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
749 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
750 | 0 | "%s: invalid IO handle.", |
751 | 0 | function ); |
752 | |
|
753 | 0 | return( -1 ); |
754 | 0 | } |
755 | 4.88M | if( io_handle->format_version < 4 ) |
756 | 716k | { |
757 | 716k | group_descriptor_data_size = sizeof( fsext_group_descriptor_ext2_t ); |
758 | 716k | } |
759 | 4.17M | else if( ( ( io_handle->incompatible_features_flags & LIBFSEXT_INCOMPATIBLE_FEATURES_FLAG_64BIT_SUPPORT ) != 0 ) |
760 | 4.17M | && ( io_handle->group_descriptor_size > 32 ) ) |
761 | 53.7k | { |
762 | 53.7k | group_descriptor_data_size = 64; |
763 | 53.7k | } |
764 | 4.11M | else |
765 | 4.11M | { |
766 | 4.11M | group_descriptor_data_size = 32; |
767 | 4.11M | } |
768 | 4.88M | data = (uint8_t *) memory_allocate( |
769 | 4.88M | sizeof( uint8_t ) * group_descriptor_data_size ); |
770 | | |
771 | 4.88M | if( data == NULL ) |
772 | 0 | { |
773 | 0 | libcerror_error_set( |
774 | 0 | error, |
775 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
776 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
777 | 0 | "%s: unable to create data.", |
778 | 0 | function ); |
779 | |
|
780 | 0 | goto on_error; |
781 | 0 | } |
782 | 4.88M | read_count = libbfio_handle_read_buffer( |
783 | 4.88M | file_io_handle, |
784 | 4.88M | data, |
785 | 4.88M | group_descriptor_data_size, |
786 | 4.88M | error ); |
787 | | |
788 | 4.88M | if( read_count != (ssize_t) group_descriptor_data_size ) |
789 | 390 | { |
790 | 390 | libcerror_error_set( |
791 | 390 | error, |
792 | 390 | LIBCERROR_ERROR_DOMAIN_IO, |
793 | 390 | LIBCERROR_IO_ERROR_READ_FAILED, |
794 | 390 | "%s: unable to read group descriptor.", |
795 | 390 | function ); |
796 | | |
797 | 390 | goto on_error; |
798 | 390 | } |
799 | 4.88M | if( libfsext_group_descriptor_read_data( |
800 | 4.88M | group_descriptor, |
801 | 4.88M | io_handle, |
802 | 4.88M | data, |
803 | 4.88M | group_descriptor_data_size, |
804 | 4.88M | error ) != 1 ) |
805 | 0 | { |
806 | 0 | libcerror_error_set( |
807 | 0 | error, |
808 | 0 | LIBCERROR_ERROR_DOMAIN_IO, |
809 | 0 | LIBCERROR_IO_ERROR_READ_FAILED, |
810 | 0 | "%s: unable to read group descriptor.", |
811 | 0 | function ); |
812 | |
|
813 | 0 | goto on_error; |
814 | 0 | } |
815 | 4.88M | memory_free( |
816 | 4.88M | data ); |
817 | | |
818 | 4.88M | return( 1 ); |
819 | | |
820 | 390 | on_error: |
821 | 390 | if( data != NULL ) |
822 | 390 | { |
823 | 390 | memory_free( |
824 | 390 | data ); |
825 | 390 | } |
826 | 390 | return( -1 ); |
827 | 4.88M | } |
828 | | |