/src/libftxf/libfusn/libfusn_record.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Record functions |
3 | | * |
4 | | * Copyright (C) 2011-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 "libfusn_debug.h" |
31 | | #include "libfusn_libcerror.h" |
32 | | #include "libfusn_libcnotify.h" |
33 | | #include "libfusn_libfdatetime.h" |
34 | | #include "libfusn_libuna.h" |
35 | | #include "libfusn_record.h" |
36 | | |
37 | | #include "fusn_record.h" |
38 | | |
39 | | /* Creates a record |
40 | | * Make sure the value record is referencing, is set to NULL |
41 | | * Returns 1 if successful or -1 on error |
42 | | */ |
43 | | int libfusn_record_initialize( |
44 | | libfusn_record_t **record, |
45 | | libcerror_error_t **error ) |
46 | 892 | { |
47 | 892 | libfusn_internal_record_t *internal_record = NULL; |
48 | 892 | static char *function = "libfusn_record_initialize"; |
49 | | |
50 | 892 | if( record == NULL ) |
51 | 0 | { |
52 | 0 | libcerror_error_set( |
53 | 0 | error, |
54 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
55 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
56 | 0 | "%s: invalid record.", |
57 | 0 | function ); |
58 | |
|
59 | 0 | return( -1 ); |
60 | 0 | } |
61 | 892 | if( *record != NULL ) |
62 | 0 | { |
63 | 0 | libcerror_error_set( |
64 | 0 | error, |
65 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
66 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
67 | 0 | "%s: invalid record value already set.", |
68 | 0 | function ); |
69 | |
|
70 | 0 | return( -1 ); |
71 | 0 | } |
72 | 892 | internal_record = memory_allocate_structure( |
73 | 892 | libfusn_internal_record_t ); |
74 | | |
75 | 892 | if( internal_record == NULL ) |
76 | 0 | { |
77 | 0 | libcerror_error_set( |
78 | 0 | error, |
79 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
80 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
81 | 0 | "%s: unable to create record.", |
82 | 0 | function ); |
83 | |
|
84 | 0 | goto on_error; |
85 | 0 | } |
86 | 892 | if( memory_set( |
87 | 892 | internal_record, |
88 | 892 | 0, |
89 | 892 | sizeof( libfusn_internal_record_t ) ) == NULL ) |
90 | 0 | { |
91 | 0 | libcerror_error_set( |
92 | 0 | error, |
93 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
94 | 0 | LIBCERROR_MEMORY_ERROR_SET_FAILED, |
95 | 0 | "%s: unable to clear record.", |
96 | 0 | function ); |
97 | |
|
98 | 0 | goto on_error; |
99 | 0 | } |
100 | 892 | *record = (libfusn_record_t *) internal_record; |
101 | | |
102 | 892 | return( 1 ); |
103 | | |
104 | 0 | on_error: |
105 | 0 | if( internal_record != NULL ) |
106 | 0 | { |
107 | 0 | memory_free( |
108 | 0 | internal_record ); |
109 | 0 | } |
110 | 0 | return( -1 ); |
111 | 892 | } |
112 | | |
113 | | /* Frees a record |
114 | | * Returns 1 if successful or -1 on error |
115 | | */ |
116 | | int libfusn_record_free( |
117 | | libfusn_record_t **record, |
118 | | libcerror_error_t **error ) |
119 | 892 | { |
120 | 892 | libfusn_internal_record_t *internal_record = NULL; |
121 | 892 | static char *function = "libfusn_record_free"; |
122 | | |
123 | 892 | if( record == NULL ) |
124 | 0 | { |
125 | 0 | libcerror_error_set( |
126 | 0 | error, |
127 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
128 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
129 | 0 | "%s: invalid record.", |
130 | 0 | function ); |
131 | |
|
132 | 0 | return( -1 ); |
133 | 0 | } |
134 | 892 | if( *record != NULL ) |
135 | 892 | { |
136 | 892 | internal_record = (libfusn_internal_record_t *) *record; |
137 | 892 | *record = NULL; |
138 | | |
139 | 892 | if( internal_record->name != NULL ) |
140 | 228 | { |
141 | 228 | memory_free( |
142 | 228 | internal_record->name ); |
143 | 228 | } |
144 | 892 | memory_free( |
145 | 892 | internal_record ); |
146 | 892 | } |
147 | 892 | return( 1 ); |
148 | 892 | } |
149 | | |
150 | | /* Copies the record from the byte stream |
151 | | * Returns 1 if successful or -1 on error |
152 | | */ |
153 | | int libfusn_record_copy_from_byte_stream( |
154 | | libfusn_record_t *record, |
155 | | const uint8_t *byte_stream, |
156 | | size_t byte_stream_size, |
157 | | libcerror_error_t **error ) |
158 | 892 | { |
159 | 892 | libfusn_internal_record_t *internal_record = NULL; |
160 | 892 | static char *function = "libfusn_record_copy_from_byte_stream"; |
161 | 892 | size_t byte_stream_offset = 0; |
162 | 892 | uint16_t name_offset = 0; |
163 | 892 | uint16_t name_size = 0; |
164 | | |
165 | | #if defined( HAVE_DEBUG_OUTPUT ) |
166 | | uint32_t value_32bit = 0; |
167 | | #endif |
168 | | |
169 | 892 | if( 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 record.", |
176 | 0 | function ); |
177 | |
|
178 | 0 | return( -1 ); |
179 | 0 | } |
180 | 892 | internal_record = (libfusn_internal_record_t *) record; |
181 | | |
182 | 892 | if( internal_record->name != NULL ) |
183 | 0 | { |
184 | 0 | libcerror_error_set( |
185 | 0 | error, |
186 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
187 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
188 | 0 | "%s: invalid record - name value already set.", |
189 | 0 | function ); |
190 | |
|
191 | 0 | return( -1 ); |
192 | 0 | } |
193 | 892 | if( byte_stream == NULL ) |
194 | 0 | { |
195 | 0 | libcerror_error_set( |
196 | 0 | error, |
197 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
198 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
199 | 0 | "%s: invalid byte stream.", |
200 | 0 | function ); |
201 | |
|
202 | 0 | return( -1 ); |
203 | 0 | } |
204 | 892 | if( byte_stream_size > (size_t) SSIZE_MAX ) |
205 | 33 | { |
206 | 33 | libcerror_error_set( |
207 | 33 | error, |
208 | 33 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
209 | 33 | LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, |
210 | 33 | "%s: invalid byte stream size value exceeds maximum.", |
211 | 33 | function ); |
212 | | |
213 | 33 | return( -1 ); |
214 | 33 | } |
215 | 859 | if( byte_stream_size < sizeof( fusn_record_header_t ) ) |
216 | 31 | { |
217 | 31 | libcerror_error_set( |
218 | 31 | error, |
219 | 31 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
220 | 31 | LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, |
221 | 31 | "%s: invalid byte stream value too small.", |
222 | 31 | function ); |
223 | | |
224 | 31 | return( -1 ); |
225 | 31 | } |
226 | | #if defined( HAVE_DEBUG_OUTPUT ) |
227 | | if( libcnotify_verbose != 0 ) |
228 | | { |
229 | | libcnotify_printf( |
230 | | "%s: record header data:\n", |
231 | | function ); |
232 | | libcnotify_print_data( |
233 | | byte_stream, |
234 | | sizeof( fusn_record_header_t ), |
235 | | 0 ); |
236 | | } |
237 | | #endif |
238 | 828 | byte_stream_copy_to_uint32_little_endian( |
239 | 828 | ( (fusn_record_header_t *) byte_stream )->record_size, |
240 | 828 | internal_record->size ); |
241 | | |
242 | 828 | byte_stream_copy_to_uint16_little_endian( |
243 | 828 | ( (fusn_record_header_t *) byte_stream )->major_version, |
244 | 828 | internal_record->major_version ); |
245 | | |
246 | 828 | byte_stream_copy_to_uint16_little_endian( |
247 | 828 | ( (fusn_record_header_t *) byte_stream )->minor_version, |
248 | 828 | internal_record->minor_version ); |
249 | | |
250 | 828 | byte_stream_copy_to_uint64_little_endian( |
251 | 828 | ( (fusn_record_header_t *) byte_stream )->update_time, |
252 | 828 | internal_record->update_time ); |
253 | | |
254 | 828 | byte_stream_copy_to_uint64_little_endian( |
255 | 828 | ( (fusn_record_header_t *) byte_stream )->file_reference, |
256 | 828 | internal_record->file_reference ); |
257 | | |
258 | 828 | byte_stream_copy_to_uint32_little_endian( |
259 | 828 | ( (fusn_record_header_t *) byte_stream )->file_attribute_flags, |
260 | 828 | internal_record->file_attribute_flags ); |
261 | | |
262 | 828 | byte_stream_copy_to_uint64_little_endian( |
263 | 828 | ( (fusn_record_header_t *) byte_stream )->parent_file_reference, |
264 | 828 | internal_record->parent_file_reference ); |
265 | | |
266 | 828 | byte_stream_copy_to_uint64_little_endian( |
267 | 828 | ( (fusn_record_header_t *) byte_stream )->update_sequence_number, |
268 | 828 | internal_record->update_sequence_number ); |
269 | | |
270 | 828 | byte_stream_copy_to_uint32_little_endian( |
271 | 828 | ( (fusn_record_header_t *) byte_stream )->update_reason_flags, |
272 | 828 | internal_record->update_reason_flags ); |
273 | | |
274 | 828 | byte_stream_copy_to_uint32_little_endian( |
275 | 828 | ( (fusn_record_header_t *) byte_stream )->update_source_flags, |
276 | 828 | internal_record->update_source_flags ); |
277 | | |
278 | 828 | byte_stream_copy_to_uint16_little_endian( |
279 | 828 | ( (fusn_record_header_t *) byte_stream )->name_size, |
280 | 828 | name_size ); |
281 | | |
282 | 828 | byte_stream_copy_to_uint16_little_endian( |
283 | 828 | ( (fusn_record_header_t *) byte_stream )->name_offset, |
284 | 828 | name_offset ); |
285 | | |
286 | | #if defined( HAVE_DEBUG_OUTPUT ) |
287 | | if( libcnotify_verbose != 0 ) |
288 | | { |
289 | | libcnotify_printf( |
290 | | "%s: record size\t\t\t: %" PRIu32 "\n", |
291 | | function, |
292 | | internal_record->size ); |
293 | | |
294 | | libcnotify_printf( |
295 | | "%s: major version\t\t\t: %" PRIu16 "\n", |
296 | | function, |
297 | | internal_record->major_version ); |
298 | | |
299 | | libcnotify_printf( |
300 | | "%s: minor version\t\t\t: %" PRIu16 "\n", |
301 | | function, |
302 | | internal_record->minor_version ); |
303 | | |
304 | | libcnotify_printf( |
305 | | "%s: file reference\t\t\t: MFT entry: %" PRIu64 ", sequence: %" PRIu64 "\n", |
306 | | function, |
307 | | internal_record->file_reference & 0xffffffffffffUL, |
308 | | internal_record->file_reference >> 48 ); |
309 | | |
310 | | libcnotify_printf( |
311 | | "%s: parent file reference\t\t: MFT entry: %" PRIu64 ", sequence: %" PRIu64 "\n", |
312 | | function, |
313 | | internal_record->parent_file_reference & 0xffffffffffffUL, |
314 | | internal_record->parent_file_reference >> 48 ); |
315 | | |
316 | | libcnotify_printf( |
317 | | "%s: update sequence number\t\t: 0x%08" PRIx64 "\n", |
318 | | function, |
319 | | internal_record->update_sequence_number ); |
320 | | |
321 | | if( libfusn_debug_print_filetime_value( |
322 | | function, |
323 | | "update time\t\t\t", |
324 | | ( (fusn_record_header_t *) byte_stream )->update_time, |
325 | | 8, |
326 | | LIBFDATETIME_ENDIAN_LITTLE, |
327 | | LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, |
328 | | error ) != 1 ) |
329 | | { |
330 | | libcerror_error_set( |
331 | | error, |
332 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
333 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
334 | | "%s: unable to print FILETIME value.", |
335 | | function ); |
336 | | |
337 | | goto on_error; |
338 | | } |
339 | | libcnotify_printf( |
340 | | "%s: update reason flags\t\t: 0x%08" PRIx32 "\n", |
341 | | function, |
342 | | internal_record->update_reason_flags ); |
343 | | libfusn_debug_print_update_reason_flags( |
344 | | internal_record->update_reason_flags ); |
345 | | libcnotify_printf( |
346 | | "\n" ); |
347 | | |
348 | | libcnotify_printf( |
349 | | "%s: update source flags\t\t: 0x%08" PRIx32 "\n", |
350 | | function, |
351 | | internal_record->update_source_flags ); |
352 | | libfusn_debug_print_update_source_flags( |
353 | | internal_record->update_source_flags ); |
354 | | libcnotify_printf( |
355 | | "\n" ); |
356 | | |
357 | | byte_stream_copy_to_uint32_little_endian( |
358 | | ( (fusn_record_header_t *) byte_stream )->security_identifier_index, |
359 | | value_32bit ); |
360 | | libcnotify_printf( |
361 | | "%s: security identifier index\t\t: %" PRIu32 "\n", |
362 | | function, |
363 | | value_32bit ); |
364 | | |
365 | | libcnotify_printf( |
366 | | "%s: file attribute flags\t\t: 0x%08" PRIx32 "\n", |
367 | | function, |
368 | | internal_record->file_attribute_flags ); |
369 | | libfusn_debug_print_file_attribute_flags( |
370 | | internal_record->file_attribute_flags ); |
371 | | libcnotify_printf( |
372 | | "\n" ); |
373 | | |
374 | | libcnotify_printf( |
375 | | "%s: name size\t\t\t\t: %" PRIu16 "\n", |
376 | | function, |
377 | | name_size ); |
378 | | |
379 | | libcnotify_printf( |
380 | | "%s: name offset\t\t\t: %" PRIu16 "\n", |
381 | | function, |
382 | | name_offset ); |
383 | | } |
384 | | #endif |
385 | 828 | byte_stream_offset = sizeof( fusn_record_header_t ); |
386 | | |
387 | 828 | if( internal_record->major_version != 2 ) |
388 | 61 | { |
389 | 61 | libcerror_error_set( |
390 | 61 | error, |
391 | 61 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
392 | 61 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
393 | 61 | "%s: unsupported major version.", |
394 | 61 | function ); |
395 | | |
396 | 61 | goto on_error; |
397 | 61 | } |
398 | 767 | if( ( (size_t) internal_record->size < sizeof( fusn_record_header_t ) ) |
399 | 767 | || ( (size_t) internal_record->size > byte_stream_size ) ) |
400 | 160 | { |
401 | 160 | libcerror_error_set( |
402 | 160 | error, |
403 | 160 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
404 | 160 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
405 | 160 | "%s: record size value out of bounds.", |
406 | 160 | function ); |
407 | | |
408 | 160 | goto on_error; |
409 | 160 | } |
410 | 607 | if( name_offset > 0 ) |
411 | 343 | { |
412 | 343 | if( ( (size_t) name_offset < sizeof( fusn_record_header_t ) ) |
413 | 343 | || ( (size_t) name_offset > internal_record->size ) ) |
414 | 66 | { |
415 | 66 | libcerror_error_set( |
416 | 66 | error, |
417 | 66 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
418 | 66 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
419 | 66 | "%s: name offset value out of bounds.", |
420 | 66 | function ); |
421 | | |
422 | 66 | goto on_error; |
423 | 66 | } |
424 | 277 | if( (size_t) name_size > ( internal_record->size - name_offset ) ) |
425 | 49 | { |
426 | 49 | libcerror_error_set( |
427 | 49 | error, |
428 | 49 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
429 | 49 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
430 | 49 | "%s: name size value out of bounds.", |
431 | 49 | function ); |
432 | | |
433 | 49 | goto on_error; |
434 | 49 | } |
435 | 228 | if( (size_t) name_offset > byte_stream_offset ) |
436 | 88 | { |
437 | | #if defined( HAVE_DEBUG_OUTPUT ) |
438 | | if( libcnotify_verbose != 0 ) |
439 | | { |
440 | | libcnotify_printf( |
441 | | "%s: record header trailing data:\n", |
442 | | function ); |
443 | | libcnotify_print_data( |
444 | | &( byte_stream[ byte_stream_offset ] ), |
445 | | (size_t) name_offset - byte_stream_offset, |
446 | | 0 ); |
447 | | } |
448 | | #endif |
449 | 88 | byte_stream_offset = (size_t) name_offset; |
450 | 88 | } |
451 | | #if defined( HAVE_DEBUG_OUTPUT ) |
452 | | if( libcnotify_verbose != 0 ) |
453 | | { |
454 | | libcnotify_printf( |
455 | | "%s: name data:\n", |
456 | | function ); |
457 | | libcnotify_print_data( |
458 | | &( byte_stream[ name_offset ] ), |
459 | | (size_t) name_size, |
460 | | 0 ); |
461 | | } |
462 | | #endif |
463 | 228 | internal_record->name = (uint8_t *) memory_allocate( |
464 | 228 | sizeof( uint8_t ) * name_size ); |
465 | | |
466 | 228 | if( internal_record->name == NULL ) |
467 | 0 | { |
468 | 0 | libcerror_error_set( |
469 | 0 | error, |
470 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
471 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
472 | 0 | "%s: unable to create name.", |
473 | 0 | function ); |
474 | |
|
475 | 0 | goto on_error; |
476 | 0 | } |
477 | 228 | internal_record->name_size = name_size; |
478 | | |
479 | 228 | if( memory_copy( |
480 | 228 | internal_record->name, |
481 | 228 | &( byte_stream[ name_offset ] ), |
482 | 228 | name_size ) == NULL ) |
483 | 0 | { |
484 | 0 | libcerror_error_set( |
485 | 0 | error, |
486 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
487 | 0 | LIBCERROR_MEMORY_ERROR_COPY_FAILED, |
488 | 0 | "%s: unable to copy name.", |
489 | 0 | function ); |
490 | |
|
491 | 0 | goto on_error; |
492 | 0 | } |
493 | | #if defined( HAVE_DEBUG_OUTPUT ) |
494 | | if( libcnotify_verbose != 0 ) |
495 | | { |
496 | | if( libfusn_debug_print_utf16_string_value( |
497 | | function, |
498 | | "name\t\t\t\t\t", |
499 | | internal_record->name, |
500 | | internal_record->name_size, |
501 | | LIBUNA_ENDIAN_LITTLE, |
502 | | error ) != 1 ) |
503 | | { |
504 | | libcerror_error_set( |
505 | | error, |
506 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
507 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
508 | | "%s: unable to print UTF-16 string value.", |
509 | | function ); |
510 | | |
511 | | return( -1 ); |
512 | | } |
513 | | } |
514 | | #endif |
515 | 228 | byte_stream_offset += (size_t) name_size; |
516 | 228 | } |
517 | | #if defined( HAVE_DEBUG_OUTPUT ) |
518 | | if( libcnotify_verbose != 0 ) |
519 | | { |
520 | | if( byte_stream_offset < (size_t) internal_record->size ) |
521 | | { |
522 | | libcnotify_printf( |
523 | | "%s: trailing data:\n", |
524 | | function ); |
525 | | libcnotify_print_data( |
526 | | &( byte_stream[ byte_stream_offset ] ), |
527 | | (size_t) internal_record->size - byte_stream_offset, |
528 | | 0 ); |
529 | | } |
530 | | else |
531 | | { |
532 | | libcnotify_printf( |
533 | | "\n" ); |
534 | | } |
535 | | } |
536 | | #endif |
537 | 492 | return( 1 ); |
538 | | |
539 | 336 | on_error: |
540 | 336 | if( internal_record->name != NULL ) |
541 | 0 | { |
542 | 0 | memory_free( |
543 | 0 | internal_record->name ); |
544 | |
|
545 | 0 | internal_record->name = NULL; |
546 | 0 | } |
547 | 336 | internal_record->name_size = 0; |
548 | | |
549 | 336 | return( -1 ); |
550 | 607 | } |
551 | | |
552 | | /* Retrieves the size |
553 | | * Returns 1 if successful or -1 on error |
554 | | */ |
555 | | int libfusn_record_get_size( |
556 | | libfusn_record_t *record, |
557 | | uint32_t *size, |
558 | | libcerror_error_t **error ) |
559 | 479 | { |
560 | 479 | libfusn_internal_record_t *internal_record = NULL; |
561 | 479 | static char *function = "libfusn_record_get_size"; |
562 | | |
563 | 479 | if( record == NULL ) |
564 | 0 | { |
565 | 0 | libcerror_error_set( |
566 | 0 | error, |
567 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
568 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
569 | 0 | "%s: invalid record.", |
570 | 0 | function ); |
571 | |
|
572 | 0 | return( -1 ); |
573 | 0 | } |
574 | 479 | internal_record = (libfusn_internal_record_t *) record; |
575 | | |
576 | 479 | if( size == NULL ) |
577 | 0 | { |
578 | 0 | libcerror_error_set( |
579 | 0 | error, |
580 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
581 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
582 | 0 | "%s: invalid size.", |
583 | 0 | function ); |
584 | |
|
585 | 0 | return( -1 ); |
586 | 0 | } |
587 | 479 | *size = internal_record->size; |
588 | | |
589 | 479 | return( 1 ); |
590 | 479 | } |
591 | | |
592 | | /* Retrieves the update time |
593 | | * Returns 1 if successful or -1 on error |
594 | | */ |
595 | | int libfusn_record_get_update_time( |
596 | | libfusn_record_t *record, |
597 | | uint64_t *update_time, |
598 | | libcerror_error_t **error ) |
599 | 0 | { |
600 | 0 | libfusn_internal_record_t *internal_record = NULL; |
601 | 0 | static char *function = "libfusn_record_get_update_time"; |
602 | |
|
603 | 0 | if( record == NULL ) |
604 | 0 | { |
605 | 0 | libcerror_error_set( |
606 | 0 | error, |
607 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
608 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
609 | 0 | "%s: invalid record.", |
610 | 0 | function ); |
611 | |
|
612 | 0 | return( -1 ); |
613 | 0 | } |
614 | 0 | internal_record = (libfusn_internal_record_t *) record; |
615 | |
|
616 | 0 | if( update_time == NULL ) |
617 | 0 | { |
618 | 0 | libcerror_error_set( |
619 | 0 | error, |
620 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
621 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
622 | 0 | "%s: invalid update time.", |
623 | 0 | function ); |
624 | |
|
625 | 0 | return( -1 ); |
626 | 0 | } |
627 | 0 | *update_time = internal_record->update_time; |
628 | |
|
629 | 0 | return( 1 ); |
630 | 0 | } |
631 | | |
632 | | /* Retrieves the file reference |
633 | | * Returns 1 if successful or -1 on error |
634 | | */ |
635 | | int libfusn_record_get_file_reference( |
636 | | libfusn_record_t *record, |
637 | | uint64_t *file_reference, |
638 | | libcerror_error_t **error ) |
639 | 0 | { |
640 | 0 | libfusn_internal_record_t *internal_record = NULL; |
641 | 0 | static char *function = "libfusn_record_get_file_reference"; |
642 | |
|
643 | 0 | if( record == NULL ) |
644 | 0 | { |
645 | 0 | libcerror_error_set( |
646 | 0 | error, |
647 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
648 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
649 | 0 | "%s: invalid record.", |
650 | 0 | function ); |
651 | |
|
652 | 0 | return( -1 ); |
653 | 0 | } |
654 | 0 | internal_record = (libfusn_internal_record_t *) record; |
655 | |
|
656 | 0 | if( file_reference == NULL ) |
657 | 0 | { |
658 | 0 | libcerror_error_set( |
659 | 0 | error, |
660 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
661 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
662 | 0 | "%s: invalid file reference.", |
663 | 0 | function ); |
664 | |
|
665 | 0 | return( -1 ); |
666 | 0 | } |
667 | 0 | *file_reference = internal_record->file_reference; |
668 | |
|
669 | 0 | return( 1 ); |
670 | 0 | } |
671 | | |
672 | | /* Retrieves the parent file reference |
673 | | * Returns 1 if successful or -1 on error |
674 | | */ |
675 | | int libfusn_record_get_parent_file_reference( |
676 | | libfusn_record_t *record, |
677 | | uint64_t *parent_file_reference, |
678 | | libcerror_error_t **error ) |
679 | 0 | { |
680 | 0 | libfusn_internal_record_t *internal_record = NULL; |
681 | 0 | static char *function = "libfusn_record_get_parent_file_reference"; |
682 | |
|
683 | 0 | if( record == NULL ) |
684 | 0 | { |
685 | 0 | libcerror_error_set( |
686 | 0 | error, |
687 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
688 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
689 | 0 | "%s: invalid record.", |
690 | 0 | function ); |
691 | |
|
692 | 0 | return( -1 ); |
693 | 0 | } |
694 | 0 | internal_record = (libfusn_internal_record_t *) record; |
695 | |
|
696 | 0 | if( parent_file_reference == NULL ) |
697 | 0 | { |
698 | 0 | libcerror_error_set( |
699 | 0 | error, |
700 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
701 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
702 | 0 | "%s: invalid parent file reference.", |
703 | 0 | function ); |
704 | |
|
705 | 0 | return( -1 ); |
706 | 0 | } |
707 | 0 | *parent_file_reference = internal_record->parent_file_reference; |
708 | |
|
709 | 0 | return( 1 ); |
710 | 0 | } |
711 | | |
712 | | /* Retrieves the update sequence number |
713 | | * Returns 1 if successful or -1 on error |
714 | | */ |
715 | | int libfusn_record_get_update_sequence_number( |
716 | | libfusn_record_t *record, |
717 | | uint64_t *update_sequence_number, |
718 | | libcerror_error_t **error ) |
719 | 0 | { |
720 | 0 | libfusn_internal_record_t *internal_record = NULL; |
721 | 0 | static char *function = "libfusn_record_get_update_sequence_number"; |
722 | |
|
723 | 0 | if( record == NULL ) |
724 | 0 | { |
725 | 0 | libcerror_error_set( |
726 | 0 | error, |
727 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
728 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
729 | 0 | "%s: invalid record.", |
730 | 0 | function ); |
731 | |
|
732 | 0 | return( -1 ); |
733 | 0 | } |
734 | 0 | internal_record = (libfusn_internal_record_t *) record; |
735 | |
|
736 | 0 | if( update_sequence_number == NULL ) |
737 | 0 | { |
738 | 0 | libcerror_error_set( |
739 | 0 | error, |
740 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
741 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
742 | 0 | "%s: invalid update sequence number.", |
743 | 0 | function ); |
744 | |
|
745 | 0 | return( -1 ); |
746 | 0 | } |
747 | 0 | *update_sequence_number = internal_record->update_sequence_number; |
748 | |
|
749 | 0 | return( 1 ); |
750 | 0 | } |
751 | | |
752 | | /* Retrieves the update reason flags |
753 | | * Returns 1 if successful or -1 on error |
754 | | */ |
755 | | int libfusn_record_get_update_reason_flags( |
756 | | libfusn_record_t *record, |
757 | | uint32_t *update_reason_flags, |
758 | | libcerror_error_t **error ) |
759 | 0 | { |
760 | 0 | libfusn_internal_record_t *internal_record = NULL; |
761 | 0 | static char *function = "libfusn_record_get_update_reason_flags"; |
762 | |
|
763 | 0 | if( record == NULL ) |
764 | 0 | { |
765 | 0 | libcerror_error_set( |
766 | 0 | error, |
767 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
768 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
769 | 0 | "%s: invalid record.", |
770 | 0 | function ); |
771 | |
|
772 | 0 | return( -1 ); |
773 | 0 | } |
774 | 0 | internal_record = (libfusn_internal_record_t *) record; |
775 | |
|
776 | 0 | if( update_reason_flags == NULL ) |
777 | 0 | { |
778 | 0 | libcerror_error_set( |
779 | 0 | error, |
780 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
781 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
782 | 0 | "%s: invalid update reason flags.", |
783 | 0 | function ); |
784 | |
|
785 | 0 | return( -1 ); |
786 | 0 | } |
787 | 0 | *update_reason_flags = internal_record->update_reason_flags; |
788 | |
|
789 | 0 | return( 1 ); |
790 | 0 | } |
791 | | |
792 | | /* Retrieves the update source flags |
793 | | * Returns 1 if successful or -1 on error |
794 | | */ |
795 | | int libfusn_record_get_update_source_flags( |
796 | | libfusn_record_t *record, |
797 | | uint32_t *update_source_flags, |
798 | | libcerror_error_t **error ) |
799 | 0 | { |
800 | 0 | libfusn_internal_record_t *internal_record = NULL; |
801 | 0 | static char *function = "libfusn_record_get_update_source_flags"; |
802 | |
|
803 | 0 | if( record == NULL ) |
804 | 0 | { |
805 | 0 | libcerror_error_set( |
806 | 0 | error, |
807 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
808 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
809 | 0 | "%s: invalid record.", |
810 | 0 | function ); |
811 | |
|
812 | 0 | return( -1 ); |
813 | 0 | } |
814 | 0 | internal_record = (libfusn_internal_record_t *) record; |
815 | |
|
816 | 0 | if( update_source_flags == NULL ) |
817 | 0 | { |
818 | 0 | libcerror_error_set( |
819 | 0 | error, |
820 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
821 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
822 | 0 | "%s: invalid update source flags.", |
823 | 0 | function ); |
824 | |
|
825 | 0 | return( -1 ); |
826 | 0 | } |
827 | 0 | *update_source_flags = internal_record->update_source_flags; |
828 | |
|
829 | 0 | return( 1 ); |
830 | 0 | } |
831 | | |
832 | | /* Retrieves the file attribute flags |
833 | | * Returns 1 if successful or -1 on error |
834 | | */ |
835 | | int libfusn_record_get_file_attribute_flags( |
836 | | libfusn_record_t *record, |
837 | | uint32_t *file_attribute_flags, |
838 | | libcerror_error_t **error ) |
839 | 0 | { |
840 | 0 | libfusn_internal_record_t *internal_record = NULL; |
841 | 0 | static char *function = "libfusn_record_get_file_attribute_flags"; |
842 | |
|
843 | 0 | if( record == NULL ) |
844 | 0 | { |
845 | 0 | libcerror_error_set( |
846 | 0 | error, |
847 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
848 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
849 | 0 | "%s: invalid record.", |
850 | 0 | function ); |
851 | |
|
852 | 0 | return( -1 ); |
853 | 0 | } |
854 | 0 | internal_record = (libfusn_internal_record_t *) record; |
855 | |
|
856 | 0 | if( file_attribute_flags == NULL ) |
857 | 0 | { |
858 | 0 | libcerror_error_set( |
859 | 0 | error, |
860 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
861 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
862 | 0 | "%s: invalid file attribute flags.", |
863 | 0 | function ); |
864 | |
|
865 | 0 | return( -1 ); |
866 | 0 | } |
867 | 0 | *file_attribute_flags = internal_record->file_attribute_flags; |
868 | |
|
869 | 0 | return( 1 ); |
870 | 0 | } |
871 | | |
872 | | /* Retrieves the size of the UTF-8 encoded name |
873 | | * The returned size includes the end of string character |
874 | | * Returns 1 if successful or -1 on error |
875 | | */ |
876 | | int libfusn_record_get_utf8_name_size( |
877 | | libfusn_record_t *record, |
878 | | size_t *utf8_string_size, |
879 | | libcerror_error_t **error ) |
880 | 0 | { |
881 | 0 | libfusn_internal_record_t *internal_record = NULL; |
882 | 0 | static char *function = "libfusn_record_get_utf8_name_size"; |
883 | |
|
884 | 0 | if( record == NULL ) |
885 | 0 | { |
886 | 0 | libcerror_error_set( |
887 | 0 | error, |
888 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
889 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
890 | 0 | "%s: invalid record.", |
891 | 0 | function ); |
892 | |
|
893 | 0 | return( -1 ); |
894 | 0 | } |
895 | 0 | internal_record = (libfusn_internal_record_t *) record; |
896 | |
|
897 | 0 | if( ( internal_record->name == NULL ) |
898 | 0 | || ( internal_record->name_size == 0 ) ) |
899 | 0 | { |
900 | 0 | if( utf8_string_size == NULL ) |
901 | 0 | { |
902 | 0 | libcerror_error_set( |
903 | 0 | error, |
904 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
905 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
906 | 0 | "%s: invalid UTF-8 string size.", |
907 | 0 | function ); |
908 | |
|
909 | 0 | return( -1 ); |
910 | 0 | } |
911 | 0 | *utf8_string_size = 0; |
912 | 0 | } |
913 | 0 | else |
914 | 0 | { |
915 | 0 | if( libuna_utf8_string_size_from_utf16_stream( |
916 | 0 | internal_record->name, |
917 | 0 | (size_t) internal_record->name_size, |
918 | 0 | LIBUNA_ENDIAN_LITTLE, |
919 | 0 | utf8_string_size, |
920 | 0 | error ) != 1 ) |
921 | 0 | { |
922 | 0 | libcerror_error_set( |
923 | 0 | error, |
924 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
925 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
926 | 0 | "%s: unable to retrieve UTF-8 string size.", |
927 | 0 | function ); |
928 | |
|
929 | 0 | return( -1 ); |
930 | 0 | } |
931 | 0 | } |
932 | 0 | return( 1 ); |
933 | 0 | } |
934 | | |
935 | | /* Retrieves the UTF-8 encoded name |
936 | | * The size should include the end of string character |
937 | | * Returns 1 if successful or -1 on error |
938 | | */ |
939 | | int libfusn_record_get_utf8_name( |
940 | | libfusn_record_t *record, |
941 | | uint8_t *utf8_string, |
942 | | size_t utf8_string_size, |
943 | | libcerror_error_t **error ) |
944 | 0 | { |
945 | 0 | libfusn_internal_record_t *internal_record = NULL; |
946 | 0 | static char *function = "libfusn_record_get_utf8_name"; |
947 | |
|
948 | 0 | if( record == NULL ) |
949 | 0 | { |
950 | 0 | libcerror_error_set( |
951 | 0 | error, |
952 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
953 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
954 | 0 | "%s: invalid record.", |
955 | 0 | function ); |
956 | |
|
957 | 0 | return( -1 ); |
958 | 0 | } |
959 | 0 | internal_record = (libfusn_internal_record_t *) record; |
960 | |
|
961 | 0 | if( internal_record->name == NULL ) |
962 | 0 | { |
963 | 0 | libcerror_error_set( |
964 | 0 | error, |
965 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
966 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
967 | 0 | "%s: invalid record - missing name.", |
968 | 0 | function ); |
969 | |
|
970 | 0 | return( -1 ); |
971 | 0 | } |
972 | 0 | if( libuna_utf8_string_copy_from_utf16_stream( |
973 | 0 | utf8_string, |
974 | 0 | utf8_string_size, |
975 | 0 | internal_record->name, |
976 | 0 | (size_t) internal_record->name_size, |
977 | 0 | LIBUNA_ENDIAN_LITTLE, |
978 | 0 | error ) != 1 ) |
979 | 0 | { |
980 | 0 | libcerror_error_set( |
981 | 0 | error, |
982 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
983 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
984 | 0 | "%s: unable to retrieve UTF-8 string.", |
985 | 0 | function ); |
986 | |
|
987 | 0 | return( -1 ); |
988 | 0 | } |
989 | 0 | return( 1 ); |
990 | 0 | } |
991 | | |
992 | | /* Retrieves the size of the UTF-16 encoded name |
993 | | * The returned size includes the end of string character |
994 | | * Returns 1 if successful or -1 on error |
995 | | */ |
996 | | int libfusn_record_get_utf16_name_size( |
997 | | libfusn_record_t *record, |
998 | | size_t *utf16_string_size, |
999 | | libcerror_error_t **error ) |
1000 | 0 | { |
1001 | 0 | libfusn_internal_record_t *internal_record = NULL; |
1002 | 0 | static char *function = "libfusn_record_get_utf16_name_size"; |
1003 | |
|
1004 | 0 | if( record == NULL ) |
1005 | 0 | { |
1006 | 0 | libcerror_error_set( |
1007 | 0 | error, |
1008 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1009 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1010 | 0 | "%s: invalid record.", |
1011 | 0 | function ); |
1012 | |
|
1013 | 0 | return( -1 ); |
1014 | 0 | } |
1015 | 0 | internal_record = (libfusn_internal_record_t *) record; |
1016 | |
|
1017 | 0 | if( ( internal_record->name == NULL ) |
1018 | 0 | || ( internal_record->name_size == 0 ) ) |
1019 | 0 | { |
1020 | 0 | if( utf16_string_size == NULL ) |
1021 | 0 | { |
1022 | 0 | libcerror_error_set( |
1023 | 0 | error, |
1024 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1025 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1026 | 0 | "%s: invalid UTF-16 string size.", |
1027 | 0 | function ); |
1028 | |
|
1029 | 0 | return( -1 ); |
1030 | 0 | } |
1031 | 0 | *utf16_string_size = 0; |
1032 | 0 | } |
1033 | 0 | else |
1034 | 0 | { |
1035 | 0 | if( libuna_utf16_string_size_from_utf16_stream( |
1036 | 0 | internal_record->name, |
1037 | 0 | (size_t) internal_record->name_size, |
1038 | 0 | LIBUNA_ENDIAN_LITTLE, |
1039 | 0 | utf16_string_size, |
1040 | 0 | error ) != 1 ) |
1041 | 0 | { |
1042 | 0 | libcerror_error_set( |
1043 | 0 | error, |
1044 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1045 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1046 | 0 | "%s: unable to retrieve UTF-16 string size.", |
1047 | 0 | function ); |
1048 | |
|
1049 | 0 | return( -1 ); |
1050 | 0 | } |
1051 | 0 | } |
1052 | 0 | return( 1 ); |
1053 | 0 | } |
1054 | | |
1055 | | /* Retrieves the UTF-16 encoded name |
1056 | | * The size should include the end of string character |
1057 | | * Returns 1 if successful or -1 on error |
1058 | | */ |
1059 | | int libfusn_record_get_utf16_name( |
1060 | | libfusn_record_t *record, |
1061 | | uint16_t *utf16_string, |
1062 | | size_t utf16_string_size, |
1063 | | libcerror_error_t **error ) |
1064 | 0 | { |
1065 | 0 | libfusn_internal_record_t *internal_record = NULL; |
1066 | 0 | static char *function = "libfusn_record_get_utf16_name"; |
1067 | |
|
1068 | 0 | if( record == NULL ) |
1069 | 0 | { |
1070 | 0 | libcerror_error_set( |
1071 | 0 | error, |
1072 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1073 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1074 | 0 | "%s: invalid record.", |
1075 | 0 | function ); |
1076 | |
|
1077 | 0 | return( -1 ); |
1078 | 0 | } |
1079 | 0 | internal_record = (libfusn_internal_record_t *) record; |
1080 | |
|
1081 | 0 | if( internal_record->name == NULL ) |
1082 | 0 | { |
1083 | 0 | libcerror_error_set( |
1084 | 0 | error, |
1085 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1086 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
1087 | 0 | "%s: invalid record - missing name.", |
1088 | 0 | function ); |
1089 | |
|
1090 | 0 | return( -1 ); |
1091 | 0 | } |
1092 | 0 | if( libuna_utf16_string_copy_from_utf16_stream( |
1093 | 0 | utf16_string, |
1094 | 0 | utf16_string_size, |
1095 | 0 | internal_record->name, |
1096 | 0 | (size_t) internal_record->name_size, |
1097 | 0 | LIBUNA_ENDIAN_LITTLE, |
1098 | 0 | error ) != 1 ) |
1099 | 0 | { |
1100 | 0 | libcerror_error_set( |
1101 | 0 | error, |
1102 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1103 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1104 | 0 | "%s: unable to retrieve UTF-16 string.", |
1105 | 0 | function ); |
1106 | |
|
1107 | 0 | return( -1 ); |
1108 | 0 | } |
1109 | 0 | return( 1 ); |
1110 | 0 | } |
1111 | | |