/src/libftxf/libftxf/libftxf_record.c
Line | Count | Source |
1 | | /* |
2 | | * Record functions |
3 | | * |
4 | | * Copyright (C) 2010-2026, 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 | 484 | { |
50 | 484 | libftxf_internal_record_t *internal_record = NULL; |
51 | 484 | static char *function = "libftxf_record_initialize"; |
52 | | |
53 | 484 | 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 | 484 | 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 | 484 | internal_record = memory_allocate_structure( |
76 | 484 | libftxf_internal_record_t ); |
77 | | |
78 | 484 | 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 | 484 | if( memory_set( |
90 | 484 | internal_record, |
91 | 484 | 0, |
92 | 484 | 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 | 484 | *record = (libftxf_record_t *) internal_record; |
104 | | |
105 | 484 | 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 | 484 | } |
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 | 484 | { |
123 | 484 | libftxf_internal_record_t *internal_record = NULL; |
124 | 484 | static char *function = "libftxf_record_free"; |
125 | | |
126 | 484 | 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 | 484 | if( *record != NULL ) |
138 | 484 | { |
139 | 484 | internal_record = (libftxf_internal_record_t *) *record; |
140 | 484 | *record = NULL; |
141 | | |
142 | 484 | memory_free( |
143 | 484 | internal_record ); |
144 | 484 | } |
145 | 484 | return( 1 ); |
146 | 484 | } |
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 | 381 | { |
157 | 381 | libfusn_record_t *usn_record = NULL; |
158 | 381 | static char *function = "libftxf_internal_record_read_update_journal_entry_list_data"; |
159 | 381 | size_t record_data_offset = 0; |
160 | 381 | uint64_t record_chain_next_lsn = 0; |
161 | 381 | uint32_t update_journal_entry_list_offset = 0; |
162 | 381 | uint32_t update_journal_entry_list_size = 0; |
163 | 381 | uint32_t usn_record_size = 0; |
164 | | |
165 | | #if defined( HAVE_DEBUG_OUTPUT ) |
166 | | uint64_t value_64bit = 0; |
167 | | #endif |
168 | | |
169 | 381 | 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 | 381 | 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 | 381 | 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 | 381 | if( record_data_size < ( sizeof( ftxf_record_header_t ) + 16 ) ) |
203 | 14 | { |
204 | 14 | libcerror_error_set( |
205 | 14 | error, |
206 | 14 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
207 | 14 | LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, |
208 | 14 | "%s: invalid record data value too small.", |
209 | 14 | function ); |
210 | | |
211 | 14 | return( -1 ); |
212 | 14 | } |
213 | 367 | 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 | 367 | byte_stream_copy_to_uint64_little_endian( |
228 | 367 | &( record_data[ record_data_offset ] ), |
229 | 367 | record_chain_next_lsn ); |
230 | | |
231 | 367 | record_data_offset += 8; |
232 | | |
233 | 367 | byte_stream_copy_to_uint32_little_endian( |
234 | 367 | &( record_data[ record_data_offset ] ), |
235 | 367 | update_journal_entry_list_offset ); |
236 | | |
237 | 367 | record_data_offset += 4; |
238 | | |
239 | 367 | byte_stream_copy_to_uint32_little_endian( |
240 | 367 | &( record_data[ record_data_offset ] ), |
241 | 367 | update_journal_entry_list_size ); |
242 | | |
243 | 367 | 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 | 367 | if( ( (size_t) update_journal_entry_list_offset < record_data_offset ) |
268 | 357 | || ( (size_t) update_journal_entry_list_offset > record_data_size ) ) |
269 | 60 | { |
270 | 60 | libcerror_error_set( |
271 | 60 | error, |
272 | 60 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
273 | 60 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
274 | 60 | "%s: update journal entry list offset value out of bounds.", |
275 | 60 | function ); |
276 | | |
277 | 60 | goto on_error; |
278 | 60 | } |
279 | 307 | 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 | 305 | if( (size_t) update_journal_entry_list_offset > record_data_offset ) |
291 | 48 | { |
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 | 48 | record_data_offset = (size_t) update_journal_entry_list_offset; |
305 | 48 | } |
306 | 826 | while( record_data_offset < record_data_size ) |
307 | 740 | { |
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 | 740 | record_data_offset += 8; |
335 | | |
336 | 740 | if( libfusn_record_initialize( |
337 | 740 | &usn_record, |
338 | 740 | 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 | 740 | if( libfusn_record_copy_from_byte_stream( |
350 | 740 | usn_record, |
351 | 740 | &( record_data[ record_data_offset ] ), |
352 | 740 | record_data_size - record_data_offset, |
353 | 740 | error ) != 1 ) |
354 | 219 | { |
355 | 219 | libcerror_error_set( |
356 | 219 | error, |
357 | 219 | LIBCERROR_ERROR_DOMAIN_IO, |
358 | 219 | LIBCERROR_IO_ERROR_READ_FAILED, |
359 | 219 | "%s: unable to read USN record.", |
360 | 219 | function ); |
361 | | |
362 | 219 | goto on_error; |
363 | 219 | } |
364 | 521 | if( libfusn_record_get_size( |
365 | 521 | usn_record, |
366 | 521 | &usn_record_size, |
367 | 521 | 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 | 521 | record_data_offset += (size_t) usn_record_size; |
379 | | |
380 | | /* TODO do something with USN records */ |
381 | 521 | if( libfusn_record_free( |
382 | 521 | &usn_record, |
383 | 521 | 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 | 521 | } |
395 | 86 | return( 1 ); |
396 | | |
397 | 281 | on_error: |
398 | 281 | if( usn_record != NULL ) |
399 | 219 | { |
400 | 219 | libfusn_record_free( |
401 | 219 | &usn_record, |
402 | 219 | NULL ); |
403 | 219 | } |
404 | 281 | return( -1 ); |
405 | 305 | } |
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 | 484 | { |
416 | 484 | libftxf_internal_record_t *internal_record = NULL; |
417 | 484 | static char *function = "libftxf_record_read"; |
418 | 484 | size_t byte_stream_offset = 0; |
419 | 484 | uint16_t record_type = 0; |
420 | 484 | uint16_t name_offset = 0; |
421 | 484 | 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 | 484 | 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 | 484 | internal_record = (libftxf_internal_record_t *) record; |
441 | | |
442 | 484 | 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 | 484 | 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 | 484 | 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 | 470 | byte_stream_copy_to_uint16_little_endian( |
488 | 470 | ( (ftxf_record_header_t *) byte_stream )->record_type, |
489 | 470 | record_type ); |
490 | | |
491 | 470 | byte_stream_copy_to_uint32_little_endian( |
492 | 470 | ( (ftxf_record_header_t *) byte_stream )->record_size, |
493 | 470 | 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 | 470 | byte_stream_offset = sizeof( ftxf_record_header_t ); |
622 | | |
623 | 470 | if( ( (size_t) internal_record->size < sizeof( ftxf_record_header_t ) ) |
624 | 461 | || ( (size_t) internal_record->size > byte_stream_size ) ) |
625 | 56 | { |
626 | 56 | libcerror_error_set( |
627 | 56 | error, |
628 | 56 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
629 | 56 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
630 | 56 | "%s: record size value out of bounds.", |
631 | 56 | function ); |
632 | | |
633 | 56 | return( -1 ); |
634 | 56 | } |
635 | 414 | switch( record_type ) |
636 | 414 | { |
637 | 381 | case LIBFTXF_RECORD_TYPE_UPDATE_JOURNAL_ENTRIES_LIST: |
638 | 381 | if( libftxf_internal_record_read_update_journal_entry_list_data( |
639 | 381 | internal_record, |
640 | 381 | byte_stream, |
641 | 381 | (size_t) internal_record->size, |
642 | 381 | error ) != 1 ) |
643 | 295 | { |
644 | 295 | libcerror_error_set( |
645 | 295 | error, |
646 | 295 | LIBCERROR_ERROR_DOMAIN_IO, |
647 | 295 | LIBCERROR_IO_ERROR_READ_FAILED, |
648 | 295 | "%s: unable to read update journal entry list.", |
649 | 295 | function ); |
650 | | |
651 | 295 | return( -1 ); |
652 | 295 | } |
653 | 86 | break; |
654 | | |
655 | 86 | default: |
656 | 33 | break; |
657 | 414 | } |
658 | | /* TODO refactor */ |
659 | 119 | if( record_type == LIBFTXF_RECORD_TYPE_UPDATE_JOURNAL_ENTRIES_LIST ) |
660 | 86 | { |
661 | 86 | return( 1 ); |
662 | 86 | } |
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 | 33 | byte_stream_offset += 8; |
688 | | |
689 | 33 | if( record_type != 0x00 ) |
690 | 31 | { |
691 | 31 | byte_stream_copy_to_uint16_little_endian( |
692 | 31 | &( byte_stream[ byte_stream_offset ] ), |
693 | 31 | 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 | 31 | byte_stream_offset += 2; |
705 | | |
706 | 31 | name_size *= 2; |
707 | | |
708 | 31 | byte_stream_copy_to_uint16_little_endian( |
709 | 31 | &( byte_stream[ byte_stream_offset ] ), |
710 | 31 | 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 | | byte_stream_offset += 2; |
721 | | |
722 | | byte_stream_copy_to_uint32_little_endian( |
723 | | &( byte_stream[ byte_stream_offset ] ), |
724 | | value_32bit ); |
725 | | libcnotify_printf( |
726 | | "%s: unknown13\t\t\t\t\t\t: 0x%08" PRIx32 "\n", |
727 | | function, |
728 | | value_32bit ); |
729 | | |
730 | | byte_stream_offset += 4; |
731 | | } |
732 | | #endif |
733 | 31 | } |
734 | 33 | if( record_type == 0x02 ) |
735 | 0 | { |
736 | | #if defined( HAVE_DEBUG_OUTPUT ) |
737 | | if( libcnotify_verbose != 0 ) |
738 | | { |
739 | | libcnotify_printf( |
740 | | "...\n\n" ); |
741 | | |
742 | | /* TODO print debug */ |
743 | | byte_stream_offset += 24; |
744 | | } |
745 | | #endif |
746 | 0 | } |
747 | 33 | if( ( record_type == 0x02 ) |
748 | 33 | || ( record_type == 0x07 ) ) |
749 | 0 | { |
750 | | #if defined( HAVE_DEBUG_OUTPUT ) |
751 | | if( libcnotify_verbose != 0 ) |
752 | | { |
753 | | if( libftxf_debug_print_filetime_value( |
754 | | function, |
755 | | "creation time\t\t\t\t\t", |
756 | | &( byte_stream[ byte_stream_offset ] ), |
757 | | 8, |
758 | | LIBFDATETIME_ENDIAN_LITTLE, |
759 | | LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, |
760 | | error ) != 1 ) |
761 | | { |
762 | | libcerror_error_set( |
763 | | error, |
764 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
765 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
766 | | "%s: unable to print FILETIME value.", |
767 | | function ); |
768 | | |
769 | | return( -1 ); |
770 | | } |
771 | | byte_stream_offset += 8; |
772 | | |
773 | | if( libftxf_debug_print_filetime_value( |
774 | | function, |
775 | | "modification time\t\t\t\t\t", |
776 | | &( byte_stream[ byte_stream_offset ] ), |
777 | | 8, |
778 | | LIBFDATETIME_ENDIAN_LITTLE, |
779 | | LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, |
780 | | error ) != 1 ) |
781 | | { |
782 | | libcerror_error_set( |
783 | | error, |
784 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
785 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
786 | | "%s: unable to print FILETIME value.", |
787 | | function ); |
788 | | |
789 | | return( -1 ); |
790 | | } |
791 | | byte_stream_offset += 8; |
792 | | |
793 | | if( libftxf_debug_print_filetime_value( |
794 | | function, |
795 | | "entry modification time\t\t\t\t", |
796 | | &( byte_stream[ byte_stream_offset ] ), |
797 | | 8, |
798 | | LIBFDATETIME_ENDIAN_LITTLE, |
799 | | LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, |
800 | | error ) != 1 ) |
801 | | { |
802 | | libcerror_error_set( |
803 | | error, |
804 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
805 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
806 | | "%s: unable to print FILETIME value.", |
807 | | function ); |
808 | | |
809 | | return( -1 ); |
810 | | } |
811 | | byte_stream_offset += 8; |
812 | | |
813 | | if( libftxf_debug_print_filetime_value( |
814 | | function, |
815 | | "access time\t\t\t\t\t", |
816 | | &( byte_stream[ byte_stream_offset ] ), |
817 | | 8, |
818 | | LIBFDATETIME_ENDIAN_LITTLE, |
819 | | LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, |
820 | | error ) != 1 ) |
821 | | { |
822 | | libcerror_error_set( |
823 | | error, |
824 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
825 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
826 | | "%s: unable to print FILETIME value.", |
827 | | function ); |
828 | | |
829 | | return( -1 ); |
830 | | } |
831 | | byte_stream_offset += 8; |
832 | | |
833 | | byte_stream_copy_to_uint64_little_endian( |
834 | | &( byte_stream[ byte_stream_offset ] ), |
835 | | value_64bit ); |
836 | | libcnotify_printf( |
837 | | "%s: allocated file size\t\t\t\t: %" PRIu64 "\n", |
838 | | function, |
839 | | value_64bit ); |
840 | | |
841 | | byte_stream_offset += 8; |
842 | | |
843 | | byte_stream_copy_to_uint64_little_endian( |
844 | | &( byte_stream[ byte_stream_offset ] ), |
845 | | value_64bit ); |
846 | | libcnotify_printf( |
847 | | "%s: file size\t\t\t\t\t\t: %" PRIu64 "\n", |
848 | | function, |
849 | | value_64bit ); |
850 | | |
851 | | byte_stream_offset += 8; |
852 | | |
853 | | byte_stream_copy_to_uint32_little_endian( |
854 | | &( byte_stream[ byte_stream_offset ] ), |
855 | | value_32bit ); |
856 | | libcnotify_printf( |
857 | | "%s: file attribute flags\t\t\t\t: 0x%08" PRIx32 "\n", |
858 | | function, |
859 | | value_32bit ); |
860 | | libftxf_debug_print_file_attribute_flags( |
861 | | value_32bit ); |
862 | | libcnotify_printf( |
863 | | "\n" ); |
864 | | |
865 | | byte_stream_offset += 4; |
866 | | |
867 | | libcnotify_printf( |
868 | | "...\n\n" ); |
869 | | } |
870 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
871 | 0 | } |
872 | 33 | else if( record_type == 0x0b ) |
873 | 1 | { |
874 | | #if defined( HAVE_DEBUG_OUTPUT ) |
875 | | if( libcnotify_verbose != 0 ) |
876 | | { |
877 | | byte_stream_copy_to_uint64_little_endian( |
878 | | &( byte_stream[ byte_stream_offset ] ), |
879 | | value_64bit ); |
880 | | libcnotify_printf( |
881 | | "%s: unknown14\t\t\t\t\t\t: 0x%08" PRIx64 "\n", |
882 | | function, |
883 | | value_64bit ); |
884 | | |
885 | | byte_stream_offset += 8; |
886 | | } |
887 | | #endif |
888 | 1 | } |
889 | | #if defined( HAVE_DEBUG_OUTPUT ) |
890 | | else if( libcnotify_verbose != 0 ) |
891 | | { |
892 | | libcnotify_printf( |
893 | | "...\n\n" ); |
894 | | } |
895 | | #endif |
896 | 33 | if( record_type == 0x15 ) |
897 | 1 | { |
898 | 1 | return( 1 ); |
899 | 1 | } |
900 | 32 | if( name_size > 0 ) |
901 | 28 | { |
902 | | /* TODO check if name size is within bounds */ |
903 | | /* TODO check if name offset is within bounds */ |
904 | | |
905 | | #if defined( HAVE_DEBUG_OUTPUT ) |
906 | | if( libcnotify_verbose != 0 ) |
907 | | { |
908 | | if( libftxf_debug_print_utf16_string_value( |
909 | | function, |
910 | | "name\t\t\t\t\t\t", |
911 | | &( byte_stream[ name_offset ] ), |
912 | | name_size, |
913 | | LIBUNA_ENDIAN_LITTLE, |
914 | | error ) != 1 ) |
915 | | { |
916 | | libcerror_error_set( |
917 | | error, |
918 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
919 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
920 | | "%s: unable to print UTF-16 string value.", |
921 | | function ); |
922 | | |
923 | | return( -1 ); |
924 | | } |
925 | | } |
926 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
927 | 28 | } |
928 | | #if defined( HAVE_DEBUG_OUTPUT ) |
929 | | if( libcnotify_verbose != 0 ) |
930 | | { |
931 | | libcnotify_printf( |
932 | | "\n" ); |
933 | | } |
934 | | #endif |
935 | 32 | return( 1 ); |
936 | 33 | } |
937 | | |