1 /*
2 * Debug functions
3 *
4 * Copyright (C) 2020-2021, 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 <memory.h>
24 #include <narrow_string.h>
25 #include <system_string.h>
26 #include <types.h>
27 #include <wide_string.h>
28
29 #include "libfsxfs_debug.h"
30 #include "libfsxfs_definitions.h"
31 #include "libfsxfs_libbfio.h"
32 #include "libfsxfs_libcerror.h"
33 #include "libfsxfs_libcnotify.h"
34 #include "libfsxfs_libfdatetime.h"
35 #include "libfsxfs_libfguid.h"
36 #include "libfsxfs_libuna.h"
37
38 #if defined( HAVE_DEBUG_OUTPUT )
39
40 /* Prints the feature flags
41 */
libfsxfs_debug_print_feature_flags(uint16_t feature_flags)42 void libfsxfs_debug_print_feature_flags(
43 uint16_t feature_flags )
44 {
45 if( ( feature_flags & 0x0010 ) != 0 )
46 {
47 libcnotify_printf(
48 "\t(XFS_SB_VERSION_ATTRBIT)\n" );
49 }
50 if( ( feature_flags & 0x0020 ) != 0 )
51 {
52 libcnotify_printf(
53 "\t(XFS_SB_VERSION_NLINKBIT)\n" );
54 }
55 if( ( feature_flags & 0x0040 ) != 0 )
56 {
57 libcnotify_printf(
58 "\t(XFS_SB_VERSION_QUOTABIT)\n" );
59 }
60 if( ( feature_flags & 0x0080 ) != 0 )
61 {
62 libcnotify_printf(
63 "\t(XFS_SB_VERSION_ALIGNBIT)\n" );
64 }
65 if( ( feature_flags & 0x0100 ) != 0 )
66 {
67 libcnotify_printf(
68 "\t(XFS_SB_VERSION_DALIGNBIT)\n" );
69 }
70 if( ( feature_flags & 0x0200 ) != 0 )
71 {
72 libcnotify_printf(
73 "\t(XFS_SB_VERSION_SHAREDBIT)\n" );
74 }
75 if( ( feature_flags & 0x0400 ) != 0 )
76 {
77 libcnotify_printf(
78 "\t(XFS_SB_VERSION_LOGV2BIT)\n" );
79 }
80 if( ( feature_flags & 0x0800 ) != 0 )
81 {
82 libcnotify_printf(
83 "\t(XFS_SB_VERSION_SECTORBIT)\n" );
84 }
85 if( ( feature_flags & 0x1000 ) != 0 )
86 {
87 libcnotify_printf(
88 "\t(XFS_SB_VERSION_EXTFLGBIT)\n" );
89 }
90 if( ( feature_flags & 0x2000 ) != 0 )
91 {
92 libcnotify_printf(
93 "\t(XFS_SB_VERSION_DIRV2BIT)\n" );
94 }
95 if( ( feature_flags & 0x4000 ) != 0 )
96 {
97 libcnotify_printf(
98 "\t(XFS_SB_VERSION_BORGBIT)\n" );
99 }
100 if( ( feature_flags & 0x8000 ) != 0 )
101 {
102 libcnotify_printf(
103 "\t(XFS_SB_VERSION_MOREBITSBIT)\n" );
104 }
105 }
106
107 /* Prints the secondary feature flags
108 */
libfsxfs_debug_print_secondary_feature_flags(uint32_t secondary_feature_flags)109 void libfsxfs_debug_print_secondary_feature_flags(
110 uint32_t secondary_feature_flags )
111 {
112 if( ( secondary_feature_flags & 0x00000001UL ) != 0 )
113 {
114 libcnotify_printf(
115 "\t(XFS_SB_VERSION2_RESERVED1BIT)\n" );
116 }
117 if( ( secondary_feature_flags & 0x00000002UL ) != 0 )
118 {
119 libcnotify_printf(
120 "\t(XFS_SB_VERSION2_LAZYSBCOUNTBIT)\n" );
121 }
122 if( ( secondary_feature_flags & 0x00000004UL ) != 0 )
123 {
124 libcnotify_printf(
125 "\t(XFS_SB_VERSION2_RESERVED4BIT)\n" );
126 }
127 if( ( secondary_feature_flags & 0x00000008UL ) != 0 )
128 {
129 libcnotify_printf(
130 "\t(XFS_SB_VERSION2_ATTR2BIT)\n" );
131 }
132 if( ( secondary_feature_flags & 0x00000010UL ) != 0 )
133 {
134 libcnotify_printf(
135 "\t(XFS_SB_VERSION2_PARENTBIT)\n" );
136 }
137
138 if( ( secondary_feature_flags & 0x00000080UL ) != 0 )
139 {
140 libcnotify_printf(
141 "\t(XFS_SB_VERSION2_PROJID32BIT)\n" );
142 }
143 if( ( secondary_feature_flags & 0x00000100UL ) != 0 )
144 {
145 libcnotify_printf(
146 "\t(XFS_SB_VERSION2_CRCBIT)\n" );
147 }
148 if( ( secondary_feature_flags & 0x00000200UL ) != 0 )
149 {
150 libcnotify_printf(
151 "\t(XFS_SB_VERSION2_FTYPE)\n" );
152 }
153 }
154
155 /* Prints the file mode
156 */
libfsxfs_debug_print_file_mode(uint16_t file_mode)157 void libfsxfs_debug_print_file_mode(
158 uint16_t file_mode )
159 {
160 if( ( file_mode & 0x0007 ) != 0 )
161 {
162 libcnotify_printf(
163 "\tAccess other: " );
164
165 if( ( file_mode & 0x0004 ) != 0 )
166 {
167 libcnotify_printf(
168 "R" );
169 }
170 if( ( file_mode & 0x0002 ) != 0 )
171 {
172 libcnotify_printf(
173 "W" );
174 }
175 if( ( file_mode & 0x0001 ) != 0 )
176 {
177 libcnotify_printf(
178 "X" );
179 }
180 libcnotify_printf(
181 "\n" );
182 }
183 if( ( file_mode & 0x0038 ) != 0 )
184 {
185 libcnotify_printf(
186 "\tAccess group: " );
187
188 if( ( file_mode & 0x0020 ) != 0 )
189 {
190 libcnotify_printf(
191 "R" );
192 }
193 if( ( file_mode & 0x0010 ) != 0 )
194 {
195 libcnotify_printf(
196 "W" );
197 }
198 if( ( file_mode & 0x0008 ) != 0 )
199 {
200 libcnotify_printf(
201 "X" );
202 }
203 libcnotify_printf(
204 "\n" );
205 }
206 if( ( file_mode & 0x01c0 ) != 0 )
207 {
208 libcnotify_printf(
209 "\tAccess user: " );
210
211 if( ( file_mode & 0x0100 ) != 0 )
212 {
213 libcnotify_printf(
214 "R" );
215 }
216 if( ( file_mode & 0x0080 ) != 0 )
217 {
218 libcnotify_printf(
219 "W" );
220 }
221 if( ( file_mode & 0x0040 ) != 0 )
222 {
223 libcnotify_printf(
224 "X" );
225 }
226 libcnotify_printf(
227 "\n" );
228 }
229 if( ( file_mode & 0x0200 ) != 0 )
230 {
231 libcnotify_printf(
232 "\tSticky bit (S_ISTXT)" );
233 }
234 if( ( file_mode & 0x0400 ) != 0 )
235 {
236 libcnotify_printf(
237 "\tSet group identifer (GID) on execution (S_ISGID)\n" );
238 }
239 if( ( file_mode & 0x0800 ) != 0 )
240 {
241 libcnotify_printf(
242 "\tSet user identifer (UID) on execution (S_ISUID)\n" );
243 }
244 switch( file_mode & 0xf000 )
245 {
246 case 0x1000:
247 libcnotify_printf(
248 "\tNamed pipe (FIFO) (S_IFIFO)\n" );
249 break;
250
251 case 0x2000:
252 libcnotify_printf(
253 "\tCharacter device (S_IFCHR)\n" );
254 break;
255
256 case 0x4000:
257 libcnotify_printf(
258 "\tDirectory (S_IFDIR)\n" );
259 break;
260
261 case 0x6000:
262 libcnotify_printf(
263 "\tBlock device (S_IFBLK)\n" );
264 break;
265
266 case 0x8000:
267 libcnotify_printf(
268 "\tRegular file (S_IFREG)\n" );
269 break;
270
271 case 0xa000:
272 libcnotify_printf(
273 "\tSymbolic link (S_IFLNK)\n" );
274 break;
275
276 case 0xc000:
277 libcnotify_printf(
278 "\tSocket (S_IFSOCK)\n" );
279 break;
280
281 default:
282 break;
283 }
284 libcnotify_printf(
285 "\n" );
286 }
287
288 /* Prints the fork type
289 */
libfsxfs_debug_print_fork_type(uint8_t fork_type)290 const char *libfsxfs_debug_print_fork_type(
291 uint8_t fork_type )
292 {
293 switch( fork_type )
294 {
295 case 0:
296 return( "XFS_DINODE_FMT_DEV" );
297
298 case 1:
299 return( "XFS_DINODE_FMT_LOCAL" );
300
301 case 2:
302 return( "XFS_DINODE_FMT_EXTENTS" );
303
304 case 3:
305 return( "XFS_DINODE_FMT_BTREE" );
306
307 case 4:
308 return( "XFS_DINODE_FMT_UUID" );
309
310 case 5:
311 return( "XFS_DINODE_FMT_RMAP" );
312 }
313 return( "Unknown" );
314 }
315
316 /* Prints a POSIX value
317 * Returns 1 if successful or -1 on error
318 */
libfsxfs_debug_print_posix_time_value(const char * function_name,const char * value_name,const uint8_t * byte_stream,size_t byte_stream_size,int byte_order,uint8_t value_type,uint32_t string_format_flags,libcerror_error_t ** error)319 int libfsxfs_debug_print_posix_time_value(
320 const char *function_name,
321 const char *value_name,
322 const uint8_t *byte_stream,
323 size_t byte_stream_size,
324 int byte_order,
325 uint8_t value_type,
326 uint32_t string_format_flags,
327 libcerror_error_t **error )
328 {
329 char date_time_string[ 32 ];
330
331 libfdatetime_posix_time_t *posix_time = NULL;
332 static char *function = "libfsxfs_debug_print_posix_time_value";
333
334 if( libfdatetime_posix_time_initialize(
335 &posix_time,
336 error ) != 1 )
337 {
338 libcerror_error_set(
339 error,
340 LIBCERROR_ERROR_DOMAIN_RUNTIME,
341 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
342 "%s: unable to create posix time.",
343 function );
344
345 goto on_error;
346 }
347 if( libfdatetime_posix_time_copy_from_byte_stream(
348 posix_time,
349 byte_stream,
350 byte_stream_size,
351 byte_order,
352 value_type,
353 error ) != 1 )
354 {
355 libcerror_error_set(
356 error,
357 LIBCERROR_ERROR_DOMAIN_RUNTIME,
358 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
359 "%s: unable to copy byte stream to posix time.",
360 function );
361
362 goto on_error;
363 }
364 if( libfdatetime_posix_time_copy_to_utf8_string(
365 posix_time,
366 (uint8_t *) date_time_string,
367 32,
368 string_format_flags,
369 error ) != 1 )
370 {
371 libcerror_error_set(
372 error,
373 LIBCERROR_ERROR_DOMAIN_RUNTIME,
374 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
375 "%s: unable to copy posix_time to string.",
376 function );
377
378 goto on_error;
379 }
380 libcnotify_printf(
381 "%s: %s: %s UTC\n",
382 function_name,
383 value_name,
384 date_time_string );
385
386 if( libfdatetime_posix_time_free(
387 &posix_time,
388 error ) != 1 )
389 {
390 libcerror_error_set(
391 error,
392 LIBCERROR_ERROR_DOMAIN_RUNTIME,
393 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
394 "%s: unable to free posix time.",
395 function );
396
397 goto on_error;
398 }
399 return( 1 );
400
401 on_error:
402 if( posix_time != NULL )
403 {
404 libfdatetime_posix_time_free(
405 &posix_time,
406 NULL );
407 }
408 return( -1 );
409 }
410
411 /* Prints a GUID/UUID value
412 * Returns 1 if successful or -1 on error
413 */
libfsxfs_debug_print_guid_value(const char * function_name,const char * value_name,const uint8_t * byte_stream,size_t byte_stream_size,int byte_order,uint32_t string_format_flags,libcerror_error_t ** error)414 int libfsxfs_debug_print_guid_value(
415 const char *function_name,
416 const char *value_name,
417 const uint8_t *byte_stream,
418 size_t byte_stream_size,
419 int byte_order,
420 uint32_t string_format_flags,
421 libcerror_error_t **error )
422 {
423 system_character_t guid_string[ 48 ];
424
425 libfguid_identifier_t *guid = NULL;
426 static char *function = "libfsxfs_debug_print_guid_value";
427
428 if( libfguid_identifier_initialize(
429 &guid,
430 error ) != 1 )
431 {
432 libcerror_error_set(
433 error,
434 LIBCERROR_ERROR_DOMAIN_RUNTIME,
435 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
436 "%s: unable to create GUID.",
437 function );
438
439 goto on_error;
440 }
441 if( libfguid_identifier_copy_from_byte_stream(
442 guid,
443 byte_stream,
444 byte_stream_size,
445 byte_order,
446 error ) != 1 )
447 {
448 libcerror_error_set(
449 error,
450 LIBCERROR_ERROR_DOMAIN_RUNTIME,
451 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
452 "%s: unable to copy byte stream to GUID.",
453 function );
454
455 goto on_error;
456 }
457 if( libfguid_identifier_copy_to_utf8_string(
458 guid,
459 (uint8_t *) guid_string,
460 48,
461 string_format_flags,
462 error ) != 1 )
463 {
464 libcerror_error_set(
465 error,
466 LIBCERROR_ERROR_DOMAIN_RUNTIME,
467 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
468 "%s: unable to copy GUID to string.",
469 function );
470
471 goto on_error;
472 }
473 libcnotify_printf(
474 "%s: %s: %s\n",
475 function_name,
476 value_name,
477 guid_string );
478
479 if( libfguid_identifier_free(
480 &guid,
481 error ) != 1 )
482 {
483 libcerror_error_set(
484 error,
485 LIBCERROR_ERROR_DOMAIN_RUNTIME,
486 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
487 "%s: unable to free GUID.",
488 function );
489
490 goto on_error;
491 }
492 return( 1 );
493
494 on_error:
495 if( guid != NULL )
496 {
497 libfguid_identifier_free(
498 &guid,
499 NULL );
500 }
501 return( -1 );
502 }
503
504 /* Prints an UTF-8 string value
505 * Returns 1 if successful or -1 on error
506 */
libfsxfs_debug_print_utf8_string_value(const char * function_name,const char * value_name,const uint8_t * byte_stream,size_t byte_stream_size,libcerror_error_t ** error)507 int libfsxfs_debug_print_utf8_string_value(
508 const char *function_name,
509 const char *value_name,
510 const uint8_t *byte_stream,
511 size_t byte_stream_size,
512 libcerror_error_t **error )
513 {
514 system_character_t *string = NULL;
515 static char *function = "libfsxfs_debug_print_utf8_string_value";
516 size_t string_size = 0;
517 int result = 0;
518
519 if( ( byte_stream == NULL )
520 || ( byte_stream_size == 0 ) )
521 {
522 libcnotify_printf(
523 "%s: %s: \n",
524 function_name,
525 value_name );
526
527 return( 1 );
528 }
529 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
530 result = libuna_utf16_string_size_from_utf8_stream(
531 byte_stream,
532 byte_stream_size,
533 &string_size,
534 error );
535 #else
536 result = libuna_utf8_string_size_from_utf8_stream(
537 byte_stream,
538 byte_stream_size,
539 &string_size,
540 error );
541 #endif
542 if( result != 1 )
543 {
544 libcerror_error_set(
545 error,
546 LIBCERROR_ERROR_DOMAIN_RUNTIME,
547 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
548 "%s: unable to determine size of string.",
549 function );
550
551 goto on_error;
552 }
553 if( string_size > (size_t) ( SSIZE_MAX / sizeof( system_character_t ) ) )
554 {
555 libcerror_error_set(
556 error,
557 LIBCERROR_ERROR_DOMAIN_RUNTIME,
558 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
559 "%s: invalid string size value exceeds maximum.",
560 function );
561
562 goto on_error;
563 }
564 string = system_string_allocate(
565 string_size );
566
567 if( string == NULL )
568 {
569 libcerror_error_set(
570 error,
571 LIBCERROR_ERROR_DOMAIN_MEMORY,
572 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
573 "%s: unable to create string.",
574 function );
575
576 goto on_error;
577 }
578 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
579 result = libuna_utf16_string_copy_from_utf8_stream(
580 (libuna_utf16_character_t *) string,
581 string_size,
582 byte_stream,
583 byte_stream_size,
584 error );
585 #else
586 result = libuna_utf8_string_copy_from_utf8_stream(
587 (libuna_utf8_character_t *) string,
588 string_size,
589 byte_stream,
590 byte_stream_size,
591 error );
592 #endif
593 if( result != 1 )
594 {
595 libcerror_error_set(
596 error,
597 LIBCERROR_ERROR_DOMAIN_RUNTIME,
598 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
599 "%s: unable to set string.",
600 function );
601
602 goto on_error;
603 }
604 libcnotify_printf(
605 "%s: %s: %" PRIs_SYSTEM "\n",
606 function_name,
607 value_name,
608 string );
609
610 memory_free(
611 string );
612
613 return( 1 );
614
615 on_error:
616 if( string != NULL )
617 {
618 memory_free(
619 string );
620 }
621 return( -1 );
622 }
623
624 /* Prints the read offsets
625 * Returns 1 if successful or -1 on error
626 */
libfsxfs_debug_print_read_offsets(libbfio_handle_t * file_io_handle,libcerror_error_t ** error)627 int libfsxfs_debug_print_read_offsets(
628 libbfio_handle_t *file_io_handle,
629 libcerror_error_t **error )
630 {
631 static char *function = "libfsxfs_debug_print_read_offsets";
632 off64_t offset = 0;
633 size64_t size = 0;
634 int number_of_offsets = 0;
635 int offset_iterator = 0;
636
637 if( file_io_handle == NULL )
638 {
639 libcerror_error_set(
640 error,
641 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
642 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
643 "%s: invalid file IO handle.",
644 function );
645
646 return( -1 );
647 }
648 if( libbfio_handle_get_number_of_offsets_read(
649 file_io_handle,
650 &number_of_offsets,
651 error ) != 1 )
652 {
653 libcerror_error_set(
654 error,
655 LIBCERROR_ERROR_DOMAIN_RUNTIME,
656 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
657 "%s: unable to retrieve number of offsets read.",
658 function );
659
660 return( -1 );
661 }
662 libcnotify_printf(
663 "Offsets read:\n" );
664
665 for( offset_iterator = 0;
666 offset_iterator < number_of_offsets;
667 offset_iterator++ )
668 {
669 if( libbfio_handle_get_offset_read(
670 file_io_handle,
671 offset_iterator,
672 &offset,
673 &size,
674 error ) != 1 )
675 {
676 libcerror_error_set(
677 error,
678 LIBCERROR_ERROR_DOMAIN_RUNTIME,
679 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
680 "%s: unable to retrieve offset: %d.",
681 function,
682 ( offset_iterator + 1 ) );
683
684 return( -1 );
685 }
686 libcnotify_printf(
687 "%08" PRIi64 " ( 0x%08" PRIx64 " ) - %08" PRIi64 " ( 0x%08" PRIx64 " ) size: %" PRIu64 "\n",
688 offset,
689 offset,
690 offset + (off64_t) size,
691 offset + (off64_t) size,
692 size );
693 }
694 libcnotify_printf(
695 "\n" );
696
697 return( 1 );
698 }
699
700 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
701
702