/src/libftxf/libftxf/libftxf_record.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Record 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 <narrow_string.h> |
26 | | #include <system_string.h> |
27 | | #include <types.h> |
28 | | #include <wide_string.h> |
29 | | |
30 | | #include "libftxf_debug.h" |
31 | | #include "libftxf_definitions.h" |
32 | | #include "libftxf_libcerror.h" |
33 | | #include "libftxf_libcnotify.h" |
34 | | #include "libftxf_libfdatetime.h" |
35 | | #include "libftxf_libfguid.h" |
36 | | #include "libftxf_libfusn.h" |
37 | | #include "libftxf_libuna.h" |
38 | | #include "libftxf_record.h" |
39 | | |
40 | | #include "ftxf_record.h" |
41 | | |
42 | | /* Creates a record |
43 | | * Make sure the value record is referencing, is set to NULL |
44 | | * Returns 1 if successful or -1 on error |
45 | | */ |
46 | | int libftxf_record_initialize( |
47 | | libftxf_record_t **record, |
48 | | libcerror_error_t **error ) |
49 | 488 | { |
50 | 488 | libftxf_internal_record_t *internal_record = NULL; |
51 | 488 | static char *function = "libftxf_record_initialize"; |
52 | | |
53 | 488 | if( record == NULL ) |
54 | 0 | { |
55 | 0 | libcerror_error_set( |
56 | 0 | error, |
57 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
58 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
59 | 0 | "%s: invalid record.", |
60 | 0 | function ); |
61 | |
|
62 | 0 | return( -1 ); |
63 | 0 | } |
64 | 488 | if( *record != NULL ) |
65 | 0 | { |
66 | 0 | libcerror_error_set( |
67 | 0 | error, |
68 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
69 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
70 | 0 | "%s: invalid record value already set.", |
71 | 0 | function ); |
72 | |
|
73 | 0 | return( -1 ); |
74 | 0 | } |
75 | 488 | internal_record = memory_allocate_structure( |
76 | 488 | libftxf_internal_record_t ); |
77 | | |
78 | 488 | if( internal_record == NULL ) |
79 | 0 | { |
80 | 0 | libcerror_error_set( |
81 | 0 | error, |
82 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
83 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
84 | 0 | "%s: unable to create record.", |
85 | 0 | function ); |
86 | |
|
87 | 0 | goto on_error; |
88 | 0 | } |
89 | 488 | if( memory_set( |
90 | 488 | internal_record, |
91 | 488 | 0, |
92 | 488 | sizeof( libftxf_internal_record_t ) ) == NULL ) |
93 | 0 | { |
94 | 0 | libcerror_error_set( |
95 | 0 | error, |
96 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
97 | 0 | LIBCERROR_MEMORY_ERROR_SET_FAILED, |
98 | 0 | "%s: unable to clear record.", |
99 | 0 | function ); |
100 | |
|
101 | 0 | goto on_error; |
102 | 0 | } |
103 | 488 | *record = (libftxf_record_t *) internal_record; |
104 | | |
105 | 488 | return( 1 ); |
106 | | |
107 | 0 | on_error: |
108 | 0 | if( internal_record != NULL ) |
109 | 0 | { |
110 | 0 | memory_free( |
111 | 0 | internal_record ); |
112 | 0 | } |
113 | 0 | return( -1 ); |
114 | 488 | } |
115 | | |
116 | | /* Frees a record |
117 | | * Returns 1 if successful or -1 on error |
118 | | */ |
119 | | int libftxf_record_free( |
120 | | libftxf_record_t **record, |
121 | | libcerror_error_t **error ) |
122 | 488 | { |
123 | 488 | libftxf_internal_record_t *internal_record = NULL; |
124 | 488 | static char *function = "libftxf_record_free"; |
125 | | |
126 | 488 | if( record == NULL ) |
127 | 0 | { |
128 | 0 | libcerror_error_set( |
129 | 0 | error, |
130 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
131 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
132 | 0 | "%s: invalid record.", |
133 | 0 | function ); |
134 | |
|
135 | 0 | return( -1 ); |
136 | 0 | } |
137 | 488 | if( *record != NULL ) |
138 | 488 | { |
139 | 488 | internal_record = (libftxf_internal_record_t *) *record; |
140 | 488 | *record = NULL; |
141 | | |
142 | 488 | memory_free( |
143 | 488 | internal_record ); |
144 | 488 | } |
145 | 488 | return( 1 ); |
146 | 488 | } |
147 | | |
148 | | /* Reads the update journal entry list |
149 | | * Returns 1 if successful or -1 on error |
150 | | */ |
151 | | int libftxf_internal_record_read_update_journal_entry_list_data( |
152 | | libftxf_internal_record_t *internal_record, |
153 | | const uint8_t *record_data, |
154 | | size_t record_data_size, |
155 | | libcerror_error_t **error ) |
156 | 379 | { |
157 | 379 | libfusn_record_t *usn_record = NULL; |
158 | 379 | static char *function = "libftxf_internal_record_read_update_journal_entry_list_data"; |
159 | 379 | size_t record_data_offset = 0; |
160 | 379 | uint64_t record_chain_next_lsn = 0; |
161 | 379 | uint32_t update_journal_entry_list_offset = 0; |
162 | 379 | uint32_t update_journal_entry_list_size = 0; |
163 | 379 | uint32_t usn_record_size = 0; |
164 | | |
165 | | #if defined( HAVE_DEBUG_OUTPUT ) |
166 | | uint64_t value_64bit = 0; |
167 | | #endif |
168 | | |
169 | 379 | if( internal_record == NULL ) |
170 | 0 | { |
171 | 0 | libcerror_error_set( |
172 | 0 | error, |
173 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
174 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
175 | 0 | "%s: invalid internal record.", |
176 | 0 | function ); |
177 | |
|
178 | 0 | return( -1 ); |
179 | 0 | } |
180 | 379 | if( record_data == NULL ) |
181 | 0 | { |
182 | 0 | libcerror_error_set( |
183 | 0 | error, |
184 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
185 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
186 | 0 | "%s: invalid record data.", |
187 | 0 | function ); |
188 | |
|
189 | 0 | return( -1 ); |
190 | 0 | } |
191 | 379 | if( record_data_size > (size_t) SSIZE_MAX ) |
192 | 0 | { |
193 | 0 | libcerror_error_set( |
194 | 0 | error, |
195 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
196 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, |
197 | 0 | "%s: invalid record data size value exceeds maximum.", |
198 | 0 | function ); |
199 | |
|
200 | 0 | return( -1 ); |
201 | 0 | } |
202 | 379 | if( record_data_size < ( sizeof( ftxf_record_header_t ) + 16 ) ) |
203 | 7 | { |
204 | 7 | libcerror_error_set( |
205 | 7 | error, |
206 | 7 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
207 | 7 | LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, |
208 | 7 | "%s: invalid record data value too small.", |
209 | 7 | function ); |
210 | | |
211 | 7 | return( -1 ); |
212 | 7 | } |
213 | 372 | record_data_offset = sizeof( ftxf_record_header_t ); |
214 | | |
215 | | #if defined( HAVE_DEBUG_OUTPUT ) |
216 | | if( libcnotify_verbose != 0 ) |
217 | | { |
218 | | libcnotify_printf( |
219 | | "%s: journal entry list data:\n", |
220 | | function ); |
221 | | libcnotify_print_data( |
222 | | &( record_data[ record_data_offset ] ), |
223 | | 16, |
224 | | 0 ); |
225 | | } |
226 | | #endif |
227 | 372 | byte_stream_copy_to_uint64_little_endian( |
228 | 372 | &( record_data[ record_data_offset ] ), |
229 | 372 | record_chain_next_lsn ); |
230 | | |
231 | 372 | record_data_offset += 8; |
232 | | |
233 | 372 | byte_stream_copy_to_uint32_little_endian( |
234 | 372 | &( record_data[ record_data_offset ] ), |
235 | 372 | update_journal_entry_list_offset ); |
236 | | |
237 | 372 | record_data_offset += 4; |
238 | | |
239 | 372 | byte_stream_copy_to_uint32_little_endian( |
240 | 372 | &( record_data[ record_data_offset ] ), |
241 | 372 | update_journal_entry_list_size ); |
242 | | |
243 | 372 | record_data_offset += 4; |
244 | | |
245 | | #if defined( HAVE_DEBUG_OUTPUT ) |
246 | | if( libcnotify_verbose != 0 ) |
247 | | { |
248 | | libcnotify_printf( |
249 | | "%s: next record lsn\t\t: 0x%08" PRIx64 "\n", |
250 | | function, |
251 | | record_chain_next_lsn ); |
252 | | |
253 | | libcnotify_printf( |
254 | | "%s: list entries offset\t: 0x%08" PRIx32 "\n", |
255 | | function, |
256 | | update_journal_entry_list_offset ); |
257 | | |
258 | | libcnotify_printf( |
259 | | "%s: list entries size\t\t: %" PRIu32 "\n", |
260 | | function, |
261 | | update_journal_entry_list_size ); |
262 | | |
263 | | libcnotify_printf( |
264 | | "\n" ); |
265 | | } |
266 | | #endif |
267 | 372 | if( ( (size_t) update_journal_entry_list_offset < record_data_offset ) |
268 | 372 | || ( (size_t) update_journal_entry_list_offset > record_data_size ) ) |
269 | 57 | { |
270 | 57 | libcerror_error_set( |
271 | 57 | error, |
272 | 57 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
273 | 57 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
274 | 57 | "%s: update journal entry list offset value out of bounds.", |
275 | 57 | function ); |
276 | | |
277 | 57 | goto on_error; |
278 | 57 | } |
279 | 315 | if( ( (size_t) update_journal_entry_list_offset + (size_t) update_journal_entry_list_size ) < record_data_size ) |
280 | 2 | { |
281 | 2 | libcerror_error_set( |
282 | 2 | error, |
283 | 2 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
284 | 2 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
285 | 2 | "%s: update journal entry list size value out of bounds.", |
286 | 2 | function ); |
287 | | |
288 | 2 | goto on_error; |
289 | 2 | } |
290 | 313 | if( (size_t) update_journal_entry_list_offset > record_data_offset ) |
291 | 51 | { |
292 | | #if defined( HAVE_DEBUG_OUTPUT ) |
293 | | if( libcnotify_verbose != 0 ) |
294 | | { |
295 | | libcnotify_printf( |
296 | | "%s: update journal entry list trailing data:\n", |
297 | | function ); |
298 | | libcnotify_print_data( |
299 | | &( record_data[ record_data_offset ] ), |
300 | | (size_t) update_journal_entry_list_offset - record_data_offset, |
301 | | 0 ); |
302 | | } |
303 | | #endif |
304 | 51 | record_data_offset = (size_t) update_journal_entry_list_offset; |
305 | 51 | } |
306 | 792 | while( record_data_offset < record_data_size ) |
307 | 702 | { |
308 | | /* TODO print entry number */ |
309 | | |
310 | | #if defined( HAVE_DEBUG_OUTPUT ) |
311 | | if( libcnotify_verbose != 0 ) |
312 | | { |
313 | | libcnotify_printf( |
314 | | "%s: unknown:\n", |
315 | | function ); |
316 | | libcnotify_print_data( |
317 | | &( record_data[ record_data_offset ] ), |
318 | | 8, |
319 | | 0 ); |
320 | | } |
321 | | #endif |
322 | | #if defined( HAVE_DEBUG_OUTPUT ) |
323 | | if( libcnotify_verbose != 0 ) |
324 | | { |
325 | | byte_stream_copy_to_uint64_little_endian( |
326 | | &( record_data[ record_data_offset ] ), |
327 | | value_64bit ); |
328 | | libcnotify_printf( |
329 | | "%s: unknown\t\t\t: 0x%08" PRIx64 "\n", |
330 | | function, |
331 | | value_64bit ); |
332 | | } |
333 | | #endif |
334 | 702 | record_data_offset += 8; |
335 | | |
336 | 702 | if( libfusn_record_initialize( |
337 | 702 | &usn_record, |
338 | 702 | error ) != 1 ) |
339 | 0 | { |
340 | 0 | libcerror_error_set( |
341 | 0 | error, |
342 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
343 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
344 | 0 | "%s: unable to create USN record.", |
345 | 0 | function ); |
346 | |
|
347 | 0 | goto on_error; |
348 | 0 | } |
349 | 702 | if( libfusn_record_copy_from_byte_stream( |
350 | 702 | usn_record, |
351 | 702 | &( record_data[ record_data_offset ] ), |
352 | 702 | record_data_size - record_data_offset, |
353 | 702 | error ) != 1 ) |
354 | 223 | { |
355 | 223 | libcerror_error_set( |
356 | 223 | error, |
357 | 223 | LIBCERROR_ERROR_DOMAIN_IO, |
358 | 223 | LIBCERROR_IO_ERROR_READ_FAILED, |
359 | 223 | "%s: unable to read USN record.", |
360 | 223 | function ); |
361 | | |
362 | 223 | goto on_error; |
363 | 223 | } |
364 | 479 | if( libfusn_record_get_size( |
365 | 479 | usn_record, |
366 | 479 | &usn_record_size, |
367 | 479 | error ) != 1 ) |
368 | 0 | { |
369 | 0 | libcerror_error_set( |
370 | 0 | error, |
371 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
372 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
373 | 0 | "%s: unable to retrieve USN record size.", |
374 | 0 | function ); |
375 | |
|
376 | 0 | goto on_error; |
377 | 0 | } |
378 | 479 | record_data_offset += (size_t) usn_record_size; |
379 | | |
380 | | /* TODO do something with USN records */ |
381 | 479 | if( libfusn_record_free( |
382 | 479 | &usn_record, |
383 | 479 | error ) != 1 ) |
384 | 0 | { |
385 | 0 | libcerror_error_set( |
386 | 0 | error, |
387 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
388 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
389 | 0 | "%s: unable to free USN record.", |
390 | 0 | function ); |
391 | |
|
392 | 0 | goto on_error; |
393 | 0 | } |
394 | 479 | } |
395 | 90 | return( 1 ); |
396 | | |
397 | 282 | on_error: |
398 | 282 | if( usn_record != NULL ) |
399 | 223 | { |
400 | 223 | libfusn_record_free( |
401 | 223 | &usn_record, |
402 | 223 | NULL ); |
403 | 223 | } |
404 | 282 | return( -1 ); |
405 | 313 | } |
406 | | |
407 | | /* Copies the record from the byte stream |
408 | | * Returns 1 if successful or -1 on error |
409 | | */ |
410 | | int libftxf_record_copy_from_byte_stream( |
411 | | libftxf_record_t *record, |
412 | | const uint8_t *byte_stream, |
413 | | size_t byte_stream_size, |
414 | | libcerror_error_t **error ) |
415 | 488 | { |
416 | 488 | libftxf_internal_record_t *internal_record = NULL; |
417 | 488 | static char *function = "libftxf_record_read"; |
418 | 488 | size_t byte_stream_offset = 0; |
419 | 488 | uint16_t record_type = 0; |
420 | 488 | uint16_t name_offset = 0; |
421 | 488 | uint16_t name_size = 0; |
422 | | |
423 | | #if defined( HAVE_DEBUG_OUTPUT ) |
424 | | uint64_t value_64bit = 0; |
425 | | uint32_t value_32bit = 0; |
426 | | uint16_t value_16bit = 0; |
427 | | #endif |
428 | | |
429 | 488 | if( record == NULL ) |
430 | 0 | { |
431 | 0 | libcerror_error_set( |
432 | 0 | error, |
433 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
434 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
435 | 0 | "%s: invalid record.", |
436 | 0 | function ); |
437 | |
|
438 | 0 | return( -1 ); |
439 | 0 | } |
440 | 488 | internal_record = (libftxf_internal_record_t *) record; |
441 | | |
442 | 488 | if( byte_stream == NULL ) |
443 | 0 | { |
444 | 0 | libcerror_error_set( |
445 | 0 | error, |
446 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
447 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
448 | 0 | "%s: invalid byte stream.", |
449 | 0 | function ); |
450 | |
|
451 | 0 | return( -1 ); |
452 | 0 | } |
453 | 488 | if( byte_stream_size > (size_t) SSIZE_MAX ) |
454 | 0 | { |
455 | 0 | libcerror_error_set( |
456 | 0 | error, |
457 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
458 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, |
459 | 0 | "%s: invalid byte stream size value exceeds maximum.", |
460 | 0 | function ); |
461 | |
|
462 | 0 | return( -1 ); |
463 | 0 | } |
464 | 488 | if( byte_stream_size < sizeof( ftxf_record_header_t ) ) |
465 | 14 | { |
466 | 14 | libcerror_error_set( |
467 | 14 | error, |
468 | 14 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
469 | 14 | LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, |
470 | 14 | "%s: invalid byte stream value too small.", |
471 | 14 | function ); |
472 | | |
473 | 14 | return( -1 ); |
474 | 14 | } |
475 | | #if defined( HAVE_DEBUG_OUTPUT ) |
476 | | if( libcnotify_verbose != 0 ) |
477 | | { |
478 | | libcnotify_printf( |
479 | | "%s: record header data:\n", |
480 | | function ); |
481 | | libcnotify_print_data( |
482 | | byte_stream, |
483 | | sizeof( ftxf_record_header_t ), |
484 | | 0 ); |
485 | | } |
486 | | #endif |
487 | 474 | byte_stream_copy_to_uint16_little_endian( |
488 | 474 | ( (ftxf_record_header_t *) byte_stream )->record_type, |
489 | 474 | record_type ); |
490 | | |
491 | 474 | byte_stream_copy_to_uint32_little_endian( |
492 | 474 | ( (ftxf_record_header_t *) byte_stream )->record_size, |
493 | 474 | internal_record->size ); |
494 | | |
495 | | #if defined( HAVE_DEBUG_OUTPUT ) |
496 | | if( libcnotify_verbose != 0 ) |
497 | | { |
498 | | byte_stream_copy_to_uint32_little_endian( |
499 | | ( (ftxf_record_header_t *) byte_stream )->unknown1, |
500 | | value_32bit ); |
501 | | libcnotify_printf( |
502 | | "%s: unknown1\t\t\t\t\t\t: 0x%08" PRIx32 "\n", |
503 | | function, |
504 | | value_32bit ); |
505 | | |
506 | | libcnotify_printf( |
507 | | "%s: record type\t\t\t\t\t: 0x%04" PRIx16 "\n", |
508 | | function, |
509 | | record_type ); |
510 | | |
511 | | byte_stream_copy_to_uint16_little_endian( |
512 | | ( (ftxf_record_header_t *) byte_stream )->unknown2, |
513 | | value_16bit ); |
514 | | libcnotify_printf( |
515 | | "%s: unknown2\t\t\t\t\t\t: 0x%04" PRIx16 "\n", |
516 | | function, |
517 | | value_16bit ); |
518 | | |
519 | | byte_stream_copy_to_uint64_little_endian( |
520 | | ( (ftxf_record_header_t *) byte_stream )->file_identifier, |
521 | | value_64bit ); |
522 | | libcnotify_printf( |
523 | | "%s: file identifier\t\t\t\t\t: 0x%08" PRIx64 "\n", |
524 | | function, |
525 | | value_64bit ); |
526 | | |
527 | | byte_stream_copy_to_uint64_little_endian( |
528 | | ( (ftxf_record_header_t *) byte_stream )->file_reference, |
529 | | value_64bit ); |
530 | | libcnotify_printf( |
531 | | "%s: file reference\t\t\t\t\t: MFT entry: %" PRIu64 ", sequence: %" PRIu64 "\n", |
532 | | function, |
533 | | value_64bit & 0xffffffffffffUL, |
534 | | value_64bit >> 48 ); |
535 | | |
536 | | byte_stream_copy_to_uint32_little_endian( |
537 | | ( (ftxf_record_header_t *) byte_stream )->unknown4, |
538 | | value_32bit ); |
539 | | libcnotify_printf( |
540 | | "%s: unknown4\t\t\t\t\t\t: 0x%08" PRIx32 "\n", |
541 | | function, |
542 | | value_32bit ); |
543 | | |
544 | | byte_stream_copy_to_uint32_little_endian( |
545 | | ( (ftxf_record_header_t *) byte_stream )->unknown5, |
546 | | value_32bit ); |
547 | | libcnotify_printf( |
548 | | "%s: unknown5\t\t\t\t\t\t: 0x%08" PRIx32 "\n", |
549 | | function, |
550 | | value_32bit ); |
551 | | |
552 | | if( libftxf_debug_print_guid_value( |
553 | | function, |
554 | | "unknown6 guid\t\t\t\t\t", |
555 | | ( (ftxf_record_header_t *) byte_stream )->unknown6, |
556 | | 16, |
557 | | LIBFGUID_ENDIAN_LITTLE, |
558 | | LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, |
559 | | error ) != 1 ) |
560 | | { |
561 | | libcerror_error_set( |
562 | | error, |
563 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
564 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
565 | | "%s: unable to print GUID value.", |
566 | | function ); |
567 | | |
568 | | return( -1 ); |
569 | | } |
570 | | byte_stream_copy_to_uint64_little_endian( |
571 | | ( (ftxf_record_header_t *) byte_stream )->unknown7, |
572 | | value_64bit ); |
573 | | libcnotify_printf( |
574 | | "%s: unknown7\t\t\t\t\t\t: 0x%08" PRIx64 "\n", |
575 | | function, |
576 | | value_64bit ); |
577 | | |
578 | | if( libftxf_debug_print_filetime_value( |
579 | | function, |
580 | | "unknown8 filetime\t\t\t\t\t", |
581 | | ( (ftxf_record_header_t *) byte_stream )->unknown8, |
582 | | 8, |
583 | | LIBFDATETIME_ENDIAN_LITTLE, |
584 | | LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, |
585 | | error ) != 1 ) |
586 | | { |
587 | | libcerror_error_set( |
588 | | error, |
589 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
590 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
591 | | "%s: unable to print FILETIME value.", |
592 | | function ); |
593 | | |
594 | | return( -1 ); |
595 | | } |
596 | | libcnotify_printf( |
597 | | "%s: record size\t\t\t\t\t: %" PRIu32 "\n", |
598 | | function, |
599 | | internal_record->size ); |
600 | | |
601 | | byte_stream_copy_to_uint32_little_endian( |
602 | | ( (ftxf_record_header_t *) byte_stream )->unknown9, |
603 | | value_32bit ); |
604 | | libcnotify_printf( |
605 | | "%s: unknown9\t\t\t\t\t\t: 0x%08" PRIx32 "\n", |
606 | | function, |
607 | | value_32bit ); |
608 | | |
609 | | byte_stream_copy_to_uint64_little_endian( |
610 | | ( (ftxf_record_header_t *) byte_stream )->unknown10, |
611 | | value_64bit ); |
612 | | libcnotify_printf( |
613 | | "%s: unknown10\t\t\t\t\t\t: 0x%08" PRIx64 "\n", |
614 | | function, |
615 | | value_64bit ); |
616 | | |
617 | | libcnotify_printf( |
618 | | "\n" ); |
619 | | } |
620 | | #endif |
621 | 474 | byte_stream_offset = sizeof( ftxf_record_header_t ); |
622 | | |
623 | 474 | if( ( (size_t) internal_record->size < sizeof( ftxf_record_header_t ) ) |
624 | 474 | || ( (size_t) internal_record->size > byte_stream_size ) ) |
625 | 77 | { |
626 | 77 | libcerror_error_set( |
627 | 77 | error, |
628 | 77 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
629 | 77 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
630 | 77 | "%s: record size value out of bounds.", |
631 | 77 | function ); |
632 | | |
633 | 77 | return( -1 ); |
634 | 77 | } |
635 | 397 | switch( record_type ) |
636 | 397 | { |
637 | 379 | case LIBFTXF_RECORD_TYPE_UPDATE_JOURNAL_ENTRIES_LIST: |
638 | 379 | if( libftxf_internal_record_read_update_journal_entry_list_data( |
639 | 379 | internal_record, |
640 | 379 | byte_stream, |
641 | 379 | (size_t) internal_record->size, |
642 | 379 | error ) != 1 ) |
643 | 289 | { |
644 | 289 | libcerror_error_set( |
645 | 289 | error, |
646 | 289 | LIBCERROR_ERROR_DOMAIN_IO, |
647 | 289 | LIBCERROR_IO_ERROR_READ_FAILED, |
648 | 289 | "%s: unable to read update journal entry list.", |
649 | 289 | function ); |
650 | | |
651 | 289 | return( -1 ); |
652 | 289 | } |
653 | 90 | break; |
654 | | |
655 | 90 | default: |
656 | 18 | break; |
657 | 397 | } |
658 | | /* TODO refactor */ |
659 | 108 | if( record_type == LIBFTXF_RECORD_TYPE_UPDATE_JOURNAL_ENTRIES_LIST ) |
660 | 90 | { |
661 | 90 | return( 1 ); |
662 | 90 | } |
663 | | #if defined( HAVE_DEBUG_OUTPUT ) |
664 | | if( libcnotify_verbose != 0 ) |
665 | | { |
666 | | libcnotify_printf( |
667 | | "%s: record data:\n", |
668 | | function ); |
669 | | libcnotify_print_data( |
670 | | &( byte_stream[ byte_stream_offset ] ), |
671 | | (size_t) internal_record->size - sizeof( ftxf_record_header_t ), |
672 | | 0 ); |
673 | | } |
674 | | #endif |
675 | | #if defined( HAVE_DEBUG_OUTPUT ) |
676 | | if( libcnotify_verbose != 0 ) |
677 | | { |
678 | | byte_stream_copy_to_uint64_little_endian( |
679 | | &( byte_stream[ byte_stream_offset ] ), |
680 | | value_64bit ); |
681 | | libcnotify_printf( |
682 | | "%s: unknown11\t\t\t\t\t\t: 0x%08" PRIx64 "\n", |
683 | | function, |
684 | | value_64bit ); |
685 | | } |
686 | | #endif |
687 | 18 | byte_stream_offset += 8; |
688 | | |
689 | 18 | if( record_type != 0x00 ) |
690 | 17 | { |
691 | 17 | byte_stream_copy_to_uint16_little_endian( |
692 | 17 | &( byte_stream[ byte_stream_offset ] ), |
693 | 17 | name_size ); |
694 | | |
695 | | #if defined( HAVE_DEBUG_OUTPUT ) |
696 | | if( libcnotify_verbose != 0 ) |
697 | | { |
698 | | libcnotify_printf( |
699 | | "%s: name size\t\t\t\t\t\t: %" PRIu16 "\n", |
700 | | function, |
701 | | name_size ); |
702 | | } |
703 | | #endif |
704 | 17 | byte_stream_offset += 2; |
705 | | |
706 | 17 | name_size *= 2; |
707 | | |
708 | 17 | byte_stream_copy_to_uint16_little_endian( |
709 | 17 | &( byte_stream[ byte_stream_offset ] ), |
710 | 17 | name_offset ); |
711 | | |
712 | | #if defined( HAVE_DEBUG_OUTPUT ) |
713 | | if( libcnotify_verbose != 0 ) |
714 | | { |
715 | | libcnotify_printf( |
716 | | "%s: name offset\t\t\t\t\t: 0x%04" PRIx16 "\n", |
717 | | function, |
718 | | name_offset ); |
719 | | } |
720 | | #endif |
721 | 17 | byte_stream_offset += 2; |
722 | | |
723 | | #if defined( HAVE_DEBUG_OUTPUT ) |
724 | | if( libcnotify_verbose != 0 ) |
725 | | { |
726 | | byte_stream_copy_to_uint32_little_endian( |
727 | | &( byte_stream[ byte_stream_offset ] ), |
728 | | value_32bit ); |
729 | | libcnotify_printf( |
730 | | "%s: unknown13\t\t\t\t\t\t: 0x%08" PRIx32 "\n", |
731 | | function, |
732 | | value_32bit ); |
733 | | } |
734 | | #endif |
735 | 17 | byte_stream_offset += 4; |
736 | 17 | } |
737 | 18 | if( record_type == 0x02 ) |
738 | 0 | { |
739 | | #if defined( HAVE_DEBUG_OUTPUT ) |
740 | | if( libcnotify_verbose != 0 ) |
741 | | { |
742 | | libcnotify_printf( |
743 | | "...\n\n" ); |
744 | | } |
745 | | #endif |
746 | | /* TODO print debug */ |
747 | 0 | byte_stream_offset += 24; |
748 | 0 | } |
749 | 18 | if( ( record_type == 0x02 ) |
750 | 18 | || ( record_type == 0x07 ) ) |
751 | 1 | { |
752 | | #if defined( HAVE_DEBUG_OUTPUT ) |
753 | | if( libcnotify_verbose != 0 ) |
754 | | { |
755 | | if( libftxf_debug_print_filetime_value( |
756 | | function, |
757 | | "creation time\t\t\t\t\t", |
758 | | &( byte_stream[ byte_stream_offset ] ), |
759 | | 8, |
760 | | LIBFDATETIME_ENDIAN_LITTLE, |
761 | | LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, |
762 | | error ) != 1 ) |
763 | | { |
764 | | libcerror_error_set( |
765 | | error, |
766 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
767 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
768 | | "%s: unable to print FILETIME value.", |
769 | | function ); |
770 | | |
771 | | return( -1 ); |
772 | | } |
773 | | } |
774 | | #endif |
775 | 1 | byte_stream_offset += 8; |
776 | | |
777 | | #if defined( HAVE_DEBUG_OUTPUT ) |
778 | | if( libcnotify_verbose != 0 ) |
779 | | { |
780 | | if( libftxf_debug_print_filetime_value( |
781 | | function, |
782 | | "modification time\t\t\t\t\t", |
783 | | &( byte_stream[ byte_stream_offset ] ), |
784 | | 8, |
785 | | LIBFDATETIME_ENDIAN_LITTLE, |
786 | | LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, |
787 | | error ) != 1 ) |
788 | | { |
789 | | libcerror_error_set( |
790 | | error, |
791 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
792 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
793 | | "%s: unable to print FILETIME value.", |
794 | | function ); |
795 | | |
796 | | return( -1 ); |
797 | | } |
798 | | } |
799 | | #endif |
800 | 1 | byte_stream_offset += 8; |
801 | | |
802 | | #if defined( HAVE_DEBUG_OUTPUT ) |
803 | | if( libcnotify_verbose != 0 ) |
804 | | { |
805 | | if( libftxf_debug_print_filetime_value( |
806 | | function, |
807 | | "entry modification time\t\t\t\t", |
808 | | &( byte_stream[ byte_stream_offset ] ), |
809 | | 8, |
810 | | LIBFDATETIME_ENDIAN_LITTLE, |
811 | | LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, |
812 | | error ) != 1 ) |
813 | | { |
814 | | libcerror_error_set( |
815 | | error, |
816 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
817 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
818 | | "%s: unable to print FILETIME value.", |
819 | | function ); |
820 | | |
821 | | return( -1 ); |
822 | | } |
823 | | } |
824 | | #endif |
825 | 1 | byte_stream_offset += 8; |
826 | | |
827 | | #if defined( HAVE_DEBUG_OUTPUT ) |
828 | | if( libcnotify_verbose != 0 ) |
829 | | { |
830 | | if( libftxf_debug_print_filetime_value( |
831 | | function, |
832 | | "access time\t\t\t\t\t", |
833 | | &( byte_stream[ byte_stream_offset ] ), |
834 | | 8, |
835 | | LIBFDATETIME_ENDIAN_LITTLE, |
836 | | LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, |
837 | | error ) != 1 ) |
838 | | { |
839 | | libcerror_error_set( |
840 | | error, |
841 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
842 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
843 | | "%s: unable to print FILETIME value.", |
844 | | function ); |
845 | | |
846 | | return( -1 ); |
847 | | } |
848 | | } |
849 | | #endif |
850 | 1 | byte_stream_offset += 8; |
851 | | |
852 | | #if defined( HAVE_DEBUG_OUTPUT ) |
853 | | if( libcnotify_verbose != 0 ) |
854 | | { |
855 | | byte_stream_copy_to_uint64_little_endian( |
856 | | &( byte_stream[ byte_stream_offset ] ), |
857 | | value_64bit ); |
858 | | libcnotify_printf( |
859 | | "%s: allocated file size\t\t\t\t: %" PRIu64 "\n", |
860 | | function, |
861 | | value_64bit ); |
862 | | } |
863 | | #endif |
864 | 1 | byte_stream_offset += 8; |
865 | | |
866 | | #if defined( HAVE_DEBUG_OUTPUT ) |
867 | | if( libcnotify_verbose != 0 ) |
868 | | { |
869 | | byte_stream_copy_to_uint64_little_endian( |
870 | | &( byte_stream[ byte_stream_offset ] ), |
871 | | value_64bit ); |
872 | | libcnotify_printf( |
873 | | "%s: file size\t\t\t\t\t\t: %" PRIu64 "\n", |
874 | | function, |
875 | | value_64bit ); |
876 | | } |
877 | | #endif |
878 | 1 | byte_stream_offset += 8; |
879 | | |
880 | | #if defined( HAVE_DEBUG_OUTPUT ) |
881 | | if( libcnotify_verbose != 0 ) |
882 | | { |
883 | | byte_stream_copy_to_uint32_little_endian( |
884 | | &( byte_stream[ byte_stream_offset ] ), |
885 | | value_32bit ); |
886 | | libcnotify_printf( |
887 | | "%s: file attribute flags\t\t\t\t: 0x%08" PRIx32 "\n", |
888 | | function, |
889 | | value_32bit ); |
890 | | libftxf_debug_print_file_attribute_flags( |
891 | | value_32bit ); |
892 | | libcnotify_printf( |
893 | | "\n" ); |
894 | | } |
895 | | #endif |
896 | 1 | byte_stream_offset += 4; |
897 | | |
898 | | #if defined( HAVE_DEBUG_OUTPUT ) |
899 | | if( libcnotify_verbose != 0 ) |
900 | | { |
901 | | libcnotify_printf( |
902 | | "...\n\n" ); |
903 | | } |
904 | | #endif |
905 | 1 | } |
906 | 17 | else if( record_type == 0x0b ) |
907 | 0 | { |
908 | | #if defined( HAVE_DEBUG_OUTPUT ) |
909 | | if( libcnotify_verbose != 0 ) |
910 | | { |
911 | | byte_stream_copy_to_uint64_little_endian( |
912 | | &( byte_stream[ byte_stream_offset ] ), |
913 | | value_64bit ); |
914 | | libcnotify_printf( |
915 | | "%s: unknown14\t\t\t\t\t\t: 0x%08" PRIx64 "\n", |
916 | | function, |
917 | | value_64bit ); |
918 | | } |
919 | | #endif |
920 | 0 | byte_stream_offset += 8; |
921 | 0 | } |
922 | | #if defined( HAVE_DEBUG_OUTPUT ) |
923 | | else if( libcnotify_verbose != 0 ) |
924 | | { |
925 | | libcnotify_printf( |
926 | | "...\n\n" ); |
927 | | } |
928 | | #endif |
929 | 18 | if( record_type == 0x15 ) |
930 | 0 | { |
931 | 0 | return( 1 ); |
932 | 0 | } |
933 | 18 | if( name_size > 0 ) |
934 | 17 | { |
935 | | /* TODO check if name size is within bounds */ |
936 | | /* TODO check if name offset is within bounds */ |
937 | | |
938 | | #if defined( HAVE_DEBUG_OUTPUT ) |
939 | | if( libcnotify_verbose != 0 ) |
940 | | { |
941 | | if( libftxf_debug_print_utf16_string_value( |
942 | | function, |
943 | | "name\t\t\t\t\t\t", |
944 | | &( byte_stream[ name_offset ] ), |
945 | | name_size, |
946 | | LIBUNA_ENDIAN_LITTLE, |
947 | | error ) != 1 ) |
948 | | { |
949 | | libcerror_error_set( |
950 | | error, |
951 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
952 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
953 | | "%s: unable to print UTF-16 string value.", |
954 | | function ); |
955 | | |
956 | | return( -1 ); |
957 | | } |
958 | | } |
959 | | #endif |
960 | 17 | } |
961 | | #if defined( HAVE_DEBUG_OUTPUT ) |
962 | | if( libcnotify_verbose != 0 ) |
963 | | { |
964 | | libcnotify_printf( |
965 | | "\n" ); |
966 | | } |
967 | | #endif |
968 | 18 | return( 1 ); |
969 | 18 | } |
970 | | |