Repository: libyal/libfsntfs Branch: main Commit: 6dff0233f983 Files: 602 Total size: 6.4 MB Directory structure: gitextract_g0xxxb8w/ ├── .codecov.yml ├── .github/ │ └── workflows/ │ ├── build.yml │ ├── build_freebsd.yml │ ├── build_macos.yml │ ├── build_ossfuzz.yml │ ├── build_shared.yml │ └── build_wheel.yml ├── .gitignore ├── AUTHORS ├── COPYING ├── COPYING.LESSER ├── ChangeLog ├── Makefile.am ├── NEWS ├── README ├── acinclude.m4 ├── appveyor.yml ├── autogen.ps1 ├── autogen.sh ├── build.ps1 ├── builddokan.ps1 ├── common/ │ ├── Makefile.am │ ├── byte_stream.h │ ├── common.h │ ├── config_borlandc.h │ ├── config_msc.h │ ├── config_winapi.h │ ├── file_stream.h │ ├── memory.h │ ├── narrow_string.h │ ├── system_string.h │ ├── types.h.in │ └── wide_string.h ├── configure.ac ├── documentation/ │ └── New Technologies File System (NTFS).asciidoc ├── dpkg/ │ ├── changelog.in │ ├── compat │ ├── control │ ├── copyright │ ├── libfsntfs-dev.install │ ├── libfsntfs-python3.install │ ├── libfsntfs-tools.install │ ├── libfsntfs.install │ ├── rules │ └── source/ │ └── format ├── fsntfstools/ │ ├── Makefile.am │ ├── bodyfile.c │ ├── bodyfile.h │ ├── digest_hash.c │ ├── digest_hash.h │ ├── fsntfsinfo.c │ ├── fsntfsmount.c │ ├── fsntfstools_getopt.c │ ├── fsntfstools_getopt.h │ ├── fsntfstools_i18n.h │ ├── fsntfstools_libbfio.h │ ├── fsntfstools_libcerror.h │ ├── fsntfstools_libclocale.h │ ├── fsntfstools_libcnotify.h │ ├── fsntfstools_libcpath.h │ ├── fsntfstools_libfcache.h │ ├── fsntfstools_libfdata.h │ ├── fsntfstools_libfdatetime.h │ ├── fsntfstools_libfguid.h │ ├── fsntfstools_libfsntfs.h │ ├── fsntfstools_libfusn.h │ ├── fsntfstools_libfwnt.h │ ├── fsntfstools_libhmac.h │ ├── fsntfstools_libuna.h │ ├── fsntfstools_output.c │ ├── fsntfstools_output.h │ ├── fsntfstools_signal.c │ ├── fsntfstools_signal.h │ ├── fsntfstools_unused.h │ ├── info_handle.c │ ├── info_handle.h │ ├── mount_dokan.c │ ├── mount_dokan.h │ ├── mount_file_entry.c │ ├── mount_file_entry.h │ ├── mount_file_system.c │ ├── mount_file_system.h │ ├── mount_fuse.c │ ├── mount_fuse.h │ ├── mount_handle.c │ ├── mount_handle.h │ ├── mount_path_string.c │ ├── mount_path_string.h │ ├── path_string.c │ └── path_string.h ├── include/ │ ├── Makefile.am │ ├── libfsntfs/ │ │ ├── codepage.h │ │ ├── definitions.h.in │ │ ├── error.h │ │ ├── extern.h │ │ ├── features.h.in │ │ └── types.h.in │ └── libfsntfs.h.in ├── libfsntfs/ │ ├── Makefile.am │ ├── fsntfs_file_name.h │ ├── fsntfs_index.h │ ├── fsntfs_logged_utility_stream.h │ ├── fsntfs_mft_attribute.h │ ├── fsntfs_mft_attribute_list.h │ ├── fsntfs_mft_entry.h │ ├── fsntfs_object_identifier.h │ ├── fsntfs_reparse_point.h │ ├── fsntfs_secure.h │ ├── fsntfs_standard_information.h │ ├── fsntfs_txf_data.h │ ├── fsntfs_volume_header.h │ ├── fsntfs_volume_information.h │ ├── libfsntfs.c │ ├── libfsntfs.rc.in │ ├── libfsntfs_attribute.c │ ├── libfsntfs_attribute.h │ ├── libfsntfs_attribute_list_attribute.c │ ├── libfsntfs_attribute_list_attribute.h │ ├── libfsntfs_attribute_list_entry.c │ ├── libfsntfs_attribute_list_entry.h │ ├── libfsntfs_bitmap_values.c │ ├── libfsntfs_bitmap_values.h │ ├── libfsntfs_buffer_data_handle.c │ ├── libfsntfs_buffer_data_handle.h │ ├── libfsntfs_cluster_block.c │ ├── libfsntfs_cluster_block.h │ ├── libfsntfs_cluster_block_data.c │ ├── libfsntfs_cluster_block_data.h │ ├── libfsntfs_cluster_block_stream.c │ ├── libfsntfs_cluster_block_stream.h │ ├── libfsntfs_cluster_block_vector.c │ ├── libfsntfs_cluster_block_vector.h │ ├── libfsntfs_compressed_block.c │ ├── libfsntfs_compressed_block.h │ ├── libfsntfs_compressed_block_data_handle.c │ ├── libfsntfs_compressed_block_data_handle.h │ ├── libfsntfs_compressed_block_vector.c │ ├── libfsntfs_compressed_block_vector.h │ ├── libfsntfs_compressed_data_handle.c │ ├── libfsntfs_compressed_data_handle.h │ ├── libfsntfs_compression.c │ ├── libfsntfs_compression.h │ ├── libfsntfs_compression_unit_data_handle.c │ ├── libfsntfs_compression_unit_data_handle.h │ ├── libfsntfs_compression_unit_descriptor.c │ ├── libfsntfs_compression_unit_descriptor.h │ ├── libfsntfs_data_run.c │ ├── libfsntfs_data_run.h │ ├── libfsntfs_data_stream.c │ ├── libfsntfs_data_stream.h │ ├── libfsntfs_debug.c │ ├── libfsntfs_debug.h │ ├── libfsntfs_definitions.h.in │ ├── libfsntfs_directory_entries_tree.c │ ├── libfsntfs_directory_entries_tree.h │ ├── libfsntfs_directory_entry.c │ ├── libfsntfs_directory_entry.h │ ├── libfsntfs_error.c │ ├── libfsntfs_error.h │ ├── libfsntfs_extent.c │ ├── libfsntfs_extent.h │ ├── libfsntfs_extern.h │ ├── libfsntfs_file_entry.c │ ├── libfsntfs_file_entry.h │ ├── libfsntfs_file_name_attribute.c │ ├── libfsntfs_file_name_attribute.h │ ├── libfsntfs_file_name_values.c │ ├── libfsntfs_file_name_values.h │ ├── libfsntfs_file_system.c │ ├── libfsntfs_file_system.h │ ├── libfsntfs_fixup_values.c │ ├── libfsntfs_fixup_values.h │ ├── libfsntfs_index.c │ ├── libfsntfs_index.h │ ├── libfsntfs_index_entry.c │ ├── libfsntfs_index_entry.h │ ├── libfsntfs_index_entry_header.c │ ├── libfsntfs_index_entry_header.h │ ├── libfsntfs_index_entry_vector.c │ ├── libfsntfs_index_entry_vector.h │ ├── libfsntfs_index_node.c │ ├── libfsntfs_index_node.h │ ├── libfsntfs_index_node_header.c │ ├── libfsntfs_index_node_header.h │ ├── libfsntfs_index_root_header.c │ ├── libfsntfs_index_root_header.h │ ├── libfsntfs_index_value.c │ ├── libfsntfs_index_value.h │ ├── libfsntfs_io_handle.c │ ├── libfsntfs_io_handle.h │ ├── libfsntfs_libbfio.h │ ├── libfsntfs_libcdata.h │ ├── libfsntfs_libcerror.h │ ├── libfsntfs_libclocale.h │ ├── libfsntfs_libcnotify.h │ ├── libfsntfs_libcthreads.h │ ├── libfsntfs_libfcache.h │ ├── libfsntfs_libfdata.h │ ├── libfsntfs_libfdatetime.h │ ├── libfsntfs_libfguid.h │ ├── libfsntfs_libfwnt.h │ ├── libfsntfs_libuna.h │ ├── libfsntfs_logged_utility_stream_values.c │ ├── libfsntfs_logged_utility_stream_values.h │ ├── libfsntfs_mft.c │ ├── libfsntfs_mft.h │ ├── libfsntfs_mft_attribute.c │ ├── libfsntfs_mft_attribute.h │ ├── libfsntfs_mft_attribute_list.c │ ├── libfsntfs_mft_attribute_list.h │ ├── libfsntfs_mft_attribute_list_entry.c │ ├── libfsntfs_mft_attribute_list_entry.h │ ├── libfsntfs_mft_entry.c │ ├── libfsntfs_mft_entry.h │ ├── libfsntfs_mft_entry_header.c │ ├── libfsntfs_mft_entry_header.h │ ├── libfsntfs_mft_metadata_file.c │ ├── libfsntfs_mft_metadata_file.h │ ├── libfsntfs_name.c │ ├── libfsntfs_name.h │ ├── libfsntfs_notify.c │ ├── libfsntfs_notify.h │ ├── libfsntfs_object_identifier_attribute.c │ ├── libfsntfs_object_identifier_attribute.h │ ├── libfsntfs_object_identifier_values.c │ ├── libfsntfs_object_identifier_values.h │ ├── libfsntfs_path_hint.c │ ├── libfsntfs_path_hint.h │ ├── libfsntfs_profiler.c │ ├── libfsntfs_profiler.h │ ├── libfsntfs_reparse_point_attribute.c │ ├── libfsntfs_reparse_point_attribute.h │ ├── libfsntfs_reparse_point_values.c │ ├── libfsntfs_reparse_point_values.h │ ├── libfsntfs_sds_index_value.c │ ├── libfsntfs_sds_index_value.h │ ├── libfsntfs_security_descriptor_attribute.c │ ├── libfsntfs_security_descriptor_attribute.h │ ├── libfsntfs_security_descriptor_index.c │ ├── libfsntfs_security_descriptor_index.h │ ├── libfsntfs_security_descriptor_index_value.c │ ├── libfsntfs_security_descriptor_index_value.h │ ├── libfsntfs_security_descriptor_values.c │ ├── libfsntfs_security_descriptor_values.h │ ├── libfsntfs_standard_information_attribute.c │ ├── libfsntfs_standard_information_attribute.h │ ├── libfsntfs_standard_information_values.c │ ├── libfsntfs_standard_information_values.h │ ├── libfsntfs_support.c │ ├── libfsntfs_support.h │ ├── libfsntfs_txf_data_values.c │ ├── libfsntfs_txf_data_values.h │ ├── libfsntfs_types.h │ ├── libfsntfs_unused.h │ ├── libfsntfs_usn_change_journal.c │ ├── libfsntfs_usn_change_journal.h │ ├── libfsntfs_volume.c │ ├── libfsntfs_volume.h │ ├── libfsntfs_volume_header.c │ ├── libfsntfs_volume_header.h │ ├── libfsntfs_volume_information_attribute.c │ ├── libfsntfs_volume_information_attribute.h │ ├── libfsntfs_volume_information_values.c │ ├── libfsntfs_volume_information_values.h │ ├── libfsntfs_volume_name_attribute.c │ ├── libfsntfs_volume_name_attribute.h │ ├── libfsntfs_volume_name_values.c │ └── libfsntfs_volume_name_values.h ├── libfsntfs.ini ├── libfsntfs.nuspec ├── libfsntfs.pc.in ├── libfsntfs.spec.in ├── m4/ │ ├── common.m4 │ ├── libbfio.m4 │ ├── libcdata.m4 │ ├── libcerror.m4 │ ├── libcfile.m4 │ ├── libclocale.m4 │ ├── libcnotify.m4 │ ├── libcpath.m4 │ ├── libcrypto.m4 │ ├── libcsplit.m4 │ ├── libcthreads.m4 │ ├── libfcache.m4 │ ├── libfdata.m4 │ ├── libfdatetime.m4 │ ├── libfguid.m4 │ ├── libfuse.m4 │ ├── libfusn.m4 │ ├── libfwnt.m4 │ ├── libhmac.m4 │ ├── libuna.m4 │ ├── pthread.m4 │ ├── python.m4 │ ├── tests.m4 │ └── types.m4 ├── manuals/ │ ├── Makefile.am │ ├── fsntfsinfo.1 │ └── libfsntfs.3 ├── msvscpp/ │ ├── Makefile.am │ ├── fsntfs_test_attribute/ │ │ └── fsntfs_test_attribute.vcproj │ ├── fsntfs_test_attribute_list_entry/ │ │ └── fsntfs_test_attribute_list_entry.vcproj │ ├── fsntfs_test_bitmap_values/ │ │ └── fsntfs_test_bitmap_values.vcproj │ ├── fsntfs_test_buffer_data_handle/ │ │ └── fsntfs_test_buffer_data_handle.vcproj │ ├── fsntfs_test_cluster_block/ │ │ └── fsntfs_test_cluster_block.vcproj │ ├── fsntfs_test_cluster_block_data/ │ │ └── fsntfs_test_cluster_block_data.vcproj │ ├── fsntfs_test_cluster_block_stream/ │ │ └── fsntfs_test_cluster_block_stream.vcproj │ ├── fsntfs_test_cluster_block_vector/ │ │ └── fsntfs_test_cluster_block_vector.vcproj │ ├── fsntfs_test_compressed_block/ │ │ └── fsntfs_test_compressed_block.vcproj │ ├── fsntfs_test_compressed_block_data_handle/ │ │ └── fsntfs_test_compressed_block_data_handle.vcproj │ ├── fsntfs_test_compressed_block_vector/ │ │ └── fsntfs_test_compressed_block_vector.vcproj │ ├── fsntfs_test_compressed_data_handle/ │ │ └── fsntfs_test_compressed_data_handle.vcproj │ ├── fsntfs_test_compression/ │ │ └── fsntfs_test_compression.vcproj │ ├── fsntfs_test_compression_unit_data_handle/ │ │ └── fsntfs_test_compression_unit_data_handle.vcproj │ ├── fsntfs_test_compression_unit_descriptor/ │ │ └── fsntfs_test_compression_unit_descriptor.vcproj │ ├── fsntfs_test_data_run/ │ │ └── fsntfs_test_data_run.vcproj │ ├── fsntfs_test_data_stream/ │ │ └── fsntfs_test_data_stream.vcproj │ ├── fsntfs_test_directory_entries_tree/ │ │ └── fsntfs_test_directory_entries_tree.vcproj │ ├── fsntfs_test_directory_entry/ │ │ └── fsntfs_test_directory_entry.vcproj │ ├── fsntfs_test_error/ │ │ └── fsntfs_test_error.vcproj │ ├── fsntfs_test_extent/ │ │ └── fsntfs_test_extent.vcproj │ ├── fsntfs_test_file_entry/ │ │ └── fsntfs_test_file_entry.vcproj │ ├── fsntfs_test_file_name_attribute/ │ │ └── fsntfs_test_file_name_attribute.vcproj │ ├── fsntfs_test_file_name_values/ │ │ └── fsntfs_test_file_name_values.vcproj │ ├── fsntfs_test_file_system/ │ │ └── fsntfs_test_file_system.vcproj │ ├── fsntfs_test_fixup_values/ │ │ └── fsntfs_test_fixup_values.vcproj │ ├── fsntfs_test_index/ │ │ └── fsntfs_test_index.vcproj │ ├── fsntfs_test_index_entry/ │ │ └── fsntfs_test_index_entry.vcproj │ ├── fsntfs_test_index_entry_header/ │ │ └── fsntfs_test_index_entry_header.vcproj │ ├── fsntfs_test_index_entry_vector/ │ │ └── fsntfs_test_index_entry_vector.vcproj │ ├── fsntfs_test_index_node/ │ │ └── fsntfs_test_index_node.vcproj │ ├── fsntfs_test_index_node_header/ │ │ └── fsntfs_test_index_node_header.vcproj │ ├── fsntfs_test_index_root_header/ │ │ └── fsntfs_test_index_root_header.vcproj │ ├── fsntfs_test_index_value/ │ │ └── fsntfs_test_index_value.vcproj │ ├── fsntfs_test_io_handle/ │ │ └── fsntfs_test_io_handle.vcproj │ ├── fsntfs_test_logged_utility_stream_values/ │ │ └── fsntfs_test_logged_utility_stream_values.vcproj │ ├── fsntfs_test_mft/ │ │ └── fsntfs_test_mft.vcproj │ ├── fsntfs_test_mft_attribute/ │ │ └── fsntfs_test_mft_attribute.vcproj │ ├── fsntfs_test_mft_attribute_list/ │ │ └── fsntfs_test_mft_attribute_list.vcproj │ ├── fsntfs_test_mft_attribute_list_entry/ │ │ └── fsntfs_test_mft_attribute_list_entry.vcproj │ ├── fsntfs_test_mft_entry/ │ │ └── fsntfs_test_mft_entry.vcproj │ ├── fsntfs_test_mft_entry_header/ │ │ └── fsntfs_test_mft_entry_header.vcproj │ ├── fsntfs_test_mft_metadata_file/ │ │ └── fsntfs_test_mft_metadata_file.vcproj │ ├── fsntfs_test_name/ │ │ └── fsntfs_test_name.vcproj │ ├── fsntfs_test_notify/ │ │ └── fsntfs_test_notify.vcproj │ ├── fsntfs_test_object_identifier_values/ │ │ └── fsntfs_test_object_identifier_values.vcproj │ ├── fsntfs_test_path_hint/ │ │ └── fsntfs_test_path_hint.vcproj │ ├── fsntfs_test_profiler/ │ │ └── fsntfs_test_profiler.vcproj │ ├── fsntfs_test_reparse_point_attribute/ │ │ └── fsntfs_test_reparse_point_attribute.vcproj │ ├── fsntfs_test_reparse_point_values/ │ │ └── fsntfs_test_reparse_point_values.vcproj │ ├── fsntfs_test_sds_index_value/ │ │ └── fsntfs_test_sds_index_value.vcproj │ ├── fsntfs_test_security_descriptor_index/ │ │ └── fsntfs_test_security_descriptor_index.vcproj │ ├── fsntfs_test_security_descriptor_index_value/ │ │ └── fsntfs_test_security_descriptor_index_value.vcproj │ ├── fsntfs_test_security_descriptor_values/ │ │ └── fsntfs_test_security_descriptor_values.vcproj │ ├── fsntfs_test_standard_information_values/ │ │ └── fsntfs_test_standard_information_values.vcproj │ ├── fsntfs_test_support/ │ │ └── fsntfs_test_support.vcproj │ ├── fsntfs_test_tools_bodyfile/ │ │ └── fsntfs_test_tools_bodyfile.vcproj │ ├── fsntfs_test_tools_digest_hash/ │ │ └── fsntfs_test_tools_digest_hash.vcproj │ ├── fsntfs_test_tools_info_handle/ │ │ └── fsntfs_test_tools_info_handle.vcproj │ ├── fsntfs_test_tools_mount_path_string/ │ │ └── fsntfs_test_tools_mount_path_string.vcproj │ ├── fsntfs_test_tools_output/ │ │ └── fsntfs_test_tools_output.vcproj │ ├── fsntfs_test_tools_path_string/ │ │ └── fsntfs_test_tools_path_string.vcproj │ ├── fsntfs_test_tools_signal/ │ │ └── fsntfs_test_tools_signal.vcproj │ ├── fsntfs_test_txf_data_values/ │ │ └── fsntfs_test_txf_data_values.vcproj │ ├── fsntfs_test_usn_change_journal/ │ │ └── fsntfs_test_usn_change_journal.vcproj │ ├── fsntfs_test_volume/ │ │ └── fsntfs_test_volume.vcproj │ ├── fsntfs_test_volume_header/ │ │ └── fsntfs_test_volume_header.vcproj │ ├── fsntfs_test_volume_information_attribute/ │ │ └── fsntfs_test_volume_information_attribute.vcproj │ ├── fsntfs_test_volume_information_values/ │ │ └── fsntfs_test_volume_information_values.vcproj │ ├── fsntfs_test_volume_name_attribute/ │ │ └── fsntfs_test_volume_name_attribute.vcproj │ ├── fsntfs_test_volume_name_values/ │ │ └── fsntfs_test_volume_name_values.vcproj │ ├── fsntfsinfo/ │ │ └── fsntfsinfo.vcproj │ ├── fsntfsmount/ │ │ └── fsntfsmount.vcproj │ ├── libbfio/ │ │ └── libbfio.vcproj │ ├── libcdata/ │ │ └── libcdata.vcproj │ ├── libcerror/ │ │ └── libcerror.vcproj │ ├── libcfile/ │ │ └── libcfile.vcproj │ ├── libclocale/ │ │ └── libclocale.vcproj │ ├── libcnotify/ │ │ └── libcnotify.vcproj │ ├── libcpath/ │ │ └── libcpath.vcproj │ ├── libcsplit/ │ │ └── libcsplit.vcproj │ ├── libcthreads/ │ │ └── libcthreads.vcproj │ ├── libfcache/ │ │ └── libfcache.vcproj │ ├── libfdata/ │ │ └── libfdata.vcproj │ ├── libfdatetime/ │ │ └── libfdatetime.vcproj │ ├── libfguid/ │ │ └── libfguid.vcproj │ ├── libfsntfs/ │ │ └── libfsntfs.vcproj │ ├── libfsntfs.sln │ ├── libfusn/ │ │ └── libfusn.vcproj │ ├── libfwnt/ │ │ └── libfwnt.vcproj │ ├── libhmac/ │ │ └── libhmac.vcproj │ ├── libuna/ │ │ └── libuna.vcproj │ └── pyfsntfs/ │ └── pyfsntfs.vcproj ├── ossfuzz/ │ ├── Makefile.am │ ├── file_entry_fuzzer.cc │ ├── mft_metadata_file_fuzzer.cc │ ├── ossfuzz_libbfio.h │ ├── ossfuzz_libfsntfs.h │ └── volume_fuzzer.cc ├── po/ │ ├── ChangeLog │ ├── Makevars.in │ └── POTFILES.in ├── pyfsntfs/ │ ├── Makefile.am │ ├── pyfsntfs.c │ ├── pyfsntfs.h │ ├── pyfsntfs_attribute.c │ ├── pyfsntfs_attribute.h │ ├── pyfsntfs_attribute_types.c │ ├── pyfsntfs_attribute_types.h │ ├── pyfsntfs_attributes.c │ ├── pyfsntfs_attributes.h │ ├── pyfsntfs_data_stream.c │ ├── pyfsntfs_data_stream.h │ ├── pyfsntfs_data_streams.c │ ├── pyfsntfs_data_streams.h │ ├── pyfsntfs_datetime.c │ ├── pyfsntfs_datetime.h │ ├── pyfsntfs_error.c │ ├── pyfsntfs_error.h │ ├── pyfsntfs_file_attribute_flags.c │ ├── pyfsntfs_file_attribute_flags.h │ ├── pyfsntfs_file_entries.c │ ├── pyfsntfs_file_entries.h │ ├── pyfsntfs_file_entry.c │ ├── pyfsntfs_file_entry.h │ ├── pyfsntfs_file_name_attribute.c │ ├── pyfsntfs_file_name_attribute.h │ ├── pyfsntfs_file_object_io_handle.c │ ├── pyfsntfs_file_object_io_handle.h │ ├── pyfsntfs_guid.c │ ├── pyfsntfs_guid.h │ ├── pyfsntfs_integer.c │ ├── pyfsntfs_integer.h │ ├── pyfsntfs_libbfio.h │ ├── pyfsntfs_libcerror.h │ ├── pyfsntfs_libclocale.h │ ├── pyfsntfs_libfguid.h │ ├── pyfsntfs_libfsntfs.h │ ├── pyfsntfs_libuna.h │ ├── pyfsntfs_mft_metadata_file.c │ ├── pyfsntfs_mft_metadata_file.h │ ├── pyfsntfs_mft_metadata_file_entries.c │ ├── pyfsntfs_mft_metadata_file_entries.h │ ├── pyfsntfs_object_identifier_attribute.c │ ├── pyfsntfs_object_identifier_attribute.h │ ├── pyfsntfs_python.h │ ├── pyfsntfs_reparse_point_attribute.c │ ├── pyfsntfs_reparse_point_attribute.h │ ├── pyfsntfs_security_descriptor_attribute.c │ ├── pyfsntfs_security_descriptor_attribute.h │ ├── pyfsntfs_standard_information_attribute.c │ ├── pyfsntfs_standard_information_attribute.h │ ├── pyfsntfs_string.c │ ├── pyfsntfs_string.h │ ├── pyfsntfs_unused.h │ ├── pyfsntfs_usn_change_journal.c │ ├── pyfsntfs_usn_change_journal.h │ ├── pyfsntfs_volume.c │ ├── pyfsntfs_volume.h │ ├── pyfsntfs_volume_file_entries.c │ ├── pyfsntfs_volume_file_entries.h │ ├── pyfsntfs_volume_information_attribute.c │ ├── pyfsntfs_volume_information_attribute.h │ ├── pyfsntfs_volume_name_attribute.c │ └── pyfsntfs_volume_name_attribute.h ├── pyproject.toml ├── runtests.ps1 ├── runtests.sh ├── setup.cfg.in ├── setup.py ├── syncdokan.ps1 ├── synclibs.ps1 ├── synclibs.sh ├── synctestdata.ps1 ├── synctestdata.sh ├── tests/ │ ├── Makefile.am │ ├── build.sh │ ├── data/ │ │ ├── attribute_list.1 │ │ ├── attribute_list_entry.1 │ │ ├── index_node_data.1 │ │ ├── mft_attribute.1 │ │ ├── mft_attribute.2 │ │ ├── mft_entry.1 │ │ ├── mft_entry.2 │ │ ├── mft_entry_header.1 │ │ ├── mft_entry_header.2 │ │ ├── mft_metadata_file.1 │ │ ├── security_descriptor_index_value_data.1 │ │ └── volume_header.1 │ ├── fsntfs_test_attribute.c │ ├── fsntfs_test_attribute_list_entry.c │ ├── fsntfs_test_bitmap_values.c │ ├── fsntfs_test_buffer_data_handle.c │ ├── fsntfs_test_cluster_block.c │ ├── fsntfs_test_cluster_block_data.c │ ├── fsntfs_test_cluster_block_stream.c │ ├── fsntfs_test_cluster_block_vector.c │ ├── fsntfs_test_compressed_block.c │ ├── fsntfs_test_compressed_block_data_handle.c │ ├── fsntfs_test_compressed_block_vector.c │ ├── fsntfs_test_compressed_data_handle.c │ ├── fsntfs_test_compression.c │ ├── fsntfs_test_compression_unit_data_handle.c │ ├── fsntfs_test_compression_unit_descriptor.c │ ├── fsntfs_test_data_run.c │ ├── fsntfs_test_data_stream.c │ ├── fsntfs_test_directory_entries_tree.c │ ├── fsntfs_test_directory_entry.c │ ├── fsntfs_test_error.c │ ├── fsntfs_test_extent.c │ ├── fsntfs_test_file_entry.c │ ├── fsntfs_test_file_name_attribute.c │ ├── fsntfs_test_file_name_values.c │ ├── fsntfs_test_file_system.c │ ├── fsntfs_test_fixup_values.c │ ├── fsntfs_test_functions.c │ ├── fsntfs_test_functions.h │ ├── fsntfs_test_getopt.c │ ├── fsntfs_test_getopt.h │ ├── fsntfs_test_index.c │ ├── fsntfs_test_index_entry.c │ ├── fsntfs_test_index_entry_header.c │ ├── fsntfs_test_index_entry_vector.c │ ├── fsntfs_test_index_node.c │ ├── fsntfs_test_index_node_header.c │ ├── fsntfs_test_index_root_header.c │ ├── fsntfs_test_index_value.c │ ├── fsntfs_test_io_handle.c │ ├── fsntfs_test_libbfio.h │ ├── fsntfs_test_libcdata.h │ ├── fsntfs_test_libcerror.h │ ├── fsntfs_test_libclocale.h │ ├── fsntfs_test_libcnotify.h │ ├── fsntfs_test_libcpath.h │ ├── fsntfs_test_libcthreads.h │ ├── fsntfs_test_libfcache.h │ ├── fsntfs_test_libfdata.h │ ├── fsntfs_test_libfsntfs.h │ ├── fsntfs_test_libuna.h │ ├── fsntfs_test_logged_utility_stream_values.c │ ├── fsntfs_test_macros.h │ ├── fsntfs_test_memory.c │ ├── fsntfs_test_memory.h │ ├── fsntfs_test_mft.c │ ├── fsntfs_test_mft_attribute.c │ ├── fsntfs_test_mft_attribute_list.c │ ├── fsntfs_test_mft_attribute_list_entry.c │ ├── fsntfs_test_mft_entry.c │ ├── fsntfs_test_mft_entry_header.c │ ├── fsntfs_test_mft_metadata_file.c │ ├── fsntfs_test_name.c │ ├── fsntfs_test_notify.c │ ├── fsntfs_test_object_identifier_values.c │ ├── fsntfs_test_path_hint.c │ ├── fsntfs_test_profiler.c │ ├── fsntfs_test_reparse_point_attribute.c │ ├── fsntfs_test_reparse_point_values.c │ ├── fsntfs_test_rwlock.c │ ├── fsntfs_test_rwlock.h │ ├── fsntfs_test_sds_index_value.c │ ├── fsntfs_test_security_descriptor_index.c │ ├── fsntfs_test_security_descriptor_index_value.c │ ├── fsntfs_test_security_descriptor_values.c │ ├── fsntfs_test_standard_information_values.c │ ├── fsntfs_test_support.c │ ├── fsntfs_test_tools_bodyfile.c │ ├── fsntfs_test_tools_digest_hash.c │ ├── fsntfs_test_tools_info_handle.c │ ├── fsntfs_test_tools_mount_path_string.c │ ├── fsntfs_test_tools_output.c │ ├── fsntfs_test_tools_path_string.c │ ├── fsntfs_test_tools_signal.c │ ├── fsntfs_test_txf_data_values.c │ ├── fsntfs_test_unused.h │ ├── fsntfs_test_usn_change_journal.c │ ├── fsntfs_test_volume.c │ ├── fsntfs_test_volume_header.c │ ├── fsntfs_test_volume_information_attribute.c │ ├── fsntfs_test_volume_information_values.c │ ├── fsntfs_test_volume_name_attribute.c │ ├── fsntfs_test_volume_name_values.c │ ├── lsan.suppressions │ ├── pkgbuild.sh │ ├── pyfsntfs_test_attribute.py │ ├── pyfsntfs_test_file_entry.py │ ├── pyfsntfs_test_support.py │ ├── pyfsntfs_test_volume.py │ ├── runtests.py │ ├── runtests.sh │ ├── syncsharedlibs.sh │ ├── test_fsntfsinfo.ps1 │ ├── test_fsntfsinfo.sh │ ├── test_fsntfsinfo_bodyfile.ps1 │ ├── test_fsntfsinfo_bodyfile.sh │ ├── test_library.ps1 │ ├── test_library.sh │ ├── test_manpage.sh │ ├── test_python_module.sh │ ├── test_runner.sh │ ├── test_tools.ps1 │ └── test_tools.sh └── tox.ini ================================================ FILE CONTENTS ================================================ ================================================ FILE: .codecov.yml ================================================ coverage: precision: 2 round: down range: 70...100 status: project: true patch: true changes: false ignore: - "libbfio/*" - "libcdata/*" - "libcerror/*" - "libcfile/*" - "libclocale/*" - "libcnotify/*" - "libcpath/*" - "libcsplit/*" - "libcthreads/*" - "libfcache/*" - "libfdata/*" - "libfdatetime/*" - "libfguid/*" - "libfusn/*" - "libfwnt/*" - "libhmac/*" - "libuna/*" - "tests/*" ================================================ FILE: .github/workflows/build.yml ================================================ # Build from source. name: build on: [push, pull_request] permissions: read-all jobs: build_ubuntu: runs-on: ubuntu-latest strategy: matrix: include: - architecture: 'x86' compiler: 'clang' configure_options: '' - architecture: 'x64' compiler: 'clang' configure_options: '' - architecture: 'x86' compiler: 'gcc' configure_options: '' - architecture: 'x64' compiler: 'gcc' configure_options: '' - architecture: 'x64' compiler: 'gcc' configure_options: '--with-pthread=no' - architecture: 'x64' compiler: 'gcc' configure_options: '--enable-wide-character-type' - architecture: 'x64' compiler: 'gcc' configure_options: '--enable-static-executables=yes --enable-multi-threading-support=no' steps: - uses: actions/checkout@v5 - name: Install build dependencies run: | sudo apt-get -y install autoconf automake autopoint build-essential git libfuse3-dev libssl-dev libtool pkg-config - name: Download test data run: | if test -x "synctestdata.sh"; then ./synctestdata.sh; fi - name: Building from source env: CC: ${{ matrix.compiler }} run: | tests/build.sh ${{ matrix.configure_options }} - name: Run tests run: | tests/runtests.sh build_dist: runs-on: ubuntu-latest strategy: matrix: include: - architecture: 'x64' compiler: 'gcc' configure_options: '' steps: - uses: actions/checkout@v5 - name: Install build dependencies run: | sudo apt-get -y install autoconf automake autopoint build-essential git libfuse3-dev libssl-dev libtool pkg-config - name: Download test data run: | if test -x "synctestdata.sh"; then ./synctestdata.sh; fi - name: Building from source env: CC: ${{ matrix.compiler }} run: | tests/build.sh ${{ matrix.configure_options }} - name: Run tests run: | make distcheck build_fuse_ubuntu: runs-on: ubuntu-latest strategy: matrix: include: - architecture: 'x64' compiler: 'gcc' configure_options: '' steps: - uses: actions/checkout@v5 - name: Install build dependencies run: | sudo apt-get -y install autoconf automake autopoint build-essential git libfuse3-dev libssl-dev libtool pkg-config libfuse-dev - name: Download test data run: | if test -x "synctestdata.sh"; then ./synctestdata.sh; fi - name: Building from source env: CC: ${{ matrix.compiler }} run: | tests/build.sh ${{ matrix.configure_options }} - name: Run tests run: | tests/runtests.sh build_fuse3_ubuntu: runs-on: ubuntu-latest strategy: matrix: include: - architecture: 'x64' compiler: 'gcc' configure_options: '' steps: - uses: actions/checkout@v5 - name: Install build dependencies run: | sudo apt-get -y install autoconf automake autopoint build-essential git libfuse3-dev libssl-dev libtool pkg-config libfuse3-dev - name: Download test data run: | if test -x "synctestdata.sh"; then ./synctestdata.sh; fi - name: Building from source env: CC: ${{ matrix.compiler }} run: | tests/build.sh ${{ matrix.configure_options }} - name: Run tests run: | tests/runtests.sh build_python_ubuntu: runs-on: ubuntu-latest strategy: matrix: include: - architecture: 'x64' compiler: 'gcc' configure_options: '--enable-python' python_version: '' steps: - uses: actions/checkout@v5 - name: Install build dependencies run: | sudo add-apt-repository universe && sudo apt-get update && sudo apt-get -y install autoconf automake autopoint build-essential git libfuse3-dev libssl-dev libtool pkg-config python3-dev python-dev-is-python3 - name: Download test data run: | if test -x "synctestdata.sh"; then ./synctestdata.sh; fi - name: Building from source env: CC: ${{ matrix.compiler }} run: | tests/build.sh ${{ matrix.configure_options }} - name: Run tests env: PYTHON_VERSION: ${{ matrix.python_version }} run: | tests/runtests.sh build_setup_py_ubuntu: runs-on: ubuntu-latest strategy: matrix: include: - architecture: 'x64' compiler: 'gcc' configure_options: '' python-version: '3.10' steps: - uses: actions/checkout@v5 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install build dependencies run: | sudo add-apt-repository universe && sudo apt-get update && sudo apt-get -y install autoconf automake autopoint build-essential git libfuse3-dev libssl-dev libtool pkg-config python3-dev python-dev-is-python3 - name: Building from source env: CC: ${{ matrix.compiler }} run: | tests/build.sh ${{ matrix.configure_options }} - name: Build Python module run: | python setup.py build coverage_ubuntu: runs-on: ubuntu-latest strategy: matrix: include: - architecture: 'x86' compiler: 'gcc' configure_options: '--enable-wide-character-type' - architecture: 'x64' compiler: 'gcc' configure_options: '--enable-wide-character-type' steps: - uses: actions/checkout@v5 - name: Install build dependencies run: | sudo apt-get -y install autoconf automake autopoint build-essential git libfuse3-dev libssl-dev libtool pkg-config - name: Download test data run: | if test -x "synctestdata.sh"; then ./synctestdata.sh; fi - name: Building from source env: CC: ${{ matrix.compiler }} run: | tests/build.sh ${{ matrix.configure_options }} --enable-shared=no CFLAGS="--coverage -O0" CPPFLAGS="-DOPTIMIZATION_DISABLED" LDFLAGS="--coverage" - name: Run tests run: | make check CHECK_WITH_STDERR=1 SKIP_TOOLS_END_TO_END_TESTS=1 - name: Generate coverage data run: | for DIRECTORY in `find . -maxdepth 1 -type d`; do \ (cd ${DIRECTORY} && find . -maxdepth 1 -name \*.gcno -type f -exec gcov -pb {} \;) \ done - name: Upload coverage report to Codecov uses: codecov/codecov-action@v5 with: name: linux-${{ matrix.architecture }}-gcc-no-optimization token: ${{ secrets.CODECOV_TOKEN }} ================================================ FILE: .github/workflows/build_freebsd.yml ================================================ # Build from source on FreeBSD. name: build_freebsd on: [push] permissions: read-all jobs: build_freebsd: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - name: Building from source id: build_freebsd uses: vmactions/freebsd-vm@v1 with: usesh: true mem: 4096 # Note that the test scripts require bash prepare: | pkg install -y autoconf automake bash fusefs-libs gettext git libtool openssl pkgconf run: | tests/build.sh tests/runtests.sh ================================================ FILE: .github/workflows/build_macos.yml ================================================ # Build from source. name: build_macos on: [push, pull_request] permissions: read-all jobs: build_macos: runs-on: ${{ matrix.os }} strategy: matrix: include: - os: macos-14 configure_options: '' - os: macos-15 configure_options: '' - os: macos-15-intel configure_options: '' - os: macos-26 configure_options: '' steps: - uses: actions/checkout@v5 - name: Install build dependencies run: | brew update -q brew install -q autoconf automake gettext gnu-sed libtool pkg-config || true brew link --force gettext ln -s /usr/local/bin/glibtoolize /usr/local/bin/libtoolize - name: Download test data run: | if test -x "synctestdata.sh"; then ./synctestdata.sh; fi - name: Building from source env: CC: ${{ matrix.compiler }} run: | tests/build.sh ${{ matrix.configure_options }} - name: Run tests run: | tests/runtests.sh ================================================ FILE: .github/workflows/build_ossfuzz.yml ================================================ # Build OSSFuzz fuzz targets from source. name: build_ossfuzz on: push: branches: [main] permissions: read-all jobs: build_ossfuzz: runs-on: ubuntu-latest strategy: matrix: include: - architecture: 'x64' compiler: 'gcc' configure_options: '' steps: - name: Install build dependencies run: | sudo apt-get -y install git - uses: actions/checkout@v5 with: repository: google/oss-fuzz path: oss-fuzz - name: Build OSSFuzz fuzz targets working-directory: oss-fuzz run: | mkdir -p projects/libfsntfs cp projects/libyal/build.sh projects/libfsntfs/ cp projects/libyal/project.yaml projects/libfsntfs/ head -n 20 projects/libyal/Dockerfile > projects/libfsntfs/Dockerfile echo "RUN git clone --depth 1 https://github.com/libyal/libfsntfs.git libfsntfs" >> projects/libfsntfs/Dockerfile tail -n 3 projects/libyal/Dockerfile >> projects/libfsntfs/Dockerfile python3 infra/helper.py build_image --pull libfsntfs python3 infra/helper.py build_fuzzers --sanitizer address libfsntfs python3 infra/helper.py check_build libfsntfs ================================================ FILE: .github/workflows/build_shared.yml ================================================ # Build from source with libyal dependencies as shared libraries. name: build_shared on: push: branches: [main] permissions: read-all jobs: build_shared_ubuntu: runs-on: ubuntu-latest strategy: matrix: include: - architecture: 'x64' compiler: 'gcc' configure_options: '' - architecture: 'x64' compiler: 'gcc' configure_options: '--enable-wide-character-type' steps: - uses: actions/checkout@v5 - name: Install build dependencies run: | sudo apt-get -y install autoconf automake autopoint build-essential git libfuse3-dev libssl-dev libtool pkg-config - name: Download test data run: | if test -x "synctestdata.sh"; then ./synctestdata.sh; fi - name: Prepare shared libraries run: | tests/syncsharedlibs.sh --use-head - name: Building from source env: CC: ${{ matrix.compiler }} run: | tests/build.sh ${{ matrix.configure_options }} - name: Run tests run: | tests/runtests.sh ================================================ FILE: .github/workflows/build_wheel.yml ================================================ # Build Python wheels from source using cibuildwheel. name: build_wheels on: [push, pull_request] permissions: read-all jobs: build_wheels_linux: name: Build wheels on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: matrix: include: - os: ubuntu-24.04-arm - os: ubuntu-latest steps: - uses: actions/checkout@v5 - name: Install build dependencies run: | sudo apt-get -y install autoconf automake autopoint build-essential git libtool pkg-config - name: Prepare build run: | ./synclibs.sh ./autogen.sh ./configure make sources >/dev/null - name: Build Python wheels uses: pypa/cibuildwheel@v3.3.0 env: CIBW_TEST_COMMAND: python tests/runtests.py CIBW_TEST_SOURCES: tests with: package-dir: . output-dir: dist - uses: actions/upload-artifact@v4 with: name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }} path: dist/*.whl build_wheels_macos: name: Build wheels on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: matrix: include: - os: macos-14 - os: macos-15-intel steps: - uses: actions/checkout@v5 - name: Install build dependencies run: | brew update -q brew install -q autoconf automake gettext gnu-sed libtool pkg-config || true brew link --force gettext ln -s /usr/local/bin/glibtoolize /usr/local/bin/libtoolize - name: Prepare build run: | ./synclibs.sh ./autogen.sh ./configure make sources >/dev/null - name: Build Python wheels uses: pypa/cibuildwheel@v3.3.0 env: CIBW_TEST_COMMAND: python tests/runtests.py CIBW_TEST_SOURCES: tests with: package-dir: . output-dir: dist - uses: actions/upload-artifact@v4 with: name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }} path: dist/*.whl build_wheels_windows: name: Build wheels on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: matrix: include: - os: windows-11-arm - os: windows-latest steps: - uses: actions/checkout@v5 - name: Prepare build run: | .\synclibs.ps1 .\autogen.ps1 - name: Build Python wheels uses: pypa/cibuildwheel@v3.3.0 env: CIBW_TEST_COMMAND: python tests/runtests.py CIBW_TEST_SOURCES: tests with: package-dir: . output-dir: dist - uses: actions/upload-artifact@v4 with: name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }} path: dist/*.whl ================================================ FILE: .gitignore ================================================ # Files to ignore by git # # Version: 20231119 # Generic auto-generated build files *~ *.a *.gcda *.gcno *.gcov *.la *.lai *.lib *.lineno *.lo *.log *.loT *.o *.obj *.Plo *.Po *.so *.so.[0-9][0-9]* *.so.[0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]* *.swp *.Tpo *.trs *.whl /*.egg-info/ __pycache__ .deps .dirstamp .libs .tox INSTALL Makefile Makefile.bcc Makefile.in stamp-h[1-9] # Specific auto-generated build files /ABOUT-NLS /aclocal.m4 /autom4te.cache/ /build /compile /confdefs.h /config.cache /config.guess /config.log /config.rpath /config.status /config.sub /configure /conftest.c /depcomp /dist /install-sh /libtool /ltmain.sh /m4/codeset.m4 /m4/extern-inline.m4 /m4/fcntl-o.m4 /m4/gettext.m4 /m4/glibc21.m4 /m4/glibc2.m4 /m4/host-cpu-c-abi.m4 /m4/iconv.m4 /m4/intdiv0.m4 /m4/intldir.m4 /m4/intl.m4 /m4/intlmacosx.m4 /m4/intmax.m4 /m4/inttypes_h.m4 /m4/inttypes-pri.m4 /m4/lcmessage.m4 /m4/lib-ld.m4 /m4/lib-link.m4 /m4/lib-prefix.m4 /m4/libtool.m4 /m4/lock.m4 /m4/longlong.m4 /m4/lt~obsolete.m4 /m4/ltoptions.m4 /m4/ltsugar.m4 /m4/ltversion.m4 /m4/nls.m4 /m4/pkg.m4 /m4/po.m4 /m4/printf-posix.m4 /m4/progtest.m4 /m4/size_max.m4 /m4/stdint_h.m4 /m4/threadlib.m4 /m4/uintmax_t.m4 /m4/visibility.m4 /m4/wchar_t.m4 /m4/wint_t.m4 /m4/xsize.m4 /MANIFEST /missing /po/boldquot.sed /po/en@boldquot.header /po/en@quot.header /po/insert-header.sin /po/Makefile.in.in /po/Makevars /po/Makevars.template /po/POTFILES /po/quot.sed /po/remove-potcdate.sed /po/remove-potcdate.sin /po/Rules-quot /test-driver /ylwrap # Project specific files /common/config.h /common/config.h.in /common/types.h /dpkg/changelog /include/libfsntfs.h /include/libfsntfs/definitions.h /include/libfsntfs/features.h /include/libfsntfs/types.h /libfsntfs.pc /libfsntfs.spec /libfsntfs/libfsntfs.rc /libfsntfs/libfsntfs_definitions.h /setup.cfg /fsntfstools/*.exe /fsntfstools/fsntfsinfo /fsntfstools/fsntfsmount /tests/*.exe /tests/fsntfs_test_attribute /tests/fsntfs_test_attribute_list_entry /tests/fsntfs_test_bitmap_values /tests/fsntfs_test_buffer_data_handle /tests/fsntfs_test_cluster_block /tests/fsntfs_test_cluster_block_data /tests/fsntfs_test_cluster_block_stream /tests/fsntfs_test_cluster_block_vector /tests/fsntfs_test_compressed_block /tests/fsntfs_test_compressed_block_data_handle /tests/fsntfs_test_compressed_block_vector /tests/fsntfs_test_compressed_data_handle /tests/fsntfs_test_compression /tests/fsntfs_test_compression_unit_data_handle /tests/fsntfs_test_compression_unit_descriptor /tests/fsntfs_test_data_run /tests/fsntfs_test_data_stream /tests/fsntfs_test_directory_entries_tree /tests/fsntfs_test_directory_entry /tests/fsntfs_test_error /tests/fsntfs_test_extent /tests/fsntfs_test_file_entry /tests/fsntfs_test_file_name_attribute /tests/fsntfs_test_file_name_values /tests/fsntfs_test_file_system /tests/fsntfs_test_fixup_values /tests/fsntfs_test_index /tests/fsntfs_test_index_entry /tests/fsntfs_test_index_entry_header /tests/fsntfs_test_index_entry_vector /tests/fsntfs_test_index_node /tests/fsntfs_test_index_node_header /tests/fsntfs_test_index_root_header /tests/fsntfs_test_index_value /tests/fsntfs_test_io_handle /tests/fsntfs_test_logged_utility_stream_values /tests/fsntfs_test_mft /tests/fsntfs_test_mft_attribute /tests/fsntfs_test_mft_attribute_list /tests/fsntfs_test_mft_attribute_list_entry /tests/fsntfs_test_mft_entry /tests/fsntfs_test_mft_entry_header /tests/fsntfs_test_mft_metadata_file /tests/fsntfs_test_name /tests/fsntfs_test_notify /tests/fsntfs_test_object_identifier_values /tests/fsntfs_test_path_hint /tests/fsntfs_test_profiler /tests/fsntfs_test_reparse_point_attribute /tests/fsntfs_test_reparse_point_values /tests/fsntfs_test_sds_index_value /tests/fsntfs_test_security_descriptor_index /tests/fsntfs_test_security_descriptor_index_value /tests/fsntfs_test_security_descriptor_values /tests/fsntfs_test_standard_information_values /tests/fsntfs_test_support /tests/fsntfs_test_tools_bodyfile /tests/fsntfs_test_tools_digest_hash /tests/fsntfs_test_tools_info_handle /tests/fsntfs_test_tools_mount_path_string /tests/fsntfs_test_tools_output /tests/fsntfs_test_tools_path_string /tests/fsntfs_test_tools_signal /tests/fsntfs_test_txf_data_values /tests/fsntfs_test_usn_change_journal /tests/fsntfs_test_volume /tests/fsntfs_test_volume_header /tests/fsntfs_test_volume_information_attribute /tests/fsntfs_test_volume_information_values /tests/fsntfs_test_volume_name_attribute /tests/fsntfs_test_volume_name_values /tests/input /tests/notify_stream.log /tests/tmp* # Local library dependencies specific files /libbfio /libcdata /libcerror /libcfile /libclocale /libcnotify /libcpath /libcsplit /libcthreads /libfcache /libfdata /libfdatetime /libfguid /libfusn /libfwnt /libhmac /libuna ================================================ FILE: AUTHORS ================================================ Acknowledgements: libfsntfs Copyright (C) 2010-2026, Joachim Metz ================================================ FILE: COPYING ================================================ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ================================================ FILE: COPYING.LESSER ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ================================================ FILE: ChangeLog ================================================ TODO * pyfsntfs convert lookup path to support additional character range * libfsntfs and fsntfsmount how to support \\ in file name? since \\ is separator used by the library * extent: flag WofCompressedData extent as wof_compressed? * extent: rename compressed flag to lznt1_compressed? * fsntfsinfo: print volume size * fsntfsinfo: print extents/data runs of $DATA stream? * get_file_entry_by_path determine unicode form * fsntfsmount: cache last 3 recently used directories? * test if format version 1.2 is supported and updated README * refactor $I30 index to file entry ** refactor libfsntfs_mft_entry_has_directory_entries_index * Ntfs compressed stream add uncompressed size check * add raw (no valid size) data stream support * check data size of WOF reparse point * add has WOF compressed data stream function (for dfVFS) * complete read/write lock support ** refactor volume and file entry to use file system ** file entry *** libfsntfs_file_entry_get_name_attribute_index *** libfsntfs_file_entry_get_security_descriptor_size *** libfsntfs_file_entry_get_security_descriptor *** continue with libfsntfs_file_entry_get_sub_file_entry_by_index ** MFT metadata file ** specific attribute values functions ** USN journal * MFT entry ** preserve attribute list data MFT entries? ** libfsntfs_attribute add function to indicate partial attribute (has attribute_list_entry but no mft_attribute) * bitmap values ** handle sparse data runs more efficiently * fsntfsinfo complete bodyfile support ** fix libfsntfs_file_entry_get_security_descriptor_size: unable to retrieve security descriptor from index for identifier: 0. ** add support for tsk metadata address calculation? inside MFT attribute? * fsntfsinfo -F add support for ADS notation * API changes ** rename libfsntfs_volume_get_number_of_file_entries to libfsntfs_volume_get_number_of_mft_entries * change libfsntfs_mft_attribute_get_utf[8,16]_name[_size] to return 0 if not set * add debug compare of long and short names * refactor index to better handle get entry by identifier ** make index value cache a passthrough for index node cache ** use tree for get entry by filename ** use tree for get entry by security identifier ** remove the need for a local cache in libfsntfs_index_read_sub_nodes, use cache value lock instead * rename libfsntfs_internal_attribute_get_data to libfsntfs_internal_attribute_get_resident_data * libfsntfs_attribute add read / seek functions * change calls to libfsntfs_mft_entry_get_index_by_utf8_name to utf16 for optimization * change calls to libfsntfs_mft_entry_get_data_attribute_by_utf8_name to utf16 for optimization * enforce LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY when trying to read data runs * libfsntfs_volume_get_root_directory return 0 if MFT entry 5 does not exists * Check if mft_entry should be cloned before passing to libfsntfs_file_entry_initialize in case it is cached out otherwise remove it from file_entry * tests: pass mft_metadata_file different input files * look into handling directories with high number of entries * libfsntfs/pyfsntfs attribute - expose raw attribute data? * USN change journal - add support for values in $Max * resident data - handle valid data size * enforce LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY when trying to read data runs * fix or remove TODO_CASE_INSENSITIVE * compressed data - handle decompression errors e.g. compression tuple offset value out of bounds. - have means to map sparse ranges outside compressed blocks - handle valid data size * create fsntfsexport tool to export file entry data * handle pre 3.1 attribute names? * check file entry life times * set file entry name, if get by index and number of filenames is 1 * cached indexes? * data runs block - add a check to see if data run sizes add up * volume - complete libfsntfs_volume_has_bitlocker_drvie_encryption - complete libfsntfs_volume_has_volume_shadow_snapshots * file entry - add API get file name by attribute index functions? - add API get parent file_reference name by attribute index functions? - add API function for owner - add API function for security identifier - only retrieve file name from the directory entry? or make clear in function documentation that first non-short filename is the fallback? - add support to retrieve name of the root entry if directory entry is missing * pyfsntfs - add attribute type enum * pyfsntfs file entry - expose more MFT entry values through API and pyfsntfs - add is empty function - add has_reparse_point function - add has_symbolic_link function - add is_corrupt function? - how to handle file-like object functions for non-data file entry * pyfsntfs file entry/data stream - add extents iterator? * libfsntfs/pyfsntfs file entry - expose default data stream - add support for short file name - fallback to short file name if no long * libfsntfs_mft_entry_read_element_data set MFT only flag using element flags * libfsntfs_attribute_read_from_mft handle attribute size out of bounds * mft metadata file parsing mark file entry as in complete if data is stored outside the $MFT * change MFT entry flags value checks to named definitions * attribute data parsing - add SSIZE_MAX check for attribute->data_size before (size_t) cast * cached approach of reading attributes ? * fix issue on win2k image - stack overflow infinite loop - determine MFT entry index based on offset do not rely on value in structure * MFT entry create get data segment function for internal usage * how to handle named index roots e.g. $ObjId:$O, $Quota:$O * fix issue with bounded MFT entry cache * support MFT entry 0 consisting of multiple $DATA attributes - add segment support to ntfs attribute data reference * file_entry: clone directory entry ? * what about ADS support ? - todo read from ads * change libfsntfs_attribute_reference_append_attribute into insert and sort attribute ranges * add function to retrieve MFT entry by index * check if check_signature function uses the right offset * refactor: libfsnt_array_append_entry in index ? * move get mft entry to file entry initialize ? - clone mft entry in file entry initialize (for now the mft entry cache contains a slot for every entry) * move volume header from io handle to separate object ? * $MFT scan - mark ignored attribute list - mark ignored data stream - mark ignored index - handle corrupt MFT entries (e.g. missing FILE signature) (+/-) - allow to read data runs but do not allow to read data * $UsnJrnl:$J parsing - move UsnJrnl parsing into library ? - add support for $UsnJrnl:$J file parsing * API - expose logged utility stream attribute Format: * index - group equivalent index data values * boot block - remove value restriction add sanity check * add support for attributes: - logged utillity stream (LOGGED_UTILITY_STREAM) (partial) * pre NTFS 3.0 attribute types - volume version * filenames - ignoring short filenames for now? * ntfs3g indicates volume is hibernated, could this be stored in the volume flags? Tools: * fsntfsinfo - print ADS - move UsnJrnl to separate tool? - fix remnant data in buffer and remove work around - sanitize control characters in filenames - add detection of BDE and VSS - add support for $LogFile - print $DATA attribute size Error tolerance: * Support partial images/file systems Tests: * file with resident data * file with non-resident data * file with sparse data * file with compressed data * file with valid data size < data size * file with ADS * directory with ADS Performance: * compact attribute union data/file reference (use type to distinguish between them) Debug: * print volume information flags description Deployment * write man pages 20141011 * see `git log' for more recent change log * updated dependencies * changes for project site move 20141004 * removed README.macosx 20140810 * worked on exposing the attributes 20140809 * worked on data streams support * worked on exposing the attributes 20140808 * worked on data streams support 20140803 * bug fix in Python bindings 20140628 * Worked on format support 20140530 * Worked on Python bindings 20140529 * updated dependencies * Worked on Python bindings 20140417 * small changes 20140318 * worked on non-resident attribute list support 20140207 * worked on libfdata refactor 20140206 * worked on libfdata refactor 20140205 * worked on libfdata refactor 20140204 * worked on libfdata refactor 20140203 * worked on libfdata refactor 20140119 * worked on libfdata refactor 20140118 * 2014 update * updated dependencies * worked on libfdata refactor 20131109 * updated dependencies 20130915 * code clean up 20130914 * updated dependencies * added libcthreads build support 20130224 * updated dependencies * 2013 update 20120929 * updated dependencies 20120821 * improve NTFS version 3.0 support 20120820 * applied update * improved reading MFT attribute lists and data MFT entries 20120526 * worked on MFT read and seek data functions 20120520 * 2012 update * updated dependencies * added libfusn * fsntfsinfo: - added info handle 20111125 * code clean up * added support for empty volume name 20111124 * removed libvshadow * updated configure.ac and m4 scripts * added include/codepage.h * updated common, array type * updated libcstring, libsystem, libuna, libfdata, libfdatetime, libfguid, libfwnt * added libfcache * code clean up 20110510 * update libvshadow 20110509 * dist fixes 20110508 * updated configure.ac * updated libcstring, libsystem, libuna, libbfio, libfdata, libfguid 20110309 * small changes 20110308 * small changes 20110306 * worked on support for MFT consisting of multiple data runs 20110305 * updated configure, common, array type, libcstring, liberror, libnotify, libsystem, libuna, libbfio, libfdata, libfdatetime, libfguid, libfwnt * 2011 update 20101216 * updated Makefile 20101214 * updated configure/Makefile 20101209 * added missing MFT entry flags debug output * code clean up * added initial gettext support * updated common, libfdatetime 20101203 * updated common, array type, liberror, libnotify, libsystem, libuna, libbfio, libfdata 20101129 * worked on txf data 20101128 * worked on txf data 20101127 * updated libfdatetime * moved abort to IO handle * worked on txf data 20101126 * worked on support for multiple index allocation attributes 20101125 * worked on support for multiple index allocation attributes * updated libuna, libbfio, libfdata 20101124 * updated configure, libcstring, liberror, libbfio * worked on support for an attribute list 20101113 * textual changes 20101112 * renamed library to libfsntfs 20101110 * worked on winsxs support 20101109 * worked on logged utility stream * updated include/error.h * updated libfdata, liberror, libbfio, libnotify, libsystem * added support for directory index that only consists of index root attribute * fixed bug in fsntinfo * added support for directory index that has root and empty allocation index attributes 20100912 * worked on reading attribute list * updated libbfio 20100911 * improved handling data runs 20100910 * worked on reading directory entries 20100909 * worked on reading directory entries 20100908 * worked on file entry functions * worked on reading directory entries * added debug print of file name attribute namespace description 20100907 * worked on reading directory entries 20100906 * worked on reading indexes 20100905 * worked on reading indexes * worked on data runs 20100904 * worked on attributes * worked on reading indexes * worked on fixup values 20100903 * worked on mft attribute * updated libbfio, libfdata * worked on file entry API functions * added libfguid for $OBJECT_ID attribute * worked on attributes 20100828 * worked on reading a MFT entry and attributes 20100827 * worked on reading a MFT entry and attributes * added debug print of file attribute flag description * added debug print of mft attribute type description 20100826 * worked on reading a MFT entry and attributes 20100825 * initial version ================================================ FILE: Makefile.am ================================================ ACLOCAL_AMFLAGS = -I m4 SUBDIRS = \ include \ common \ libcerror \ libcthreads \ libcdata \ libclocale \ libcnotify \ libcsplit \ libuna \ libcfile \ libcpath \ libbfio \ libfcache \ libfdata \ libfdatetime \ libfguid \ libfwnt \ libfsntfs \ libfusn \ libhmac \ fsntfstools \ pyfsntfs \ po \ manuals \ tests \ ossfuzz \ msvscpp DPKG_FILES = \ dpkg/changelog \ dpkg/changelog.in \ dpkg/compat \ dpkg/control \ dpkg/copyright \ dpkg/rules \ dpkg/libfsntfs.install \ dpkg/libfsntfs-dev.install \ dpkg/libfsntfs-python3.install \ dpkg/libfsntfs-tools.install \ dpkg/source/format GETTEXT_FILES = \ config.rpath \ po/Makevars.in PKGCONFIG_FILES = \ libfsntfs.pc.in SETUP_PY_FILES = \ pyproject.toml \ setup.cfg \ setup.cfg.in \ setup.py SPEC_FILES = \ libfsntfs.spec \ libfsntfs.spec.in EXTRA_DIST = \ $(DPKG_FILES) \ $(GETTEXT_FILES) \ $(PKGCONFIG_FILES) \ $(SETUP_PY_FILES) \ $(SPEC_FILES) DISTCLEANFILES = \ config.status \ config.cache \ config.log \ libfsntfs.pc \ libfsntfs.spec \ Makefile \ Makefile.in \ po/Makevars pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = \ libfsntfs.pc libtool: @LIBTOOL_DEPS@ cd $(srcdir) && $(SHELL) ./config.status --recheck lib: library library: (cd $(srcdir)/common && $(MAKE) $(AM_MAKEFLAGS)) (cd $(srcdir)/libcerror && $(MAKE) $(AM_MAKEFLAGS)) (cd $(srcdir)/libcthreads && $(MAKE) $(AM_MAKEFLAGS)) (cd $(srcdir)/libcdata && $(MAKE) $(AM_MAKEFLAGS)) (cd $(srcdir)/libclocale && $(MAKE) $(AM_MAKEFLAGS)) (cd $(srcdir)/libcnotify && $(MAKE) $(AM_MAKEFLAGS)) (cd $(srcdir)/libcsplit && $(MAKE) $(AM_MAKEFLAGS)) (cd $(srcdir)/libuna && $(MAKE) $(AM_MAKEFLAGS)) (cd $(srcdir)/libcfile && $(MAKE) $(AM_MAKEFLAGS)) (cd $(srcdir)/libcpath && $(MAKE) $(AM_MAKEFLAGS)) (cd $(srcdir)/libbfio && $(MAKE) $(AM_MAKEFLAGS)) (cd $(srcdir)/libfcache && $(MAKE) $(AM_MAKEFLAGS)) (cd $(srcdir)/libfdata && $(MAKE) $(AM_MAKEFLAGS)) (cd $(srcdir)/libfdatetime && $(MAKE) $(AM_MAKEFLAGS)) (cd $(srcdir)/libfguid && $(MAKE) $(AM_MAKEFLAGS)) (cd $(srcdir)/libfwnt && $(MAKE) $(AM_MAKEFLAGS)) (cd $(srcdir)/libfsntfs && $(MAKE) $(AM_MAKEFLAGS)) (cd $(srcdir)/po && $(MAKE) $(AM_MAKEFLAGS)) ================================================ FILE: NEWS ================================================ ================================================ FILE: README ================================================ libfsntfs is a library to access the New Technology File System (NTFS) format. Project information: * Status: experimental * Licence: LGPLv3+ Read-only supported NTFS formats: * NTFS version 3.0 * NTFS version 3.1 Supported NTFS format features: * LZNT1 compression * Windows Overlay Filter (WOF) compressed data (LZX and LZXPRESS-Huffman) * Case sensitive directories Unsupported NTFS format features: * NTFS version 1.0 * NTFS version 1.1 * NTFS version 1.2 * Encrypted File System (EFS) For more information see: * Project documentation: https://github.com/libyal/libfsntfs/wiki/Home * How to build from source: https://github.com/libyal/libfsntfs/wiki/Building ================================================ FILE: acinclude.m4 ================================================ dnl Checks for required headers and functions dnl dnl Version: 20230206 dnl Function to detect if libfsntfs dependencies are available AC_DEFUN([AX_LIBFSNTFS_CHECK_LOCAL], [dnl Headers included in libfsntfs/libfsntfs_name.c AC_CHECK_HEADERS([wctype.h]) dnl Functions used in libfsntfs/libfsntfs_name.c AC_CHECK_FUNCS([towupper]) AS_IF( [test "x$ac_cv_func_towupper" != xyes], [AC_MSG_FAILURE( [Missing function: towupper], [1]) ]) dnl Check for internationalization functions in libfsntfs/libfsntfs_i18n.c AC_CHECK_FUNCS([bindtextdomain]) ]) dnl Function to detect if fsntfstools dependencies are available AC_DEFUN([AX_FSNTFSTOOLS_CHECK_LOCAL], [AC_CHECK_HEADERS([signal.h sys/signal.h unistd.h]) AC_CHECK_FUNCS([close getopt setvbuf]) AS_IF( [test "x$ac_cv_func_close" != xyes], [AC_MSG_FAILURE( [Missing function: close], [1]) ]) dnl Headers included in fsntfstools/fsntfsmount.c AC_CHECK_HEADERS([errno.h sys/time.h]) dnl Functions included in fsntfstools/mount_file_system.c and fsntfstools/mount_file_entry.c AS_IF( [test "x$ac_cv_enable_winapi" = xno], [AC_CHECK_FUNCS([clock_gettime getegid geteuid time]) ]) ]) dnl Function to check if DLL support is needed AC_DEFUN([AX_LIBFSNTFS_CHECK_DLL_SUPPORT], [AS_IF( [test "x$enable_shared" = xyes && test "x$ac_cv_enable_static_executables" = xno], [AS_CASE( [$host], [*cygwin* | *mingw* | *msys*], [AC_DEFINE( [HAVE_DLLMAIN], [1], [Define to 1 to enable the DllMain function.]) AC_SUBST( [HAVE_DLLMAIN], [1]) AC_SUBST( [LIBFSNTFS_DLL_EXPORT], ["-DLIBFSNTFS_DLL_EXPORT"]) AC_SUBST( [LIBFSNTFS_DLL_IMPORT], ["-DLIBFSNTFS_DLL_IMPORT"]) ]) ]) ]) ================================================ FILE: appveyor.yml ================================================ environment: nuget_token: secure: xFlOodfYttki8HxA1hdhVhQ2lkVbj1EA1FxP9T1il2MUsBfH1rPEbTZy+etaMTD8 matrix: - TARGET: vs2008 BUILD_ENVIRONMENT: msbuild APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 VisualStudioVersion: 9.0 platform: Win32 configuration: Release PYTHON_PATH: "C:\\Python37" - TARGET: vs2010 BUILD_ENVIRONMENT: msbuild APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 VisualStudioVersion: 10.0 platform: Win32 configuration: Release PYTHON_PATH: "C:\\Python37" - TARGET: vs2012 BUILD_ENVIRONMENT: msbuild APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 VisualStudioVersion: 11.0 platform: Win32 configuration: Release PYTHON_PATH: "C:\\Python37" - TARGET: vs2013 BUILD_ENVIRONMENT: msbuild APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 VisualStudioVersion: 12.0 platform: Win32 configuration: Release PYTHON_PATH: "C:\\Python37" - TARGET: vs2015 BUILD_ENVIRONMENT: msbuild APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 VisualStudioVersion: 14.0 platform: Win32 configuration: Release PYTHON_PATH: "C:\\Python38" - TARGET: vs2017 BUILD_ENVIRONMENT: msbuild APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 VisualStudioVersion: 15.0 platform: Win32 configuration: Release PYTHON_PATH: "C:\\Python38" - TARGET: vs2019 BUILD_ENVIRONMENT: msbuild APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 VisualStudioVersion: 16.0 platform: Win32 configuration: Release PYTHON_PATH: "C:\\Python311" - TARGET: vs2022 BUILD_ENVIRONMENT: msbuild APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 VisualStudioVersion: 17.0 platform: Win32 configuration: Release PYTHON_PATH: "C:\\Python311" - TARGET: vs2022-vsdebug BUILD_ENVIRONMENT: msbuild APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 VisualStudioVersion: 17.0 platform: Win32 configuration: VSDebug PYTHON_PATH: "C:\\Python311" - TARGET: vs2022-x64 BUILD_ENVIRONMENT: msbuild APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 VisualStudioVersion: 17.0 platform: x64 configuration: Release PYTHON_PATH: "C:\\Python311" - TARGET: vs2022-python BUILD_ENVIRONMENT: msbuild APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 VisualStudioVersion: 17.0 platform: x64 configuration: Release PYTHON_PATH: "C:\\Python311-x64" - TARGET: vs2022-nuget BUILD_ENVIRONMENT: msbuild APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 VisualStudioVersion: 17.0 configuration: Release PYTHON_PATH: "C:\\Python311" - TARGET: macos-x64-clang BUILD_ENVIRONMENT: xcode APPVEYOR_BUILD_WORKER_IMAGE: macos-sonoma HOMEBREW_NO_INSTALL_CLEANUP: 1 CC: clang CFLAGS: "-I/usr/local/include" LDFLAGS: "-L/usr/local/lib" CONFIGURE_OPTIONS: "" - TARGET: macos-x64-gcc BUILD_ENVIRONMENT: xcode APPVEYOR_BUILD_WORKER_IMAGE: macos-sonoma HOMEBREW_NO_INSTALL_CLEANUP: 1 CC: gcc CFLAGS: "-I/usr/local/include" LDFLAGS: "-L/usr/local/lib" CONFIGURE_OPTIONS: "" - TARGET: macos-x64-gcc-python BUILD_ENVIRONMENT: xcode APPVEYOR_BUILD_WORKER_IMAGE: macos-sonoma PYTHON: "/usr/local/opt/python@3.11/bin/python3" PYTHON_CONFIG: "/usr/local/opt/python@3.11/bin/python3-config" HOMEBREW_NO_INSTALL_CLEANUP: 1 CC: gcc CFLAGS: "-I/usr/local/include" LDFLAGS: "-L/usr/local/lib" CONFIGURE_OPTIONS: "--enable-python" - TARGET: macos-pkgbuild BUILD_ENVIRONMENT: xcode APPVEYOR_BUILD_WORKER_IMAGE: macos-sonoma PYTHON: "/usr/local/opt/python@3.11/bin/python3" PYTHON_CONFIG: "/usr/local/opt/python@3.11/bin/python3-config" HOMEBREW_NO_INSTALL_CLEANUP: 1 CC: gcc CFLAGS: "-I/usr/local/include" LDFLAGS: "-L/usr/local/lib" CONFIGURE_OPTIONS: "--disable-dependency-tracking --prefix=/usr/local --enable-python --with-pyprefix" - TARGET: cygwin64-gcc BUILD_ENVIRONMENT: cygwin64 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 CONFIGURE_OPTIONS: "" - TARGET: cygwin64-gcc-no-optimization BUILD_ENVIRONMENT: cygwin64 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 CONFIGURE_OPTIONS: "--enable-shared=no" CFLAGS: "--coverage -O0" CPPFLAGS: "-DOPTIMIZATION_DISABLED" LDFLAGS: "--coverage" - TARGET: cygwin64-gcc-python BUILD_ENVIRONMENT: cygwin64 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 CONFIGURE_OPTIONS: "--enable-python" - TARGET: cygwin64-gcc-static-executables BUILD_ENVIRONMENT: cygwin64 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 CONFIGURE_OPTIONS: "--enable-static-executables --with-libfuse=no" - TARGET: mingw-w64-gcc BUILD_ENVIRONMENT: mingw-w64 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 CONFIGURE_OPTIONS: "" - TARGET: mingw-w64-gcc-no-optimization BUILD_ENVIRONMENT: mingw-w64 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 CONFIGURE_OPTIONS: "--enable-shared=no" CFLAGS: "--coverage -O0" CPPFLAGS: "-DOPTIMIZATION_DISABLED" LDFLAGS: "--coverage" - TARGET: mingw-w64-gcc-python BUILD_ENVIRONMENT: mingw-w64 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 CONFIGURE_OPTIONS: "--enable-python" - TARGET: mingw-w64-gcc-static-executables BUILD_ENVIRONMENT: mingw-w64 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 CONFIGURE_OPTIONS: "--enable-static-executables" matrix: allow_failures: - TARGET: mingw-w64-gcc-python install: - cmd: if [%BUILD_ENVIRONMENT%]==[msbuild] ( git clone https://github.com/libyal/vstools.git ..\vstools ) - ps: If (($env:BUILD_ENVIRONMENT -eq "msbuild") -And (Test-Path ".\synctestdata.ps1")) { .\synctestdata.ps1 } - sh: if ( test ${BUILD_ENVIRONMENT} = "xcode" ) && test -f "./synctestdata.sh"; then ./synctestdata.sh; fi - ps: If ($env:BUILD_ENVIRONMENT -eq "msbuild") { If ( ( "vs2008", "vs2010", "vs2012", "vs2013", "vs2015" ).Contains( $env:TARGET ) ) { .\syncdokan.ps1 -UseLegacyVersion } Else { .\syncdokan.ps1 } } - cmd: if [%TARGET%]==[vs2010] ( pushd ..\dokan && set PYTHONPATH=..\vstools && C:\Python37\python.exe ..\vstools\vstools\scripts\msvscpp_convert.py --no-python-dll --output-format 2010 msvscpp\dokan.sln && rd /q /s msvscpp && ren vs2010 msvscpp && popd ) - cmd: if [%TARGET%]==[vs2012] ( pushd ..\dokan && set PYTHONPATH=..\vstools && C:\Python37\python.exe ..\vstools\vstools\scripts\msvscpp_convert.py --no-python-dll --extend-with-x64 --output-format 2012 msvscpp\dokan.sln && rd /q /s msvscpp && ren vs2012 msvscpp && popd ) - cmd: if [%TARGET%]==[vs2013] ( pushd ..\dokan && set PYTHONPATH=..\vstools && C:\Python37\python.exe ..\vstools\vstools\scripts\msvscpp_convert.py --output-format 2013 msvscpp\dokan.sln && rd /q /s msvscpp && ren vs2013 msvscpp && popd ) - cmd: if [%TARGET%]==[vs2015] ( pushd ..\dokan && set PYTHONPATH=..\vstools && C:\Python37\python.exe ..\vstools\vstools\scripts\msvscpp_convert.py --output-format 2015 msvscpp\dokan.sln && rd /q /s msvscpp && ren vs2015 msvscpp && popd ) - ps: If ($env:BUILD_ENVIRONMENT -eq "msbuild") { If ( ( "vs2008", "vs2010", "vs2012", "vs2013", "vs2015" ).Contains( $env:TARGET ) ) { .\builddokan.ps1 -UseLegacyVersion } Else { $Configuration = $env:CONFIGURATION; If (${Configuration} -eq "VSDebug") { $Configuration = "Debug" } .\builddokan.ps1 -Configuration ${Configuration} -Platform "Win32"; .\builddokan.ps1 -Configuration ${Configuration} -Platform "x64"; } } - sh: if test ${BUILD_ENVIRONMENT} = "xcode"; then brew untap homebrew/homebrew-cask-versions && brew update -q; fi - sh: if test ${BUILD_ENVIRONMENT} = "xcode"; then brew install -q autoconf automake gettext gnu-sed libtool macfuse openssl pkg-config || true; fi - ps: If ($env:BUILD_ENVIRONMENT -eq "cygwin64") { (New-Object Net.WebClient).DownloadFile("https://cygwin.com/setup-x86_64.exe", "C:\\cygwin64\\setup-x86_64.exe") } - cmd: if [%BUILD_ENVIRONMENT%]==[cygwin64] ( C:\cygwin64\setup-x86_64.exe -qgnNdO -l C:\cygwin64\var\cache\setup -R c:\cygwin64 -s http://cygwin.mirror.constant.com -P cygfuse -P gettext-devel -P libssl-devel -P python3-devel -P wget -P zlib-devel ) - cmd: if [%BUILD_ENVIRONMENT%]==[mingw-w64] ( C:\msys64\usr\bin\pacman -S --noconfirm --needed autoconf automake gettext-devel libtool make mingw-w64-x86_64-gcc mingw-w64-x86_64-python3 pkg-config ) - ps: If ( ( "cygwin64-gcc-no-optimization", "mingw-w64-gcc-no-optimization" ).Contains( $env:TARGET ) ) { $ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest -Uri https://uploader.codecov.io/latest/windows/codecov.exe -Outfile ..\codecov.exe } build_script: - ps: If ($env:BUILD_ENVIRONMENT -eq "msbuild") { .\synclibs.ps1; .\autogen.ps1 } - ps: If ($env:TARGET -eq "vs2008") { .\build.ps1 -VisualStudioVersion 2008 -PythonPath $env:PYTHON_PATH -VSToolsOptions "--no-python-dll" } - ps: If ( ( "vs2010", "vs2012", "vs2013", "vs2015" ).Contains( $env:TARGET ) ) { .\build.ps1 -VisualStudioVersion $env:TARGET.Substring(2, 4) -Configuration $env:CONFIGURATION -Platform $env:PLATFORM -PythonPath $env:PYTHON_PATH -VSToolsOptions "--extend-with-x64 --no-python-dll" } - ps: If ( ( "vs2017", "vs2019", "vs2022", "vs2022-vsdebug", "vs2022-x64" ).Contains( $env:TARGET ) ) { .\build.ps1 -VisualStudioVersion $env:TARGET.Substring(2, 4) -Configuration $env:CONFIGURATION -Platform $env:PLATFORM -PythonPath $env:PYTHON_PATH -VSToolsOptions "--extend-with-x64 --no-python-dll --with-dokany" } - ps: If ($env:TARGET -eq "vs2022-python") { .\build.ps1 -VisualStudioVersion $env:TARGET.Substring(2, 4) -Configuration $env:CONFIGURATION -Platform $env:PLATFORM -PythonPath $env:PYTHON_PATH -VSToolsOptions "--extend-with-x64 --python-path $env:PYTHON_PATH --with-dokany" } - ps: If ($env:TARGET -eq "vs2022-nuget") { .\build.ps1 -VisualStudioVersion $env:TARGET.Substring(2, 4) -Configuration $env:CONFIGURATION -Platform Win32 -PythonPath $env:PYTHON_PATH -VSToolsOptions "--extend-with-x64 --no-python-dll --with-dokany"; .\build.ps1 -VisualStudioVersion $env:TARGET.Substring(2, 4) -Configuration $env:CONFIGURATION -Platform x64 -PythonPath $env:PYTHON_PATH -VSToolsOptions "--extend-with-x64 --no-python-dll --with-dokany" } - cmd: if [%TARGET%]==[vs2022-nuget] ( move msvscpp vs2008 && move vs2022 msvscpp && nuget pack libfsntfs.nuspec ) - sh: if test ${BUILD_ENVIRONMENT} = "xcode"; then export PATH="/usr/local/opt/gettext/bin:$PATH"; export SED="/usr/local/bin/gsed"; tests/build.sh ${CONFIGURE_OPTIONS}; fi - cmd: if [%BUILD_ENVIRONMENT%]==[cygwin64] ( xcopy /i /q /s C:\projects\libfsntfs C:\cygwin64\home\appveyor\libfsntfs && C:\cygwin64\bin\bash -e -l -c "cd libfsntfs && wget -q 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' -O './config.guess' && wget -q 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' -O './config.sub'" && C:\cygwin64\bin\bash -e -l -c "cd libfsntfs && tests/build.sh ${CONFIGURE_OPTIONS}" ) - cmd: if [%BUILD_ENVIRONMENT%]==[mingw-w64] ( xcopy /i /q /s C:\projects\libfsntfs C:\msys64\home\appveyor\libfsntfs && C:\msys64\usr\bin\bash -e -l -c "cd libfsntfs && tests/build.sh ${CONFIGURE_OPTIONS}" ) test_script: - cmd: rem Run tests - ps: If ($env:BUILD_ENVIRONMENT -eq "msbuild") { .\runtests.ps1 } - sh: if test ${BUILD_ENVIRONMENT} = "xcode" && test ${TARGET} != "macos-pkgbuild"; then tests/runtests.sh; fi - sh: if test ${TARGET} = "macos-pkgbuild"; then tests/pkgbuild.sh; fi - cmd: if [%BUILD_ENVIRONMENT%]==[cygwin64] ( C:\cygwin64\bin\bash -l -c "cd libfsntfs && tests/runtests.sh" ) - cmd: if [%BUILD_ENVIRONMENT%]==[mingw-w64] ( C:\msys64\usr\bin\bash -l -c "cd libfsntfs && tests/runtests.sh" ) after_test: - cmd: if [%TARGET%]==[cygwin64-gcc-no-optimization] ( C:\cygwin64\bin\bash -e -l -c "cd libfsntfs && for DIRECTORY in `find . -maxdepth 1 -type d`; do (cd ${DIRECTORY} && find . -maxdepth 1 -name \*.gcno -type f -exec gcov -pb {} \;) done" && C:\projects\codecov.exe -R \cygwin64\home\appveyor\libfsntfs --name %TARGET% ) - cmd: if [%TARGET%]==[mingw-w64-gcc-no-optimization] ( C:\msys64\usr\bin\bash -e -l -c "cd libfsntfs && for DIRECTORY in `find . -maxdepth 1 -type d`; do (cd ${DIRECTORY} && find . -maxdepth 1 -name \*.gcno -type f -exec gcov -pb {} \;) done" && C:\projects\codecov.exe -R \msys64\home\appveyor\libfsntfs --name %TARGET% ) artifacts: - path: \*.nupkg deploy_script: - ps: If ($env:APPVEYOR_REPO_TAG -eq "true" -and $isWindows -and $env:TARGET -eq "vs2022-nuget") { Invoke-Expression "nuget push *.nupkg -NonInteractive -NoSymbols -Source https://api.nuget.org/v3/index.json -ApiKey ${env:NUGET_TOKEN}" } ================================================ FILE: autogen.ps1 ================================================ # Script to generate the necessary files for a msvscpp build # # Version: 20241014 $WinFlex = "..\win_flex_bison\win_flex.exe" $WinBison = "..\win_flex_bison\win_bison.exe" $Library = Get-Content -Path configure.ac | select -skip 3 -first 1 | % { $_ -Replace " \[","" } | % { $_ -Replace "\],","" } $Version = Get-Content -Path configure.ac | select -skip 4 -first 1 | % { $_ -Replace " \[","" } | % { $_ -Replace "\],","" } $Prefix = ${Library}.Substring(3) Get-Content -Path "include\${Library}.h.in" | Out-File -Encoding ascii "include\${Library}.h" Get-Content -Path "include\${Library}\definitions.h.in" | % { $_ -Replace "@VERSION@","${Version}" } | Out-File -Encoding ascii "include\${Library}\definitions.h" Get-Content -Path "include\${Library}\features.h.in" | % { $_ -Replace "@[A-Z0-9_]*@","0" } | Out-File -Encoding ascii "include\${Library}\features.h" Get-Content -Path "include\${Library}\types.h.in" | % { $_ -Replace "@[A-Z0-9_]*@","0" } | Out-File -Encoding ascii "include\${Library}\types.h" Get-Content -Path "common\types.h.in" | % { $_ -Replace "@PACKAGE@","${Library}" } | Out-File -Encoding ascii "common\types.h" Get-Content -Path "${Library}\${Library}_definitions.h.in" | % { $_ -Replace "@VERSION@","${Version}" } | Out-File -Encoding ascii "${Library}\${Library}_definitions.h" Get-Content -Path "${Library}\${Library}.rc.in" | % { $_ -Replace "@VERSION@","${Version}" } | Out-File -Encoding ascii "${Library}\${Library}.rc" If (Test-Path "setup.cfg.in") { Get-Content -Path "setup.cfg.in" | % { $_ -Replace "@VERSION@","${Version}" } | Out-File -Encoding ascii "setup.cfg" } If (Test-Path "${Prefix}.net") { Get-Content -Path "${Prefix}.net\${Prefix}.net.rc.in" | % { $_ -Replace "@VERSION@","${Version}" } | Out-File -Encoding ascii "${Prefix}.net\${Prefix}.net.rc" } $NamePrefix = "" ForEach (${Library} in Get-ChildItem -Directory -Path "lib*") { ForEach (${DirectoryElement} in Get-ChildItem -Path "${Library}\*.l") { $OutputFile = ${DirectoryElement} -Replace ".l$",".c" $NamePrefix = Split-Path -path ${DirectoryElement} -leaf $NamePrefix = ${NamePrefix} -Replace ".l$","_" Write-Host "Running: ${WinFlex} -Cf ${DirectoryElement}" # PowerShell will raise NativeCommandError if win_flex writes to stdout or stderr # therefore 2>&1 is added and the output is stored in a variable. $Output = Invoke-Expression -Command "& '${WinFlex}' -Cf ${DirectoryElement} 2>&1" Write-Host ${Output} # Moving manually since `win_flex -o filename' does not provide the expected behavior. Move-Item "lex.yy.c" ${OutputFile} -force } ForEach (${DirectoryElement} in Get-ChildItem -Path "${Library}\*.y") { $OutputFile = ${DirectoryElement} -Replace ".y$",".c" Write-Host "Running: ${WinBison} -d -v -l -p ${NamePrefix} -o ${OutputFile} ${DirectoryElement}" # PowerShell will raise NativeCommandError if win_bison writes to stdout or stderr # therefore 2>&1 is added and the output is stored in a variable. $Output = Invoke-Expression -Command "& '${WinBison}' -d -v -l -p ${NamePrefix} -o ${OutputFile} ${DirectoryElement} 2>&1" Write-Host ${Output} } } ================================================ FILE: autogen.sh ================================================ #!/bin/sh # Script to generate configure and Makefile using the autotools. # # Version: 20241013 EXIT_SUCCESS=0; EXIT_FAILURE=1; BINDIR=`which aclocal`; BINDIR=`dirname ${BINDIR}`; if ! test -x "${BINDIR}/aclocal" && test "${BINDIR}" != "/usr/bin"; then BINDIR="/usr/bin"; fi if ! test -x "${BINDIR}/aclocal" && test "${BINDIR}" != "/usr/local/bin"; then BINDIR="/usr/local/bin"; fi if ! test -x "${BINDIR}/aclocal" && test "${BINDIR}" != "/opt/local/bin"; then # Default location of MacPorts installed binaries. BINDIR="/opt/local/bin"; fi if ! test -x "${BINDIR}/aclocal" && test "${BINDIR}" != "/opt/homebrew/bin"; then # Default location of Homebrew installed binaries. BINDIR="/opt/homebrew/bin"; fi if ! test -x "${BINDIR}/aclocal" && test "${BINDIR}" != "/mingw32/bin"; then # Default location of 32-bit MSYS2-MinGW installed binaries. BINDIR="/mingw32/bin"; fi if ! test -x "${BINDIR}/aclocal" && test "${BINDIR}" != "/mingw64/bin"; then # Default location of 64-bit MSYS2-MinGW installed binaries. BINDIR="/mingw64/bin"; fi if ! test -x "${BINDIR}/aclocal"; then echo "Unable to find autotools"; exit ${EXIT_FAILURE}; fi ACLOCAL="${BINDIR}/aclocal"; AUTOCONF="${BINDIR}/autoconf"; AUTOHEADER="${BINDIR}/autoheader"; AUTOMAKE="${BINDIR}/automake"; AUTOPOINT="${BINDIR}/autopoint"; AUTORECONF="${BINDIR}/autoreconf"; LIBTOOLIZE="${BINDIR}/libtoolize"; PKGCONFIG="${BINDIR}/pkg-config"; if test "${OSTYPE}" = "msys"; then # Work-around for autopoint failing to detect gettext version # using func_trace (which is not available) on MSYS by writing # the gettext version to intl/VERSION. if ! test -d intl; then mkdir intl; fi GETTEXT_VERSION=`gettext --version | head -n1 | sed 's/^.* //'`; echo "gettext-${GETTEXT_VERSION}" > intl/VERSION; elif ! test -x "${PKGCONFIG}"; then if test "${BINDIR}" != "/usr/bin"; then # On OpenBSD most of the autotools are located in # /usr/local/bin while pkg-config is located in /usr/bin PKGCONFIG="/usr/bin/pkg-config"; fi if ! test -x "${PKGCONFIG}"; then echo "Unable to find: pkg-config"; exit ${EXIT_FAILURE}; fi fi if test -x "${AUTORECONF}"; then ${AUTORECONF} --force --install if test $? -ne 0; then exit $?; fi else if ! test -x "${ACLOCAL}"; then echo "Unable to find: aclocal"; exit ${EXIT_FAILURE}; fi if ! test -x "${AUTOCONF}"; then echo "Unable to find: autoconf"; exit ${EXIT_FAILURE}; fi if ! test -x "${AUTOHEADER}"; then echo "Unable to find: autoheader"; exit ${EXIT_FAILURE}; fi if ! test -x "${AUTOMAKE}"; then echo "Unable to find: automake"; exit ${EXIT_FAILURE}; fi if ! test -x "${AUTOPOINT}"; then echo "Unable to find: autopoint"; exit ${EXIT_FAILURE}; fi if ! test -x "${LIBTOOLIZE}"; then echo "Unable to find: libtoolize"; exit ${EXIT_FAILURE}; fi ${AUTOPOINT} --force; if test $? -ne 0; then exit $?; fi ${ACLOCAL} --force --install -I m4; if test $? -ne 0; then exit $?; fi ${LIBTOOLIZE} --force; if test $? -ne 0; then exit $?; fi ${AUTOHEADER} --force; if test $? -ne 0; then exit $?; fi ${AUTOCONF} --force; if test $? -ne 0; then exit $?; fi ${AUTOMAKE} --force --add-missing; if test $? -ne 0; then exit $?; fi fi exit ${EXIT_SUCCESS}; ================================================ FILE: build.ps1 ================================================ # Script that builds libfsntfs # # Version: 20251125 Param ( [string]$Configuration = ${Env:Configuration}, [string]$Platform = ${Env:Platform}, [string]$PlatformToolset = "", [string]$PythonPath = "C:\Python311", [string]$VisualStudioVersion = "", [string]$VSToolsOptions = "--extend-with-x64", [string]$VSToolsPath = "..\vstools" ) $ExitSuccess = 0 $ExitFailure = 1 $Python = "${PythonPath}\python.exe" $Git = "git" $GitUrl = "https://github.com/libyal/vstools.git" $MSVSCppConvert = "${VSToolsPath}\vstools\scripts\msvscpp_convert.py" If (-Not (Test-Path $Python)) { Write-Host "Missing Python: ${Python}" -foreground Red Exit ${ExitFailure} } If (-Not (Test-Path ${VSToolsPath})) { # PowerShell will raise NativeCommandError if git writes to stdout or stderr # therefore 2>&1 is added and the output is stored in a variable. $Output = Invoke-Expression -Command "${Git} clone ${GitUrl} ${VSToolsPath} 2>&1" | %{ "$_" } } Else { Push-Location "${VSToolsPath}" Try { # Make sure vstools are up to date. $Output = Invoke-Expression -Command "${Git} pull 2>&1" | %{ "$_" } } Finally { Pop-Location } } If (-Not (Test-Path ${MSVSCppConvert})) { Write-Host "Missing msvscpp_convert.py: ${MSVSCppConvert}" -foreground Red Exit ${ExitFailure} } If (-Not ${VisualStudioVersion}) { $VisualStudioVersion = "2022" Write-Host "Visual Studio version not set defauting to: ${VisualStudioVersion}" -foreground Red } If ((${VisualStudioVersion} -ne "2008") -And (${VisualStudioVersion} -ne "2010") -And (${VisualStudioVersion} -ne "2012") -And (${VisualStudioVersion} -ne "2013") -And (${VisualStudioVersion} -ne "2015") -And (${VisualStudioVersion} -ne "2017") -And (${VisualStudioVersion} -ne "2019") -And (${VisualStudioVersion} -ne "2022")) { Write-Host "Unsupported Visual Studio version: ${VisualStudioVersion}" -foreground Red Exit ${ExitFailure} } $MSBuild = "" If (${VisualStudioVersion} -eq "2008") { $MSBuild = "C:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe" } ElseIf ((${VisualStudioVersion} -eq "2010") -Or (${VisualStudioVersion} -eq "2012")) { $MSBuild = "C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" } ElseIf (${VisualStudioVersion} -eq "2013") { $MSBuild = "C:\Program Files (x86)\MSBuild\12.0\Bin\MSBuild.exe" } ElseIf (${VisualStudioVersion} -eq "2015") { $MSBuild = "C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" } ElseIf (${VisualStudioVersion} -eq "2017") { $Results = Get-ChildItem -Path "C:\Program Files\Microsoft Visual Studio\${VisualStudioVersion}\*\MSBuild\15.0\Bin\MSBuild.exe" -Recurse -ErrorAction SilentlyContinue -Force If ($Results.Count -eq 0) { $Results = Get-ChildItem -Path "C:\Program Files (x86)\Microsoft Visual Studio\${VisualStudioVersion}\*\MSBuild\15.0\Bin\MSBuild.exe" -Recurse -ErrorAction SilentlyContinue -Force } If ($Results.Count -gt 0) { $MSBuild = $Results[0].FullName } } ElseIf (${VisualStudioVersion} -eq "2019" -Or ${VisualStudioVersion} -eq "2022") { $Results = Get-ChildItem -Path "C:\Program Files\Microsoft Visual Studio\${VisualStudioVersion}\*\MSBuild\Current\Bin\MSBuild.exe" -Recurse -ErrorAction SilentlyContinue -Force If ($Results.Count -eq 0) { $Results = Get-ChildItem -Path "C:\Program Files (x86)\Microsoft Visual Studio\${VisualStudioVersion}\*\MSBuild\Current\Bin\MSBuild.exe" -Recurse -ErrorAction SilentlyContinue -Force } If ($Results.Count -gt 0) { $MSBuild = $Results[0].FullName } } If (-Not ${MSBuild}) { Write-Host "Unable to determine path to msbuild.exe" -foreground Red Exit ${ExitFailure} } ElseIf (-Not (Test-Path ${MSBuild})) { Write-Host "Missing msbuild.exe: ${MSBuild}" -foreground Red Exit ${ExitFailure} } If (${VisualStudioVersion} -eq "2008") { $VSSolutionPath = "msvscpp" } Else { $VSSolutionPath = "vs${VisualStudioVersion}" If (-Not (Test-Path "${VSSolutionPath}")) { ${Env:PYTHONPATH} = ${VSToolsPath} Invoke-Expression -Command "& '${Python}' ${MSVSCppConvert} --output-format ${VisualStudioVersion} ${VSToolsOptions} msvscpp\libfsntfs.sln 2>&1" | %{ "$_" } } } $VSSolutionFile = "${VSSolutionPath}\libfsntfs.sln" If (-Not (Test-Path "${VSSolutionFile}")) { Write-Host "Missing Visual Studio ${VisualStudioVersion} solution file: ${VSSolutionFile}" -foreground Red Exit ${ExitFailure} } If (-Not ${Configuration}) { $Configuration = "Release" Write-Host "Configuration not set defauting to: ${Configuration}" } If (-Not ${Platform}) { $Platform = "Win32" Write-Host "Platform not set defauting to: ${Platform}" } $PlatformToolset = "" If (-Not ${PlatformToolset}) { If (${VisualStudioVersion} -eq "2015") { $PlatformToolset = "v140" } ElseIf (${VisualStudioVersion} -eq "2017") { $PlatformToolset = "v141" } ElseIf (${VisualStudioVersion} -eq "2019") { $PlatformToolset = "v142" } ElseIf (${VisualStudioVersion} -eq "2022") { $PlatformToolset = "v143" } Write-Host "PlatformToolset not set defauting to: ${PlatformToolset}" } $MSBuildOptions = "/verbosity:quiet /target:Build /property:Configuration=${Configuration},Platform=${Platform}" If (${PlatformToolset}) { $MSBuildOptions = "${MSBuildOptions} /property:PlatformToolset=${PlatformToolset}" } If (${Env:APPVEYOR} -eq "True") { Invoke-Expression -Command "& '${MSBuild}' ${MSBuildOptions} ${VSSolutionFile} /logger:'C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll' 2>&1" | %{ "$_" } } Else { Invoke-Expression -Command "& '${MSBuild}' ${MSBuildOptions} ${VSSolutionFile} 2>&1" | %{ "$_" } } Exit ${ExitSuccess} ================================================ FILE: builddokan.ps1 ================================================ # Script that builds dokan # # Version: 20180322 Param ( [string]$Configuration = ${Env:Configuration}, [string]$Platform = ${Env:Platform}, [switch]$UseLegacyVersion = $false ) If (-not ${Configuration}) { $Configuration = "Release" } If (-not ${Platform}) { $Platform = "Win32" } If (${Env:AppVeyor} -eq "True") { $MSBuild = "MSBuild.exe" } ElseIf (${Env:VisualStudioVersion} -eq "15.0") { $MSBuild = "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\amd64\MSBuild.exe" } ElseIf (${Env:VisualStudioVersion} -eq "9.0") { $MSBuild = "C:\\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe" } Else { $MSBuild = "C:\\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" } $MSBuildOptions = "/verbosity:quiet /target:Build /property:Configuration=${Configuration},Platform=${Platform}" If ($UseLegacyVersion) { $DokanPath = "../dokan" $ProjectFile = "msvscpp\dokan.sln" } Else { $DokanPath = "../dokany" $ProjectFile = "dokan\dokan.vcxproj" } Push-Location ${DokanPath} Try { Write-Host "${MSBuild} ${MSBuildOptions} ${ProjectFile}" Invoke-Expression -Command "& '${MSBuild}' ${MSBuildOptions} ${ProjectFile}" } Finally { Pop-Location } ================================================ FILE: common/Makefile.am ================================================ AM_CPPFLAGS = \ -I../include -I$(top_srcdir)/include EXTRA_DIST = \ byte_stream.h \ common.h \ config.h \ config_borlandc.h \ config_msc.h \ config_winapi.h \ file_stream.h \ memory.h \ narrow_string.h \ system_string.h \ types.h \ types.h.in \ wide_string.h DISTCLEANFILES = \ config.h \ types.h \ Makefile \ Makefile.in ================================================ FILE: common/byte_stream.h ================================================ /* * Byte stream functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _BYTE_STREAM_H ) #define _BYTE_STREAM_H #include "common.h" #include "types.h" #if defined( __cplusplus ) extern "C" { #endif #define _BYTE_STREAM_HOST_IS_ENDIAN_BIG ( *((uint32_t *) "\x01\x02\x03\x04" ) == 0x01020304 ) #define _BYTE_STREAM_HOST_IS_ENDIAN_LITTLE ( *((uint32_t *) "\x01\x02\x03\x04" ) == 0x04030201 ) #define _BYTE_STREAM_HOST_IS_ENDIAN_MIDDLE ( *((uint32_t *) "\x01\x02\x03\x04" ) == 0x02010403 ) #define _BYTE_STREAM_ENDIAN_BIG (uint8_t) 'b' #define _BYTE_STREAM_ENDIAN_LITTLE (uint8_t) 'l' #define _BYTE_STREAM_ENDIAN_MIDDLE (uint8_t) 'm' typedef union byte_stream_float32 { float floating_point; uint32_t integer; } byte_stream_float32_t; typedef union byte_stream_float64 { double floating_point; uint64_t integer; } byte_stream_float64_t; #define byte_stream_copy_to_uint16_big_endian( byte_stream, value ) \ ( value ) = ( byte_stream )[ 0 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 1 ]; #define byte_stream_copy_to_uint16_little_endian( byte_stream, value ) \ ( value ) = ( byte_stream )[ 1 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 0 ]; #define byte_stream_copy_to_uint24_big_endian( byte_stream, value ) \ ( value ) = ( byte_stream )[ 0 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 1 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 2 ]; #define byte_stream_copy_to_uint24_little_endian( byte_stream, value ) \ ( value ) = ( byte_stream )[ 2 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 1 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 0 ]; #define byte_stream_copy_to_uint32_big_endian( byte_stream, value ) \ ( value ) = ( byte_stream )[ 0 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 1 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 2 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 3 ]; #define byte_stream_copy_to_uint32_little_endian( byte_stream, value ) \ ( value ) = ( byte_stream )[ 3 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 2 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 1 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 0 ]; #define byte_stream_copy_to_uint48_big_endian( byte_stream, value ) \ ( value ) = ( byte_stream )[ 0 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 1 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 2 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 3 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 4 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 5 ]; #define byte_stream_copy_to_uint48_little_endian( byte_stream, value ) \ ( value ) |= ( byte_stream )[ 5 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 4 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 3 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 2 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 1 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 0 ]; #define byte_stream_copy_to_uint64_big_endian( byte_stream, value ) \ ( value ) = ( byte_stream )[ 0 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 1 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 2 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 3 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 4 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 5 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 6 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 7 ]; #define byte_stream_copy_to_uint64_little_endian( byte_stream, value ) \ ( value ) = ( byte_stream )[ 7 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 6 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 5 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 4 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 3 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 2 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 1 ]; \ ( value ) <<= 8; \ ( value ) |= ( byte_stream )[ 0 ]; #define byte_stream_copy_from_uint16_big_endian( byte_stream, value ) \ ( byte_stream )[ 0 ] = (uint8_t) ( ( ( value ) >> 8 ) & 0x0ff ); \ ( byte_stream )[ 1 ] = (uint8_t) ( ( value ) & 0x0ff ) #define byte_stream_copy_from_uint16_little_endian( byte_stream, value ) \ ( byte_stream )[ 1 ] = (uint8_t) ( ( ( value ) >> 8 ) & 0x0ff ); \ ( byte_stream )[ 0 ] = (uint8_t) ( ( value ) & 0x0ff ) #define byte_stream_copy_from_uint24_big_endian( byte_stream, value ) \ ( byte_stream )[ 0 ] = (uint8_t) ( ( ( value ) >> 16 ) & 0x0ff ); \ ( byte_stream )[ 1 ] = (uint8_t) ( ( ( value ) >> 8 ) & 0x0ff ); \ ( byte_stream )[ 2 ] = (uint8_t) ( ( value ) & 0x0ff ) #define byte_stream_copy_from_uint24_little_endian( byte_stream, value ) \ ( byte_stream )[ 2 ] = (uint8_t) ( ( ( value ) >> 16 ) & 0x0ff ); \ ( byte_stream )[ 1 ] = (uint8_t) ( ( ( value ) >> 8 ) & 0x0ff ); \ ( byte_stream )[ 0 ] = (uint8_t) ( ( value ) & 0x0ff ) #define byte_stream_copy_from_uint32_big_endian( byte_stream, value ) \ ( byte_stream )[ 0 ] = (uint8_t) ( ( ( value ) >> 24 ) & 0x0ff ); \ ( byte_stream )[ 1 ] = (uint8_t) ( ( ( value ) >> 16 ) & 0x0ff ); \ ( byte_stream )[ 2 ] = (uint8_t) ( ( ( value ) >> 8 ) & 0x0ff ); \ ( byte_stream )[ 3 ] = (uint8_t) ( ( value ) & 0x0ff ) #define byte_stream_copy_from_uint32_little_endian( byte_stream, value ) \ ( byte_stream )[ 3 ] = (uint8_t) ( ( ( value ) >> 24 ) & 0x0ff ); \ ( byte_stream )[ 2 ] = (uint8_t) ( ( ( value ) >> 16 ) & 0x0ff ); \ ( byte_stream )[ 1 ] = (uint8_t) ( ( ( value ) >> 8 ) & 0x0ff ); \ ( byte_stream )[ 0 ] = (uint8_t) ( ( value ) & 0x0ff ) #define byte_stream_copy_from_uint48_big_endian( byte_stream, value ) \ ( byte_stream )[ 0 ] = (uint8_t) ( ( ( value ) >> 40 ) & 0x0ff ); \ ( byte_stream )[ 1 ] = (uint8_t) ( ( ( value ) >> 32 ) & 0x0ff ); \ ( byte_stream )[ 2 ] = (uint8_t) ( ( ( value ) >> 24 ) & 0x0ff ); \ ( byte_stream )[ 3 ] = (uint8_t) ( ( ( value ) >> 16 ) & 0x0ff ); \ ( byte_stream )[ 4 ] = (uint8_t) ( ( ( value ) >> 8 ) & 0x0ff ); \ ( byte_stream )[ 5 ] = (uint8_t) ( ( value ) & 0x0ff ) #define byte_stream_copy_from_uint48_little_endian( byte_stream, value ) \ ( byte_stream )[ 5 ] = (uint8_t) ( ( ( value ) >> 40 ) & 0x0ff ); \ ( byte_stream )[ 4 ] = (uint8_t) ( ( ( value ) >> 32 ) & 0x0ff ); \ ( byte_stream )[ 3 ] = (uint8_t) ( ( ( value ) >> 24 ) & 0x0ff ); \ ( byte_stream )[ 2 ] = (uint8_t) ( ( ( value ) >> 16 ) & 0x0ff ); \ ( byte_stream )[ 1 ] = (uint8_t) ( ( ( value ) >> 8 ) & 0x0ff ); \ ( byte_stream )[ 0 ] = (uint8_t) ( ( value ) & 0x0ff ) #define byte_stream_copy_from_uint64_big_endian( byte_stream, value ) \ ( byte_stream )[ 0 ] = (uint8_t) ( ( ( value ) >> 56 ) & 0x0ff ); \ ( byte_stream )[ 1 ] = (uint8_t) ( ( ( value ) >> 48 ) & 0x0ff ); \ ( byte_stream )[ 2 ] = (uint8_t) ( ( ( value ) >> 40 ) & 0x0ff ); \ ( byte_stream )[ 3 ] = (uint8_t) ( ( ( value ) >> 32 ) & 0x0ff ); \ ( byte_stream )[ 4 ] = (uint8_t) ( ( ( value ) >> 24 ) & 0x0ff ); \ ( byte_stream )[ 5 ] = (uint8_t) ( ( ( value ) >> 16 ) & 0x0ff ); \ ( byte_stream )[ 6 ] = (uint8_t) ( ( ( value ) >> 8 ) & 0x0ff ); \ ( byte_stream )[ 7 ] = (uint8_t) ( ( value ) & 0x0ff ) #define byte_stream_copy_from_uint64_little_endian( byte_stream, value ) \ ( byte_stream )[ 7 ] = (uint8_t) ( ( ( value ) >> 56 ) & 0x0ff ); \ ( byte_stream )[ 6 ] = (uint8_t) ( ( ( value ) >> 48 ) & 0x0ff ); \ ( byte_stream )[ 5 ] = (uint8_t) ( ( ( value ) >> 40 ) & 0x0ff ); \ ( byte_stream )[ 4 ] = (uint8_t) ( ( ( value ) >> 32 ) & 0x0ff ); \ ( byte_stream )[ 3 ] = (uint8_t) ( ( ( value ) >> 24 ) & 0x0ff ); \ ( byte_stream )[ 2 ] = (uint8_t) ( ( ( value ) >> 16 ) & 0x0ff ); \ ( byte_stream )[ 1 ] = (uint8_t) ( ( ( value ) >> 8 ) & 0x0ff ); \ ( byte_stream )[ 0 ] = (uint8_t) ( ( value ) & 0x0ff ) #define byte_stream_bit_rotate_left_8bit( byte_stream, number_of_bits ) \ ( ( ( byte_stream ) << ( number_of_bits ) ) | ( ( byte_stream ) >> ( 8 - ( number_of_bits ) ) ) ) #define byte_stream_bit_rotate_right_8bit( byte_stream, number_of_bits ) \ ( ( ( byte_stream ) >> ( number_of_bits ) ) | ( ( byte_stream ) << ( 8 - ( number_of_bits ) ) ) ) #define byte_stream_bit_rotate_left_16bit( byte_stream, number_of_bits ) \ ( ( ( byte_stream ) << ( number_of_bits ) ) | ( ( byte_stream ) >> ( 16 - ( number_of_bits ) ) ) ) #define byte_stream_bit_rotate_right_16bit( byte_stream, number_of_bits ) \ ( ( ( byte_stream ) >> ( number_of_bits ) ) | ( ( byte_stream ) << ( 16 - ( number_of_bits ) ) ) ) #define byte_stream_bit_rotate_left_32bit( byte_stream, number_of_bits ) \ ( ( ( byte_stream ) << ( number_of_bits ) ) | ( ( byte_stream ) >> ( 32 - ( number_of_bits ) ) ) ) #define byte_stream_bit_rotate_right_32bit( byte_stream, number_of_bits ) \ ( ( ( byte_stream ) >> ( number_of_bits ) ) | ( ( byte_stream ) << ( 32 - ( number_of_bits ) ) ) ) #define byte_stream_bit_rotate_left_64bit( byte_stream, number_of_bits ) \ ( ( ( byte_stream ) << ( number_of_bits ) ) | ( ( byte_stream ) >> ( 64 - ( number_of_bits ) ) ) ) #define byte_stream_bit_rotate_right_64bit( byte_stream, number_of_bits ) \ ( ( ( byte_stream ) >> ( number_of_bits ) ) | ( ( byte_stream ) << ( 64 - ( number_of_bits ) ) ) ) #define byte_stream_bit_rotate_left( value, number_of_bits ) \ ( ( ( value ) << ( number_of_bits ) ) | ( ( value ) >> ( ( sizeof( value ) << 3 ) - ( number_of_bits ) ) ) ) #define byte_stream_bit_rotate_right( value, number_of_bits ) \ ( ( ( value ) >> ( number_of_bits ) ) | ( ( value ) << ( ( sizeof( value ) << 3 ) - ( number_of_bits ) ) ) ) #if defined( __cplusplus ) } #endif #endif /* !defined( _BYTE_STREAM_H ) */ ================================================ FILE: common/common.h ================================================ /* * Common include file * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _COMMON_H ) #define _COMMON_H #if defined( HAVE_CONFIG_H ) #include "config.h" #endif /* Include the Borland/CodeGear C++ Builder compiler specific configuration */ #if defined( __BORLANDC__ ) #include "config_borlandc.h" /* Include the Microsoft Visual Studio C++ compiler specific configuration */ #elif defined( _MSC_VER ) #include "config_msc.h" #endif #include "config_winapi.h" #endif /* !defined( _COMMON_H ) */ ================================================ FILE: common/config_borlandc.h ================================================ /* * Configuration for the Borland/CodeGear C++ Builder compiler * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _CONFIG_BORLANDC_H ) #define _CONFIG_BORLANDC_H #endif /* !defined( _CONFIG_BORLANDC_H ) */ ================================================ FILE: common/config_msc.h ================================================ /* * Configuration for the Microsoft Visual Studio C++ compiler * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _CONFIG_MSC_H ) #define _CONFIG_MSC_H /* Disable warning C4127: conditional expression is constant */ #pragma warning( disable : 4127 ) /* Disable warning C4201: nonstandard extension used : nameless struct/union */ #pragma warning( disable : 4201 ) #endif /* !defined( _CONFIG_MSC_H ) */ ================================================ FILE: common/config_winapi.h ================================================ /* * Configuration file for WINAPI * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _CONFIG_WINAPI_H ) #define _CONFIG_WINAPI_H /* Define the earliest supported WINAPI version #define WINVER 0x0501 */ /* If necessary make sure WINAPI is defined */ #if defined( HAVE_WINDOWS_H ) || defined( __BORLANDC__ ) || defined( _MSC_VER ) #include #endif #if defined( WINAPI ) /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "joachim.metz@gmail.com" /* Define the size of the integer for WINAPI */ #if !defined( SIZEOF_INT ) #define SIZEOF_INT 4 #endif /* Define the size of size_t for WINAPI * Do not define when pyconfig.h has been included via python.h */ #if !defined( HAVE_PYCONFIG_H ) #if !defined( SIZEOF_SIZE_T ) #if __WORDSIZE == 64 #define SIZEOF_SIZE_T 8 #else #define SIZEOF_SIZE_T 4 #endif #endif #endif /* !defined( HAVE_PYCONFIG_H ) */ /* Define the size of the wide character for WINAPI */ #if !defined( SIZEOF_WCHAR_T ) #define SIZEOF_WCHAR_T 2 #endif /* Enable the DllMain function */ #define HAVE_DLLMAIN 1 /* Enable verbose output #define HAVE_VERBOSE_OUTPUT 1 */ /* Enable debug output #define HAVE_DEBUG_OUTPUT 1 */ /* Enable both the narrow and wide character functions */ #if !defined( HAVE_WIDE_CHARACTER_TYPE ) #define HAVE_WIDE_CHARACTER_TYPE 1 #endif /* If not controlled by config.h enable multi-thread support */ #if !defined( HAVE_CONFIG_H ) && !defined( HAVE_MULTI_THREAD_SUPPORT ) #define HAVE_MULTI_THREAD_SUPPORT 1 #endif #endif /* defined( WINAPI ) */ #endif /* !defined( _CONFIG_WINAPI_H ) */ ================================================ FILE: common/file_stream.h ================================================ /* * FILE stream functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FILE_STREAM_H ) #define _FILE_STREAM_H #include "common.h" #if defined( HAVE_GLIB_H ) #include #include #endif #include #if defined( __cplusplus ) extern "C" { #endif #define FILE_STREAM_OPEN_APPEND "a" #define FILE_STREAM_OPEN_READ "r" #define FILE_STREAM_OPEN_WRITE "w" #if defined( WINAPI ) #define FILE_STREAM_BINARY_OPEN_APPEND "ab" #define FILE_STREAM_BINARY_OPEN_READ "rb" #define FILE_STREAM_BINARY_OPEN_WRITE "wb" #else #define FILE_STREAM_BINARY_OPEN_APPEND "a" #define FILE_STREAM_BINARY_OPEN_READ "r" #define FILE_STREAM_BINARY_OPEN_WRITE "w" #endif /* narrow character FILE stream open */ #if defined( HAVE_GLIB_H ) #define file_stream_open( filename, mode ) \ g_fopen( filename, mode ) #elif defined( HAVE_FOPEN ) || defined( WINAPI ) #define file_stream_open( filename, mode ) \ fopen( filename, mode ) #endif /* wide character FILE stream open */ #if defined( WINAPI ) #define file_stream_open_wide( filename, mode ) \ _wfopen( filename, mode ) #endif /* FILE stream close */ #if defined( HAVE_FCLOSE ) || defined( WINAPI ) #define file_stream_close( stream ) \ fclose( stream ) #endif /* FILE stream read */ #if defined( HAVE_FREAD ) || defined( WINAPI ) #define file_stream_read( stream, data, size ) \ fread( data, 1, size, stream ) #endif /* FILE stream write */ #if defined( HAVE_FWRITE ) || defined( WINAPI ) #define file_stream_write( stream, data, size ) \ fwrite( data, 1, size, stream ) #endif /* FILE stream seek */ #if defined( WINAPI ) #define file_stream_seek_offset( stream, offset, whence ) \ fseek( stream, offset, whence ) #elif defined( HAVE_FSEEKO ) #define file_stream_seek_offset( stream, offset, whence ) \ fseeko( stream, offset, whence ) #elif defined( HAVE_FSEEKO64 ) #define file_stream_seek_offset( stream, offset, whence ) \ fseeko64( stream, offset, whence ) #endif /* End of FILE stream */ #if defined( HAVE_FEOF ) || defined( WINAPI ) #define file_stream_at_end( stream ) \ feof( stream ) #endif /* Get narrow character string from FILE stream */ #if defined( HAVE_FGETS ) || defined( WINAPI ) #define file_stream_get_string( stream, string, size ) \ fgets( string, size, stream ) #endif /* Get wide characters string from FILE stream */ #if defined( HAVE_FGETWS ) || defined( WINAPI ) #define file_stream_get_string_wide( stream, string, size ) \ fgetws( string, size, stream ) #endif /* Variable arguments formatted print to stream function */ #if defined( HAVE_GLIB_H ) #define file_stream_vfprintf( stream, format, ... ) \ g_vfprintf( stream, format, __VA_ARGS__ ) /* Borland BCC previous to version 5.6.0 cannot handle the macro form: MACRO( ... ) */ #elif defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 ) #define file_stream_vfprintf \ vfprintf #elif defined( HAVE_VFPRINTF ) || defined( WINAPI ) #define file_stream_vfprintf( stream, format, ... ) \ vfprintf( stream, format, __VA_ARGS__ ) #endif #if defined( __cplusplus ) } #endif #endif /* !defined( _FILE_STREAM_H ) */ ================================================ FILE: common/memory.h ================================================ /* * Memory functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _MEMORY_H ) #define _MEMORY_H #include "common.h" #if defined( HAVE_GLIB_H ) #include #endif #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #if defined( HAVE_STRING_H ) || defined( WINAPI ) #include #endif #if defined( __cplusplus ) extern "C" { #endif /* Note that 128 MiB is an arbitrary selected upper limit here */ #define MEMORY_MAXIMUM_ALLOCATION_SIZE \ ( 128 * 1024 * 1024 ) /* Memory allocation */ #if defined( HAVE_GLIB_H ) #define memory_allocate( size ) \ g_malloc( (gsize) size ) #elif defined( WINAPI ) #define memory_allocate( size ) \ HeapAlloc( GetProcessHeap(), 0, (SIZE_T) size ) #elif defined( HAVE_MALLOC ) #define memory_allocate( size ) \ malloc( size ) #endif #define memory_allocate_structure( type ) \ (type *) memory_allocate( sizeof( type ) ) #define memory_allocate_structure_as_value( type ) \ (intptr_t *) memory_allocate( sizeof( type ) ) /* Memory reallocation */ #if defined( HAVE_GLIB_H ) #define memory_reallocate( buffer, size ) \ g_realloc( (gpointer) buffer, (gsize) size ) #elif defined( WINAPI ) /* HeapReAlloc does not allocate empty (NULL) buffers as realloc does */ #define memory_reallocate( buffer, size ) \ ( buffer == NULL ) ? \ HeapAlloc( GetProcessHeap(), 0, (SIZE_T) size ) : \ HeapReAlloc( GetProcessHeap(), 0, (LPVOID) buffer, (SIZE_T) size ) #elif defined( HAVE_REALLOC ) #define memory_reallocate( buffer, size ) \ realloc( (void *) buffer, size ) #endif /* Memory free */ #if defined( HAVE_GLIB_H ) #define memory_free( buffer ) \ g_free( (gpointer) buffer ) #elif defined( WINAPI ) #define memory_free( buffer ) \ ( buffer == NULL ) ? TRUE : HeapFree( GetProcessHeap(), 0, (LPVOID) buffer ) #elif defined( HAVE_FREE ) #define memory_free( buffer ) \ free( (void *) buffer ) #endif /* Memory compare */ #if defined( HAVE_MEMCMP ) || defined( WINAPI ) #define memory_compare( buffer1, buffer2, size ) \ memcmp( (const void *) buffer1, (const void *) buffer2, size ) #endif /* Memory copy */ #if defined( HAVE_MEMCPY ) || defined( WINAPI ) #define memory_copy( destination, source, count ) \ memcpy( (void *) destination, (void *) source, count ) #endif /* Memory set */ #if defined( HAVE_MEMSET ) || defined( WINAPI ) #define memory_set( buffer, value, count ) \ memset( (void *) buffer, (int) value, count ) #endif #if defined( __cplusplus ) } #endif #endif /* !defined( _MEMORY_H ) */ ================================================ FILE: common/narrow_string.h ================================================ /* * Narrow character string functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _NARROW_STRING_H ) #define _NARROW_STRING_H #include "common.h" #include "memory.h" #include "types.h" #if defined( HAVE_GLIB_H ) #include #endif #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #if defined( HAVE_STRING_H ) || defined( WINAPI ) #include #endif #if defined( __cplusplus ) extern "C" { #endif /* String allocation */ #define narrow_string_allocate( size ) \ (char *) memory_allocate( sizeof( char ) * ( size ) ) /* String reallocation */ #define narrow_string_reallocate( string, size ) \ (char *) memory_reallocate( string, ( sizeof( char ) * ( size ) ) ) /* String length */ #if defined( HAVE_STRLEN ) || defined( WINAPI ) #define narrow_string_length( string ) \ strlen( string ) #endif /* String compare */ #if defined( HAVE_MEMCMP ) || defined( WINAPI ) #define narrow_string_compare( string1, string2, size ) \ memcmp( (void *) string1, (void *) string2, size ) #elif defined( HAVE_STRNCMP ) #define narrow_string_compare( string1, string2, size ) \ strncmp( string1, string2, size ) #endif /* Caseless string compare */ #if defined( HAVE_GLIB_H ) #define narrow_string_compare_no_case( string1, string2, size ) \ g_ascii_strncasecmp( string1, string2, size ) #elif defined( _MSC_VER ) #define narrow_string_compare_no_case( string1, string2, size ) \ _strnicmp( string1, string2, size ) #elif ( defined( WINAPI ) && !defined( __CYGWIN__ ) ) || defined( HAVE_STRNICMP ) #define narrow_string_compare_no_case( string1, string2, size ) \ strnicmp( string1, string2, size ) #elif defined( HAVE_STRNCASECMP ) #define narrow_string_compare_no_case( string1, string2, size ) \ strncasecmp( string1, string2, size ) #elif defined( HAVE_STRCASECMP ) #define narrow_string_compare_no_case( string1, string2, size ) \ strcasecmp( string1, string2 ) #endif /* String copy */ #if defined( HAVE_MEMCPY ) || defined( WINAPI ) #define narrow_string_copy( destination, source, size ) \ (char *) memcpy( (void *) destination, (void *) source, size ) #elif defined( HAVE_STRNCPY ) #define narrow_string_copy( destination, source, size ) \ strncpy( destination, source, size ) #endif /* String character search */ #if defined( HAVE_MEMCHR ) || defined( WINAPI ) #define narrow_string_search_character( string, character, size ) \ (char *) memchr( (void *) string, (int) character, size ) #elif defined( HAVE_STRCHR ) #define narrow_string_search_character( string, character, size ) \ strchr( string, (int) character ) #endif /* String reverse character search */ #if defined( HAVE_MEMRCHR ) && ( HAVE_DECL_MEMRCHR == 1 ) #define narrow_string_search_character_reverse( string, character, size ) \ (char *) memrchr( (void *) string, (int) character, size ) #elif defined( HAVE_STRRCHR ) || defined( WINAPI ) /* (void)(size) is used to suppress unused variable warnings */ #define narrow_string_search_character_reverse( string, character, size ) \ strrchr( string, (int) character ); (void)(size) #endif /* String sub-string search */ #if defined( HAVE_STRSTR ) || defined( WINAPI ) #define narrow_string_search_string( string, substring, size ) \ strstr( string, substring ) #endif /* String formatted print (snprintf) */ #if defined( HAVE_GLIB_H ) #define narrow_string_snprintf( target, size, ... ) \ g_snprintf( target, size, __VA_ARGS__ ) #elif defined( _MSC_VER ) #define narrow_string_snprintf( target, size, ... ) \ sprintf_s( target, size, __VA_ARGS__ ) #elif defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 ) #define narrow_string_snprintf \ snprintf #elif defined( HAVE_SNPRINTF ) || defined( WINAPI ) #define narrow_string_snprintf( target, size, ... ) \ snprintf( target, size, __VA_ARGS__ ) #endif /* String input conversion (sscanf) */ #if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 ) #define narrow_string_sscanf \ sscanf #elif defined( HAVE_SSCANF ) || defined( WINAPI ) #define narrow_string_sscanf( string, format, ... ) \ sscanf( string, format, __VA_ARGS__ ) #endif /* Variable arguments formatted print to string function (vsnprintf) */ #if defined( HAVE_GLIB_H ) #define narrow_string_vsnprintf( string, size, format, ... ) \ g_vsnprintf( string, size, format, __VA_ARGS__ ) #elif defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 ) #define narrow_string_vsnprintf \ vsnprintf #elif defined( HAVE_VSNPRINTF ) || defined( WINAPI ) #define narrow_string_vsnprintf( string, size, format, ... ) \ vsnprintf( string, size, format, __VA_ARGS__ ) #endif #if defined( __cplusplus ) } #endif #endif /* !defined( _NARROW_STRING_H ) */ ================================================ FILE: common/system_string.h ================================================ /* * System character string functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _SYSTEM_STRING_H ) #define _SYSTEM_STRING_H #include "common.h" #include "narrow_string.h" #include "types.h" #include "wide_string.h" #if defined( _cplusplus ) extern "C" { #endif #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) #if SIZEOF_WCHAR_T != 2 #error Unsupported wide system character size #endif /* Intermediate version of the macro required * for correct evaluation predefined string */ #define _SYSTEM_STRING_INTERMEDIATE( string ) \ L ## string #define _SYSTEM_STRING( string ) \ _SYSTEM_STRING_INTERMEDIATE( string ) #define system_string_allocate( size ) \ wide_string_allocate( size ) #define system_string_reallocate( string, size ) \ wide_string_reallocate( string, size ) #define system_string_compare( destination, source, size ) \ wide_string_compare( destination, source, size ) #define system_string_compare_no_case( destination, source, size ) \ wide_string_compare_no_case( destination, source, size ) #define system_string_copy( destination, source, size ) \ wide_string_copy( destination, source, size ) #define system_string_length( string ) \ wide_string_length( string ) #define system_string_search_character( string, character, size ) \ wide_string_search_character( string, character, size ) #define system_string_search_character_reverse( string, character, size ) \ wide_string_search_character_reverse( string, character, size ) #define system_string_search_string( string, substring, size ) \ wide_string_search_string( string, substring, size ) #if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 ) #define system_string_sprintf \ wide_string_snwprintf #else #define system_string_sprintf( string, size, format, ... ) \ wide_string_snwprintf( string, size, format, __VA_ARGS__ ) #endif #if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 ) #define system_string_vsnprintf \ wide_string_vsnwprintf #else #define system_string_vsnprintf( string, size, format, ... ) \ wide_string_vsnwprintf( string, size, format, __VA_ARGS__ ) #endif #else #define _SYSTEM_STRING( string ) \ string #define system_string_allocate( size ) \ narrow_string_allocate( size ) #define system_string_reallocate( string, size ) \ narrow_string_reallocate( string, size ) #define system_string_compare( destination, source, size ) \ narrow_string_compare( destination, source, size ) #define system_string_compare_no_case( destination, source, size ) \ narrow_string_compare_no_case( destination, source, size ) #define system_string_copy( destination, source, size ) \ narrow_string_copy( destination, source, size ) #define system_string_length( string ) \ narrow_string_length( string ) #define system_string_search_character( string, character, size ) \ narrow_string_search_character( string, character, size ) #define system_string_search_character_reverse( string, character, size ) \ narrow_string_search_character_reverse( string, character, size ) #define system_string_search_string( string, substring, size ) \ narrow_string_search_string( string, substring, size ) #if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 ) #define system_string_sprintf \ narrow_string_snprintf #else #define system_string_sprintf( string, size, format, ... ) \ narrow_string_snprintf( string, size, format, __VA_ARGS__ ) #endif #if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 ) #define system_string_vsnprintf \ narrow_string_vsnprintf #else #define system_string_vsnprintf( string, size, format, ... ) \ narrow_string_vsnprintf( string, size, format, __VA_ARGS__ ) #endif #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */ /* For backwards compatibility */ #define system_string_vsprintf system_string_vsnprintf #if defined( _cplusplus ) } #endif #endif /* !defined( _SYSTEM_STRING_H ) */ ================================================ FILE: common/types.h.in ================================================ /* * Type and type-support definitions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _TYPES_H ) #define _TYPES_H #include "common.h" #if defined( HAVE_LIMITS_H ) || defined( WINAPI ) #include #endif /* Make sure to include inttypes.h or stdint.h before * PRI definitions are defined */ #include <@PACKAGE@/types.h> #if defined( WINAPI ) && ( defined( _UNICODE ) || defined( UNICODE ) ) #define HAVE_WIDE_SYSTEM_CHARACTER 1 /* The system character type is wide * A system string contains either UTF-16 or UTF-32 */ typedef wchar_t system_character_t; typedef wint_t system_integer_t; #define PRIc_SYSTEM "lc" #define PRIs_SYSTEM "ls" #else /* The system character type is narrow * A system string contains either UTF-8 or extended ASCII with a codepage */ typedef char system_character_t; typedef int system_integer_t; #define PRIc_SYSTEM "c" #define PRIs_SYSTEM "s" #endif /* defined( WINAPI ) && ( defined( _UNICODE ) || defined( UNICODE ) ) */ /* Fallback for systems without PRI definitions * Do not define when pyconfig.h has been included via python.h */ #if !defined( HAVE_PYCONFIG_H ) #if !defined( PRId8 ) #define PRId8 "d" #endif #if !defined( PRId16 ) #define PRId16 "d" #endif #if !defined( PRId32 ) #if defined( WINAPI ) #define PRId32 "I32d" #else #define PRId32 "d" #endif #endif /* !defined( PRId32 ) */ #if !defined( PRId64 ) #if defined( WINAPI ) #define PRId64 "I64d" #elif __WORDSIZE == 64 #define PRId64 "ld" #else #define PRId64 "lld" #endif #endif /* !defined( PRId64 ) */ #if !defined( PRIi8 ) #define PRIi8 "i" #endif #if !defined( PRIi16 ) #define PRIi16 "i" #endif #if !defined( PRIi32 ) #if defined( WINAPI ) #define PRIi32 "I32i" #else #define PRIi32 "i" #endif #endif /* !defined( PRIi32 ) */ #if !defined( PRIi64 ) #if defined( WINAPI ) #define PRIi64 "I64i" #elif __WORDSIZE == 64 #define PRIi64 "li" #else #define PRIi64 "lli" #endif #endif /* !defined( PRIi64 ) */ #if !defined( PRIu8 ) #define PRIu8 "u" #endif #if !defined( PRIu16 ) #define PRIu16 "u" #endif #if !defined( PRIu32 ) #if defined( WINAPI ) #define PRIu32 "I32u" #else #define PRIu32 "u" #endif #endif /* !defined( PRIu32 ) */ #if !defined( PRIu64 ) #if defined( WINAPI ) #define PRIu64 "I64u" #elif __WORDSIZE == 64 #define PRIu64 "lu" #else #define PRIu64 "llu" #endif #endif /* !defined( PRIu64 ) */ #if !defined( PRIo8 ) #define PRIo8 "o" #endif #if !defined( PRIo16 ) #define PRIo16 "o" #endif #if !defined( PRIo32 ) #if defined( WINAPI ) #define PRIo32 "I32o" #else #define PRIo32 "o" #endif #endif /* !defined( PRIo32 ) */ #if !defined( PRIo64 ) #if defined( WINAPI ) #define PRIo64 "I64o" #elif __WORDSIZE == 64 #define PRIo64 "lo" #else #define PRIo64 "llo" #endif #endif /* !defined( PRIo64 ) */ #if !defined( PRIx8 ) #define PRIx8 "x" #endif #if !defined( PRIx16 ) #define PRIx16 "x" #endif #if !defined( PRIx32 ) #if defined( WINAPI ) #define PRIx32 "I32x" #else #define PRIx32 "x" #endif #endif /* !defined( PRIx32 ) */ #if !defined( PRIx64 ) #if defined( WINAPI ) #define PRIx64 "I64x" #elif __WORDSIZE == 64 #define PRIx64 "lx" #else #define PRIx64 "llx" #endif #endif /* !defined( PRIx64 ) */ #endif /* !defined( HAVE_PYCONFIG_H ) */ /* Fallback for systems without printf %jd definition */ #if defined( HAVE_PRINTF_JD ) #define PRIjd "jd" #define PRIji "ji" #define PRIju "ju" #define PRIjx "jx" #elif SIZEOF_OFF_T == 8 #define PRIjd PRId64 #define PRIji PRIi64 #define PRIju PRIu64 #define PRIjx PRIx64 #else #define PRIjd PRId32 #define PRIji PRIi32 #define PRIju PRIu32 #define PRIjx PRIx32 #endif /* defined( HAVE_PRINTF_JD ) */ /* Fallback for systems without printf %zd definition */ #if defined( HAVE_PRINTF_ZD ) #define PRIzd "zd" #define PRIzi "zi" #define PRIzu "zu" #define PRIzx "zx" #elif defined( _MSC_VER ) #define PRIzd "Id" #define PRIzi "Ii" #define PRIzu "Iu" #define PRIzx "Ix" #elif SIZEOF_SIZE_T == 8 #define PRIzd PRId64 #define PRIzi PRIi64 #define PRIzu PRIu64 #define PRIzx PRIx64 #else #define PRIzd PRId32 #define PRIzi PRIi32 #define PRIzu PRIu32 #define PRIzx PRIx32 #endif /* defined( HAVE_PRINTF_ZD ) */ /* Fallback for systems without (U)INTx_MAX definitions */ /* The maximum signed 8-bit integer is 127 (0x7f) */ #if !defined( INT8_MAX ) #define INT8_MAX (0x7f) #endif /* The maximum unsigned 8-bit integer is 256 (0xff) */ #if !defined( UINT8_MAX ) #define UINT8_MAX (0xff) #endif /* The maximum signed 16-bit integer is 32767 (0x7ffff) */ #if !defined( INT16_MAX ) #define INT16_MAX (0x7fff) #endif /* The maximum unsigned 16-bit integer is 65535 (0xffff) */ #if !defined( UINT16_MAX ) #define UINT16_MAX (0xffff) #endif /* The maximum signed 32-bit integer is 2147483647 (0x7fffffff) */ #if !defined( INT32_MAX ) #define INT32_MAX (0x7fffffffL) #endif /* The maximum unsigned 32-bit integer is 4294967295 (0xffffffff) */ #if !defined( UINT32_MAX ) #define UINT32_MAX (0xffffffffUL) #endif /* The minimum signed 64-bit integer is -9223372036854775808 (0x8000000000000000) */ #if !defined( INT64_MIN ) #if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 ) #define INT64_MIN (0x8000000000000000UL) #else #define INT64_MIN (0x8000000000000000ULL) #endif #endif /* !defined( INT64_MIN ) */ /* The maximum signed 64-bit integer is 9223372036854775807 (0x7fffffffffffffff) */ #if !defined( INT64_MAX ) #if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 ) #define INT64_MAX (0x7fffffffffffffffUL) #else #define INT64_MAX (0x7fffffffffffffffULL) #endif #endif /* !defined( INT64_MAX ) */ /* The maximum unsigned 64-bit integer is 18446744073709551615 (0xffffffffffffffff) */ #if !defined( UINT64_MAX ) #if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 ) #define UINT64_MAX (0xffffffffffffffffUL) #else #define UINT64_MAX (0xffffffffffffffffULL) #endif #endif /* !defined( UINT64_MAX ) */ /* The maximum signed integer */ #if !defined( INT_MAX ) #define INT_MAX INT32_MAX #endif /* The maximum unsigned integer */ #if !defined( UINT_MAX ) #define UINT_MAX UINT32_MAX #endif /* The maximum signed long integer */ #if !defined( LONG_MAX ) #define LONG_MAX INT32_MAX #endif /* The maximum unsigned long integer */ #if !defined( ULONG_MAX ) #define ULONG_MAX UINT32_MAX #endif /* The maximum signed size type is platform dependent */ #if !defined( SSIZE_MAX ) #if defined( WINAPI ) #if defined( _WIN64 ) #define SSIZE_MAX INT64_MAX #else #define SSIZE_MAX INT32_MAX #endif #else #if __WORDSIZE == 64 #define SSIZE_MAX INT64_MAX #else #define SSIZE_MAX INT32_MAX #endif #endif /* WINAPI */ #endif /* SSIZE_MAX */ #endif /* !defined( _TYPES_H ) */ ================================================ FILE: common/wide_string.h ================================================ /* * Wide character string functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _WIDE_STRING_H ) #define _WIDE_STRING_H #include "common.h" #include "memory.h" #include "types.h" #if defined( HAVE_WCHAR_H ) || defined( WINAPI ) #include #endif #if defined( __cplusplus ) extern "C" { #endif /* Intermediate version of the macro required * for correct evaluation predefined string */ #define _WIDE_STRING_INTERMEDIATE( string ) \ L ## string #define _WIDE_STRING( string ) \ _WIDE_STRING_INTERMEDIATE( string ) /* String allocation */ #define wide_string_allocate( size ) \ (wchar_t *) memory_allocate( sizeof( wchar_t ) * ( size ) ) /* String reallocation */ #define wide_string_reallocate( string, size ) \ (wchar_t *) memory_reallocate( string, ( sizeof( wchar_t ) * ( size ) ) ) /* String length */ #if defined( HAVE_WCSLEN ) || defined( WINAPI ) #define wide_string_length( string ) \ wcslen( string ) #endif /* String compare */ #if defined( HAVE_WMEMCMP ) #define wide_string_compare( string1, string2, size ) \ wmemcmp( (void *) string1, (void *) string2, size ) #elif defined( HAVE_WCSNCMP ) || defined( WINAPI ) #define wide_string_compare( string1, string2, size ) \ wcsncmp( string1, string2, size ) #endif /* Caseless string compare */ #if defined( _MSC_VER ) || ( defined( __BORLANDC__ ) && ( __BORLANDC__ >= 0x0551 ) ) #define wide_string_compare_no_case( string1, string2, size ) \ _wcsnicmp( string1, string2, size ) #elif ( defined( WINAPI ) && !defined( __CYGWIN__ ) ) || defined( HAVE_WCSNICMP ) #define wide_string_compare_no_case( string1, string2, size ) \ wcsnicmp( string1, string2, size ) #elif defined( HAVE_WCSNCASECMP ) #define wide_string_compare_no_case( string1, string2, size ) \ wcsncasecmp( string1, string2, size ) #elif defined( HAVE_WCSCASECMP ) #define wide_string_compare_no_case( string1, string2, size ) \ wcscasecmp( string1, string2 ) #endif /* String copy */ #if defined( HAVE_WMEMCPY ) #define wide_string_copy( destination, source, size ) \ (wchar_t *) wmemcpy( (void *) destination, (void *) source, size ) #elif defined( HAVE_WCSNCPY ) || defined( WINAPI ) #define wide_string_copy( destination, source, size ) \ wcsncpy( destination, source, size ) #endif /* String character search */ #if defined( HAVE_WMEMCHR ) #define wide_string_search_character( string, character, size ) \ (wchar_t *) wmemchr( (void *) string, (wchar_t) character, size ) #elif defined( HAVE_WCSCHR ) || defined( WINAPI ) #define wide_string_search_character( string, character, size ) \ wcschr( string, (wchar_t) character ) #endif /* String reverse character search */ #if defined( HAVE_WMEMRCHR ) #define wide_string_search_character_reverse( string, character, size ) \ (wchar_t *) wmemrchr( (void *) string, (wchar_t) character, size ) #elif defined( HAVE_WCSRCHR ) || defined( WINAPI ) /* (void)(size) is used to suppress unused variable warnings */ #define wide_string_search_character_reverse( string, character, size ) \ wcsrchr( string, (wchar_t) character ); (void)(size) #endif /* String sub-string search */ #if defined( HAVE_WCSSTR ) || defined( WINAPI ) #define wide_string_search_string( string, substring, size ) \ wcsstr( string, substring ) #endif /* String formatted print (snwprintf) */ #if defined( _MSC_VER ) #define wide_string_snwprintf( target, size, ... ) \ swprintf_s( target, size, __VA_ARGS__ ) #elif defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 ) #define wide_string_snwprintf \ snwprintf #elif defined( WINAPI ) #define wide_string_snwprintf( target, size, ... ) \ snwprintf( target, size, __VA_ARGS__ ) #elif defined( HAVE_SWPRINTF ) #define wide_string_snwprintf( target, size, ... ) \ swprintf( target, size, __VA_ARGS__ ) #endif /* Variable arguments formatted print to string function (vsnwprintf) */ #if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 ) #define wide_string_vsnwprintf \ _vsnwprintf #elif defined( WINAPI ) #define wide_string_vsnwprintf( string, size, format, ... ) \ _vsnwprintf( string, size, format, __VA_ARGS__ ) #elif defined( HAVE_VSWPRINTF ) #define wide_string_vsnwprintf( string, size, format, ... ) \ vswprintf( string, size, format, __VA_ARGS__ ) #endif #if defined( __cplusplus ) } #endif #endif /* !defined( _WIDE_STRING_H ) */ ================================================ FILE: configure.ac ================================================ AC_PREREQ([2.71]) AC_INIT( [libfsntfs], [20260208], [joachim.metz@gmail.com]) AC_CONFIG_SRCDIR( [include/libfsntfs.h.in]) AM_INIT_AUTOMAKE([gnu 1.6 tar-ustar]) AM_EXTRA_RECURSIVE_TARGETS([sources splint]) AC_CONFIG_MACRO_DIR([m4]) dnl Check for host type AC_CANONICAL_HOST dnl Check for libtool DLL support LT_INIT([win32-dll]) dnl Checks for programs AC_PROG_CC AC_PROG_GCC_TRADITIONAL AC_PROG_CXX AC_PROG_MAKE_SET AC_PROG_INSTALL dnl Check for libtool AC_SUBST(LIBTOOL_DEPS) dnl Check for pkg-config AC_PATH_PROG(PKGCONFIG,[pkg-config]) dnl Support of internationalization (i18n) AM_GNU_GETTEXT([external]) AM_GNU_GETTEXT_VERSION([0.21]) dnl Check for compiler language support AC_C_CONST AC_C_VOLATILE dnl Check for large file support AC_SYS_LARGEFILE dnl Check if shared library support should be disabled AX_COMMON_CHECK_DISABLE_SHARED_LIBS dnl Check if tools should be build as static executables AX_COMMON_CHECK_ENABLE_STATIC_EXECUTABLES dnl Check if WINAPI support should be enabled AX_COMMON_CHECK_ENABLE_WINAPI dnl Check if wide character type should be enabled AX_COMMON_CHECK_ENABLE_WIDE_CHARACTER_TYPE dnl Check if verbose output should be enabled AX_COMMON_CHECK_ENABLE_VERBOSE_OUTPUT dnl Check if debug output should be enabled AX_COMMON_CHECK_ENABLE_DEBUG_OUTPUT dnl Check for type definitions AX_TYPES_CHECK_LOCAL dnl Check if common required headers and functions are available AX_COMMON_CHECK_LOCAL dnl Check if libcerror or required headers and functions are available AX_LIBCERROR_CHECK_ENABLE dnl Check if libcthreads or required headers and functions are available AX_LIBCTHREADS_CHECK_ENABLE dnl Check if libcdata or required headers and functions are available AX_LIBCDATA_CHECK_ENABLE dnl Check if libclocale or required headers and functions are available AX_LIBCLOCALE_CHECK_ENABLE dnl Check if libcnotify or required headers and functions are available AX_LIBCNOTIFY_CHECK_ENABLE dnl Check if libcsplit or required headers and functions are available AX_LIBCSPLIT_CHECK_ENABLE dnl Check if libuna or required headers and functions are available AX_LIBUNA_CHECK_ENABLE dnl Check if libcfile or required headers and functions are available AX_LIBCFILE_CHECK_ENABLE dnl Check if libcpath or required headers and functions are available AX_LIBCPATH_CHECK_ENABLE dnl Check if libbfio or required headers and functions are available AX_LIBBFIO_CHECK_ENABLE dnl Check if libfcache or required headers and functions are available AX_LIBFCACHE_CHECK_ENABLE dnl Check if libfdata or required headers and functions are available AX_LIBFDATA_CHECK_ENABLE dnl Check if libfdatetime or required headers and functions are available AX_LIBFDATETIME_CHECK_ENABLE dnl Check if libfguid or required headers and functions are available AX_LIBFGUID_CHECK_ENABLE dnl Check if libfwnt or required headers and functions are available AX_LIBFWNT_CHECK_ENABLE dnl Check if libfsntfs required headers and functions are available AX_LIBFSNTFS_CHECK_LOCAL dnl Check if libfsntfs Python bindings (pyfsntfs) required headers and functions are available AX_PYTHON_CHECK_ENABLE AS_IF( [test "x${ac_cv_enable_python}" != xno], [dnl Headers included in pyfsntfs/pyfsntfs_error.c AC_CHECK_HEADERS([stdarg.h varargs.h]) AS_IF( [test "x$ac_cv_header_stdarg_h" != xyes && test "x$ac_cv_header_varargs_h" != xyes], [AC_MSG_FAILURE( [Missing headers: stdarg.h and varargs.h], [1]) ]) ]) dnl Check if libfusn or required headers and functions are available AX_LIBFUSN_CHECK_ENABLE dnl Check if libhmac or required headers and functions are available AX_LIBHMAC_CHECK_ENABLE dnl Check if libfuse or required headers and functions are available AX_LIBFUSE_CHECK_ENABLE dnl Check if fsntfstools required headers and functions are available AX_FSNTFSTOOLS_CHECK_LOCAL dnl Check if DLL support is needed AX_LIBFSNTFS_CHECK_DLL_SUPPORT dnl Check if tests required headers and functions are available AX_TESTS_CHECK_LOCAL AX_TESTS_CHECK_OSSFUZZ dnl Set additional compiler flags CFLAGS="$CFLAGS -Wall"; dnl Check if requires and build requires should be set in spec file AS_IF( [test "x$ac_cv_libcerror" = xyes || test "x$ac_cv_libcthreads" = xyes || test "x$ac_cv_libcdata" = xyes || test "x$ac_cv_libclocale" = xyes || test "x$ac_cv_libcnotify" = xyes || test "x$ac_cv_libcsplit" = xyes || test "x$ac_cv_libuna" = xyes || test "x$ac_cv_libcfile" = xyes || test "x$ac_cv_libcpath" = xyes || test "x$ac_cv_libbfio" = xyes || test "x$ac_cv_libfcache" = xyes || test "x$ac_cv_libfdata" = xyes || test "x$ac_cv_libfdatetime" = xyes || test "x$ac_cv_libfguid" = xyes || test "x$ac_cv_libfwnt" = xyes], [AC_SUBST( [libfsntfs_spec_requires], [Requires:]) ]) AS_IF( [test "x$ac_cv_libfusn" = xyes || test "x$ac_cv_libhmac" = xyes || test "x$ac_cv_libcrypto" != xno || test "x$ac_cv_libfuse" != xno], [AC_SUBST( [libfsntfs_spec_tools_build_requires], [BuildRequires:]) ]) dnl Set the date for the dpkg files AC_SUBST( [DPKG_DATE], [`date -R 2> /dev/null`]) dnl Set the date for the spec file AC_SUBST( [SPEC_DATE], [`date +"%a %b %e %Y" 2> /dev/null`]) dnl Generate Makefiles AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([include/Makefile]) AC_CONFIG_FILES([common/Makefile]) AC_CONFIG_FILES([libcerror/Makefile]) AC_CONFIG_FILES([libcthreads/Makefile]) AC_CONFIG_FILES([libcdata/Makefile]) AC_CONFIG_FILES([libclocale/Makefile]) AC_CONFIG_FILES([libcnotify/Makefile]) AC_CONFIG_FILES([libcsplit/Makefile]) AC_CONFIG_FILES([libuna/Makefile]) AC_CONFIG_FILES([libcfile/Makefile]) AC_CONFIG_FILES([libcpath/Makefile]) AC_CONFIG_FILES([libbfio/Makefile]) AC_CONFIG_FILES([libfcache/Makefile]) AC_CONFIG_FILES([libfdata/Makefile]) AC_CONFIG_FILES([libfdatetime/Makefile]) AC_CONFIG_FILES([libfguid/Makefile]) AC_CONFIG_FILES([libfwnt/Makefile]) AC_CONFIG_FILES([libfsntfs/Makefile]) AC_CONFIG_FILES([pyfsntfs/Makefile]) AC_CONFIG_FILES([libfusn/Makefile]) AC_CONFIG_FILES([libhmac/Makefile]) AC_CONFIG_FILES([fsntfstools/Makefile]) AC_CONFIG_FILES([po/Makefile.in]) AC_CONFIG_FILES([po/Makevars]) AC_CONFIG_FILES([manuals/Makefile]) AC_CONFIG_FILES([tests/Makefile]) AC_CONFIG_FILES([ossfuzz/Makefile]) AC_CONFIG_FILES([msvscpp/Makefile]) dnl Generate header files AC_CONFIG_FILES([include/libfsntfs.h]) AC_CONFIG_FILES([include/libfsntfs/definitions.h]) AC_CONFIG_FILES([include/libfsntfs/features.h]) AC_CONFIG_FILES([include/libfsntfs/types.h]) AC_CONFIG_FILES([libfsntfs/libfsntfs_definitions.h]) dnl Generate distribution specific files AC_CONFIG_FILES([common/types.h]) AC_CONFIG_FILES([dpkg/changelog]) AC_CONFIG_FILES([libfsntfs/libfsntfs.rc]) AC_CONFIG_FILES([libfsntfs.pc]) AC_CONFIG_FILES([libfsntfs.spec]) AC_CONFIG_FILES([setup.cfg]) dnl Generate a source configuration file AC_CONFIG_HEADERS([common/config.h]) AC_OUTPUT dnl Print a summary AC_MSG_NOTICE([ Building: libcerror support: $ac_cv_libcerror libcthreads support: $ac_cv_libcthreads libcdata support: $ac_cv_libcdata libclocale support: $ac_cv_libclocale libcnotify support: $ac_cv_libcnotify libcsplit support: $ac_cv_libcsplit libuna support: $ac_cv_libuna libcfile support: $ac_cv_libcfile libcpath support: $ac_cv_libcpath libbfio support: $ac_cv_libbfio libfcache support: $ac_cv_libfcache libfdata support: $ac_cv_libfdata libfdatetime support: $ac_cv_libfdatetime libfguid support: $ac_cv_libfguid libfwnt support: $ac_cv_libfwnt libfusn support: $ac_cv_libfusn libhmac support: $ac_cv_libhmac MD5 support: $ac_cv_libhmac_md5 FUSE support: $ac_cv_libfuse Features: Multi-threading support: $ac_cv_libcthreads_multi_threading Wide character type support: $ac_cv_enable_wide_character_type fsntfstools are build as static executables: $ac_cv_enable_static_executables Python (pyfsntfs) support: $ac_cv_enable_python Verbose output: $ac_cv_enable_verbose_output Debug output: $ac_cv_enable_debug_output ]); ================================================ FILE: documentation/New Technologies File System (NTFS).asciidoc ================================================ = New Technologies File System (NTFS) Analysis of NTFS :toc: :toclevels: 4 :numbered!: [abstract] == Summary NTFS is the primary file system for Microsoft Windows versions that are based on Windows NT. This specification is based on publicly available work on the format and was enhanced by analyzing test data. This document is intended as a working document of the data format specification for the libfsntfs project. [preface] == Document information [cols="1,5"] |=== | Author(s): | Joachim Metz | Abstract: | This document contains information about the New Technologies File System (NTFS) | Classification: | Public | Keywords: | New Technologies File System, NTFS |=== [preface] == License .... Copyright (C) 2009-2025, Joachim Metz . Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". .... [preface] == Revision history [cols="1,1,1,5",options="header"] |=== | Version | Author | Date | Comments | 0.0.1 | J.B. Metz | August 2009 + September 2010 + October 2010 + November 2010 + December 2010 | Initial version, based on earlier notes. | 0.0.2 | J.B. Metz | March 2011 | Additional information about multi data run MFT. | 0.0.3 | J.B. Metz | May 2012 | Additional information. | 0.0.4 | J.B. Metz | February 2014 | Additional information. | 0.0.5 | J.B. Metz | July 2014 + August 2014 | Textual changes and additional information. | 0.0.6 | J.B. Metz | March 2015 | Additional information and switched to asciidoc format. | 0.0.7 | J.B. Metz | May 2015 | Additional information. | 0.0.8 | J.B. Metz | July 2015 | Textual changes. | 0.0.9 | J.B. Metz | August 2015 | Additional information. | 0.0.10 | J.B. Metz | August 2015 | Additional information regarding index and security descriptors. | 0.0.11 | J.B. Metz | January 2016 | Additional information about common alternate data stream. | 0.0.12 | J.B. Metz | January 2016 | Additional information about extended attributes. | 0.0.13 | J.B. Metz | March 2016 | Small changes. | 0.0.14 | J.B. Metz | April 2016 | Small changes. | 0.0.15 | J.B. Metz | June 2018 | Corrected typos. | 0.0.16 | J.B. Metz | January 2019 | Changes to format. | 0.0.17 | J.B. Metz | August 2019 | Additional information regarding volumes created by Windows 10 (1903) and mkntfs. | 0.0.18 | J.B. Metz | September 2019 | Additional information regarding Windows Overlay Filter (WOF) compressed data. | 0.0.19 | J.B. Metz | November 2019 | Additional information regarding short file names. | 0.0.20 | J.B. Metz | January 2020 | Additional information regarding $STANDARD_INFORMATION and $ATTRIBUTE_LIST attributes. | 0.0.21 | J.B. Metz | April 2020 | Additional information regarding compressed data runs. | 0.0.22 | J.B. Metz | May 2020 | Additional information regarding LZNT1 compressed block corruption scenarios. | 0.0.23 | J.B. Metz | December 2020 | Additional information regarding reparse point tag values. | 0.0.24 | J.B. Metz | October 2021 | Small changes. | 0.0.25 | J.B. Metz | February 2022 | Additional information regarding index entry size. | 0.0.26 | J.B. Metz | December 2022 | Additional information regarding $VOLUME_INFORMATION flags. | 0.0.27 | J.B. Metz | July 2023 | Additional information file name UTF-16 strings. | 0.0.28 | J.B. Metz | January 2025 | Textual changes. |=== :numbered: == Overview NTFS is the primary file system for Microsoft Windows versions that are based on Windows NT. [yellow-background]*TODO describe relation to OS2 HPFS* [cols="1,5",options="header"] |=== | Characteristics | Description | Byte order | little-endian | Date and time values | FILETIME in UTC | Character strings | ASCII strings are Single Byte Character (SBC) or Multi Byte Character (MBC) string stored with a codepage. Sometimes referred to as ANSI string representation. + Though technically maybe incorrect, this document will use term (extended) ASCII string. + Unicode strings are stored in UTF-16 little-endian without the byte order mark (BOM). |=== === Versions There are multiple version of NTFS. [cols="1,5",options="header"] |=== | NTFS version | Remarks | 1.0 | Introduced in Windows NT 3.1 | 1.1 | Introduced in Windows NT 3.5, also seen to be used by Windows NT 3.1 | 1.2 | Introduced in Windows NT 3.51 | 3.0 | Introduced in Windows 2000 | 3.1 | Introduced in Windows XP |=== [yellow-background]*Need test images for version 1.0 and 1.1* [NOTE] The versions mentioned above are the version as used by NTFS. Another common versioning schema uses the Windows version, e.g. NTFS 5.0 is the version of NTFS used on Windows XP which is version 3.1 in schema mentioned above. === Test version The following version of programs were used to test the information within this document: * Windows NT 3.1 (version 1.1) * Windows NT4 (version 1.2) * Windows 2000 (version 3.0) * Windows XP SP3 (version 3.1) * Windows 2003 (version 3.1) * Windows Vista (version 3.1) * Windows 2008 (version 3.1) * Windows 7 (version 3.1) * Windows 8 (version 3.1) * Windows 10 (1809, 1903) (version 3.1) * Windows 11 (21H2) (version 3.1) * NTFS-3G [NOTE] Windows 10 (1809) has been observed to use NTFS version 1.2 for 64k cluster block size. == Terminology === Cluster NTFS refers to it file system blocks as clusters. Note that these are not the same as the physical clusters of a harddisk. For clarity these are referred to as cluster blocks. In other sources they are also referred to as logical clusters which are numbered globally (or absolute). Typically the cluster block is 8 sectors (8 x 512 = 4096 bytes) in size. === Virtual cluster The term virtual cluster refers to cluster blocks which are numbered locally (or relative). === Long and short (file) name In Windows terminology the name of a file (or directory) can either be short or long. The short name is an equivalent of the filename in the (DOS) 8.3 format. The long name is actual the (full) name of the file. The term long refers to the aspect that the name is longer than the short variant. Because most documentation refer to the (full) name as the long name, for clarity sake so will this document. == The volume Everything on an NTFS volume is a file. There are two types of files: * files that contain volume and file system metadata (referred to as metadata files); * files that contain data (referred to as files). === The metadata files NTFS uses the Master File Table (MFT) to store information about files and directories. The MFT entries reference the different volume and file system metadata. There are several predefined metadata files. The following metadata files are predefined and use a fixed MFT entry index. [cols="1,1,5",options="header"] |=== | MFT entry index | Filename | Description | 0 | $MFT | Master File Table | 1 | $MFTMirr | Back up of the first 4 entries of the Master File Table | 2 | $LogFile | Metadata transaction journal | 3 | $Volume | Volume information | 4 | $AttrDef | MFT entry attribute definitions | 5 | . | Root directory | 6 | $Bitmap | Cluster block allocation bitmap | 7 | $Boot | Boot record (or boot code) | 8 | $BadClus | Bad clusters | 9 | $Quota | Quota information + Last used in NTFS version 1.2 | 9 | $Secure | Security and access control information + Introduced in NTFS version 3.0 | 10 | $UpCase | Table of uppercase characters used for ensuring case insensitivity in Windows and DOS name spaces. | 11 | $Extend | A directory containing extended metadata files | 12-15 | | [yellow-background]*Unknown (Reserved)* + Marked as in use but empty | 16-23 | | Unused + Marked as unused 3+| _As of NTFS version 3.0_ | 24 | $Extend\$Quota | Quota information + Was MFT entry 9 in Windows NT 4 | 25 | $Extend\$ObjId | Unique file identifiers for distributed link tracking | 26 | $Extend\$Reparse | Backreferences to reparse points 3+| _As of Windows Vista_ ([yellow-background]*or server 2003?*) + _Transactional NTFS metadata (See section: <>)_ | 27 | $Extend\$RmMetadata | Resource manager metadata directory | 28 | $Extend\$RmMetadata\$Repair | Repair information | 29 or 30 | $Extend\$RmMetadata\$TxfLog | Transactional NTFS (TxF) log metadata directory | 30 or 31 | $Extend\$RmMetadata\$Txf | Transactional NTFS (TxF) metadata directory | 31 or 32 | $Extend\$RmMetadata\$TxfLog\$Tops | TxF Old Page Stream (TOPS) file + Used to store data that has been overwritten inside a currently active transaction | 32 or 33 | $Extend\$RmMetadata\$TxfLog\$TxfLog.blf | Transactional NTFS (TxF) base log metadata file 3+| _As of Windows 10_ | 29 | $Extend\$Deleted | Temporary location for files that have an open handle but a request has been made to delete them 3+| _Common_ | | ... | A file or directory |=== The following metadata files are predefined, however the MFT entry index is commonly used but not fixed. [cols="1,1,5",options="header"] |=== | MFT entry index | Filename | Description | | $Extend\$UsnJrnl | USN change journal + See section: <> + [yellow-background]*Has this file been added in Windows XP SP3? Otherwise what are reasons for it to not be present?* |=== == The volume header The volume header is stored at the start of the volume (in the $Boot metadata file) and contains: * the volume signature * the BIOS parameter block * the boot loader The volume header is 512 bytes in size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 3 | | Boot entry point + Often contains: + eb52 jmp 0x52 + 90 nop + This is a jump instruction to the bootcode at offset 84 followed by a no-operation. | 3 | 8 | "NTFS\x20\x20\x20\x20" | File system signature + (Also known as OEM and/or dummy identifier) + 4+| _DOS version 2.0 BIOS parameter block (BPB)_ | 11 | 2 | | Bytes per sector + Values supported by mkntfs: 256, 512, 1024, 2048 and 4096 | 13 | 1 | | Sectors per cluster block + See below. | 14 | 2 | 0x00 | [yellow-background]*Unknown (Reserved Sectors)* + not used by NTFS and must be 0 `[MSDN]` | 16 | 1 | 0x00 | Number of File Allocation Tables (FATs) + not used by NTFS and must be 0 `[MSDN]` | 17 | 2 | 0 | Root directory entries + not used by NTFS and must be 0 `[MSDN]` | 19 | 2 | | [yellow-background]*Unknown (Total number of sectors (16-bit))* + [yellow-background]*Used if the total of number of sectors fits in 16-bit?* | 21 | 1 | | Media descriptor + See section: <> | 22 | 2 | 0x00 | Sectors Per File Allocation Table (FAT) + not used by NTFS and must be 0 `[MSDN]` 4+| _DOS version 3.4 BIOS parameter block (BPB)_ | 24 | 2 | 0x3f | Sectors per track + Not used by NTFS `[MSDN]` | 26 | 2 | 0xff | Number of heads + Not used by NTFS `[MSDN]` | 28 | 4 | 0x3f | Number of hidden sectors + Not used by NTFS `[MSDN]` | 32 | 4 | 0x00 | [yellow-background]*Unknown (Total number of sectors (32-bit))* + [yellow-background]*Used if the total of number of sectors fits in 32-bit?* + Not used by NTFS must be 0 `[MSDN]` 4+| _NTFS version 8.0 BIOS parameter block (BPB) or extended BPB_ + _Introduced in Windows NT version 3.1_ | 36 | 1 | 0x80 | [yellow-background]*Unknown (Disc unit number)* + Not used by NTFS `[MSDN]` | 37 | 1 | 0x00 | [yellow-background]*Unknown (Flags)* + Not used by NTFS `[MSDN]` | 38 | 1 | 0x80 | [yellow-background]*Unknown (BPB version signature byte)* + Not used by NTFS `[MSDN]` | 39 | 1 | 0x00 | [yellow-background]*Unknown (Reserved)* + Not used by NTFS `[MSDN]` | 40 | 8 | | Total number of sectors (64-bit) | 48 | 8 | | Master File Table (MFT) cluster block number | 56 | 8 | | Mirror MFT cluster block number | 64 | 1 | | MFT entry size + See below. | 65 | 3 | | [yellow-background]*Unknown* + Not used by NTFS `[MSDN]` | 68 | 1 | | Index entry size + See below. | 69 | 3 | | [yellow-background]*Unknown* + Not used by NTFS `[MSDN]` | 72 | 8 | | NTFS volume serial number + See below. | 80 | 4 | 0x00 | Checksum + not used by NTFS `[MSDN]` 4+| | 84 | 426 | | Bootcode + [yellow-background]*What is the exact end of the bootcode and are there no trailing values?* | 510 | 2 | 0x55 0xaa | Sector signature |=== The sectors per cluster block value as used by mkntfs is defined as following: * Values 0 to 128 represent sizes of 0 to 128 sectors. * Values 244 to 255 represent sizes of `2^(256-n)` sectors. * Other values are unknown. The MFT entry size and index entry size are defined as following: * Values 0 to 127 represent sizes of 0 to 127 cluster blocks. * Values 128 to 255 represent sizes of `2^(256-n)` bytes; or `2^(-n)` if considered as a signed byte. * Other values are not considered valid. The cluster block size can be determined as following: .... cluster block size = bytes per sector x sectors per cluster block .... [NOTE] Different NTFS implementations support different cluster block sizes. Known supported cluster block size: [cols="1,1,5",options="header"] |=== | Cluster block size | Bytes per sector | Supported by | 256 | 256 | mkntfs | 512 | 256 - 512 | mkntfs, ntfs3g, Windows | 1024 | 256 - 1024 | mkntfs, ntfs3g, Windows | 2048 | 256 - 2048 | mkntfs, ntfs3g, Windows | 4096 | 256 - 4096 | mkntfs, ntfs3g, Windows | 8192 | 256 - 4096 | mkntfs, ntfs3g, Windows | 16K (16384) | 256 - 4096 | mkntfs, ntfs3g, Windows | 32K (32768) | 256 - 4096 | mkntfs, ntfs3g, Windows | 64K (65536) | 256 - 4096 | mkntfs, ntfs3g, Windows | 128K (131072) | 256 - 4096 | mkntfs, ntfs3g, Windows 10 (1903) | 256K (262144) | 256 - 4096 | mkntfs, ntfs3g, Windows 10 (1903) | 512K (524288) | 256 - 4096 | mkntfs, ntfs3g, Windows 10 (1903) | 1M (1048576) | 256 - 4096 | mkntfs, ntfs3g, Windows 10 (1903) | 2M (2097152) | 512 - 4096 | mkntfs, ntfs3g, Windows 10 (1903) |=== [NOTE] Windows 10 (1903) requires the partition containing the NTFS file system to be aligned with the cluster block size. For example for a cluster block size of 128k the partition must 128 KiB aligned. The default partition partition alignment appears to be 64 KiB. [NOTE] mkntfs restricts the cluster size to: bytes per sector >= cluster size > 4096 * bytes per sector The MFT offset can be determined as following: .... MFT offset = volume header offset + ( MFT cluster block number x Cluster block size ) .... Note that the lower 32-bit part of the NTFS volume serial number is the WINAPI volume serial number. E.g. compare the output of: .... fsutil fsinfo volumeinfo C: fsutil fsinfo ntfsinfo C: .... Often the volume will be smaller than the underlying partition. A (nearly identical) backup of the volume header is stored in last sector of cluster block, that follows the last cluster block of the volume. Often this is the 512 bytes after the last sector of the volume, but not necessarily. The backup volume header is not included in the volume size. === BitLocker Drive Encryption (BDE) BitLocker Drive Encryption (BDE) uses the file system signature: "-FVE-FS-". Where FVE is an abbreviation of Full Volume Encryption. The data structures of BDE on Windows Vista and 7 differ. A Windows Vista BDE volume starts with: .... eb 52 90 2d 46 56 45 26 46 53 2d .... A Windows 7 BDE volume starts with: .... eb 58 90 2d 46 56 45 26 46 53 2d .... BDE is largely a stand-alone but has some integration with NTFS. For more information about BDE see https://github.com/libyal/libbde/blob/main/documentation/BitLocker%20Drive%20Encryption%20(BDE)%20format.asciidoc[[LIBBDE\]]. === Volume Shadow Snapshots (VSS) Volume Shadow Snapshots (VSS) uses the GUID 3808876b-c176-4e48-b7ae-04046e6cc752 (stored in little-endian) to identify its data. VSS is largely a stand-alone but has some integration with NTFS. For more information about VSS see https://github.com/libyal/libvshadow/blob/main/documentation/Volume%20Shadow%20Snapshot%20(VSS)%20format.asciidoc[[LIBVSHADOW\]]. === [[media_descriptor]]Media descriptor [cols="1,1,5",options="header"] |=== | Bit(s) | Identifier | Description | 0 | | Sides: + 0 => single-sided + 1 => double-sided | 1 | | Track size: + 0 => 9 sectors per track + 1 => 8 sectors per track | 2 | | Density: + 0 => 80 tracks + 1 => 40 tracks | 3 | | Type: + 0 => Fixed disc + 1 => Removable disc | 4 – 7 | | Always set to 1 |=== === The boot loader [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 512 | | | [yellow-background]*Windows NT (boot) loader* + [yellow-background]*NTLDR/BOOTMGR* |=== == The Master File Table (MFT) The MFT consist of an array of MFT entries. The offset of the MFT table can be found in the volume header and the size of the MFT is defined by the MFT entry of the $MFT metadata file. [NOTE] The MFT can consists of multiple data ranges, defined by the data runs in the $MFT metadata file. === MFT entry Although the size of a MFT entry is defined in the volume header is commonly 1024 bytes in size and consists of: * The MFT entry header * The fix-up values * An array of MFT attribute values * Padding, which should contain 0-byte values [NOTE] The MFT entry can be filled entirely with 0-byte values. Seen in Windows XP for MFT entry indexes 16 - 23. ==== MFT entry header The MFT entry header (FILE_RECORD_SEGMENT_HEADER) is 42 or 48 bytes in size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description 4+| _MULTI_SECTOR_HEADER_ | 0 | 4 | "BAAD" + "FILE" | Signature | 4 | 2 | | The fix-up values offset + Contains an offset relative from the start of the MFT entry + According to `[MSDN]` this value is the update sequence array offset | 6 | 2 | | The number of fix-up values + According to `[MSDN]` this value is the update sequence array size. 4+| | 8 | 8 | | Metadata transaction journal sequence number + Contains a $LogFile Sequence Number (LSN) | 16 | 2 | | Sequence (number) | 18 | 2 | | Reference (link) count | 20 | 2 | | Attributes offset (or first attribute offset) + Contains an offset relative from the start of the MFT entry | 22 | 2 | | Entry flags + See section: <> | 24 | 4 | | Used entry size + Contains the number of bytes of the MFT entry that are in use | 28 | 4 | | Total entry size + Contains the number of bytes of the MFT entry [yellow-background]*Could this be used to store data larger than 1024 - header continuously?* | 32 | 8 | | Base record file reference + See section: <> | 40 | 2 | | First available attribute identifier 4+| _Version 3.0_ | 42 | 2 | | [yellow-background]*Unknown (wfixupPattern)* | 44 | 4 | | [yellow-background]*Unknown* 4+| _Version 3.1_ | 42 | 2 | | [yellow-background]*Unknown (wfixupPattern)* | 44 | 4 | | MFT entry index |=== The base record file reference indicates if the MFT entry is used to store additional attributes for another MFT entry, e.g. for attribute list attributes. According to `[MSDN]` the sequence number is incremented each time that a file record segment is freed; it is 0 if the segment is not used. `[MSDN]` states that the update sequence array must end before the last USHORT value in the first sector. It also claims the update sequence array size value contains the number of bytes. It seems to be more likely to the number of words. The "BAAD" signature presumably indicates a bad MFT entry. `[RUSSON05]` states that during chkdsk, if NTFS finds a multi-sector item where the multi-sector header does not match the values at the end of the sector, it marks the item as "BAAD" and fill it with 0-byte values except for a fix-up value at the end of the first sector. The "BAAD" signature has been seen to be used on Windows NT4 and XP. In NT4 (version 1.2) the MFT entry is 42 bytes in size and the fix-up values are stored at offset 42. This is likely where the field name wfixupPattern originates from. === [[mft_entry_flags]]MFT entry flags [cols="1,1,5",options="header"] |=== | Value | Identifier | Description | 0x0001 | FILE_RECORD_SEGMENT_IN_USE + MFT_RECORD_IN_USE | In use | 0x0002 | FILE_NAME_INDEX_PRESENT + MFT_RECORD_IS_DIRECTORY | Has file name (or $I30) index + When this flag is set the file entry represents a directory (that contains sub file entries) | 0x0004 | MFT_RECORD_IN_EXTEND | [yellow-background]*Unknown* + According to `[APPLE06]` this is set for all system files present in the $Extend directory | 0x0008 | MFT_RECORD_IS_VIEW_INDEX | Is index + When this flag is set the file entry represents an index + According to `[APPLE06]` this is set for all indices other than $I30 |=== === [[file_reference]]The file reference The file reference (FILE_REFERENCE or MFT_SEGMENT_REFERENCE) is 8 bytes in size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 6 | | MFT entry index + Note that the index value in the MFT entry is only 32-bit in size. | 6 | 2 | | Sequence number |=== === [[fix_up_values]]The fix-up values The fix-up values are of variable size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 2 | | Fix-up placeholder value | 2 | 2 x number of fix-up values | | Fix-up (original) value array |=== On disk the last 2 bytes for each 512 bytes block is replaced by the fix-up placeholder value. The original value is stored in the corresponding fix-up (original) value array entry. [NOTE] There can be more fix-up values than the amount of sectors in the data. See `[CARRIER05]` and/or `[RUSSON05]` for examples on applying the fix-up values. === MFT attribute The MFT attribute consist of: * the attribute header * the attribute resident or non-resident data * the <> * [yellow-background]*unknown data likely alignment padding (4-byte alignment)* * the attribute data runs or data * alignment padding (8-byte alignment), can contain remnant data ==== MFT attribute header The MFT attribute header (ATTRIBUTE_RECORD_HEADER) is 16 bytes in size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 4 | | Attribute type (or type code) + See section: <> | 4 | 4 | | Size (or record length) + The size of the attribute including the 8 bytes of the attribute type and size | 8 | 1 | | Non-resident flag (or form code) + 0 => RESIDENT_FORM + 1 => NONRESIDENT_FORM | 9 | 1 | | Name size (or name length) + Contains the number of characters without the end-of-string character | 10 | 2 | | Name offset + Contains an offset relative from the start of the MFT attribute | 12 | 2 | | Attribute data flags + See section: <> | 14 | 2 | | Attribute identifier (or instance) + [yellow-background]*An unique identifier to distinguish between attributes that contain segmented data.* |=== ===== Notes [yellow-background]*Size (or record length) upper 2 bytes overloaded or remnant data?* .... type : 0x000000a0 ($INDEX_ALLOCATION) size : 458832 (0x70050) non resident flag : 0x01 name size : 4 name offset : 64 data flags : 0x0000 identifier : 4 .... ===== [[mft_attribute_data_flags]]MFT attribute data flags [cols="1,1,5",options="header"] |=== | Value | Identifier | Description | 0x0001 | | Is compressed | | | | 0x00ff | ATTRIBUTE_FLAG_COMPRESSION_MASK | | | | | 0x4000 | ATTRIBUTE_FLAG_ENCRYPTED | Is encrypted | 0x8000 | ATTRIBUTE_FLAG_SPARSE | Is sparse |=== [yellow-background]*Does 0x0001 indicate the LZNT1 compression method? Do other values indicate other compression values?* ==== Resident MFT attribute The resident MFT attribute data is present when the non-resident flag is not set (0). The resident data is 8 bytes in size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 4 | | Data size (or value length) | 4 | 2 | | Data offset (or value size) + Contains an offset relative from the start of the MFT attribute | 6 | 1 | | Indexed flag + [yellow-background]*Only the lower bit is used, do the other bits have any significance?* | 7 | 1 | 0x00 | Padding + Contains an empty byte |=== ===== Notes [yellow-background]*What meaning has ATTRIBUTE_FLAG_COMPRESSION_MASK in $INDEX_ROOT attribute? The attribute data is uncompressed.* Seen on Windows 10 (NTFS version 3.1) .... type : 0x00000090 ($INDEX_ROOT) size : 88 non resident flag : 0x00 name size : 4 name offset : 24 data flags : 0x0001 Is compressed .... ==== Non-resident MFT attribute The non-resident MFT attribute data is present when the non-resident flag is set (1). The non-resident data is 48 or 56 bytes in size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 8 | | First (or lowest) Virtual Cluster Number (VCN) of the data | 8 | 8 | | Last (or highest) Virtual Cluster Number (VCN) of the data + [yellow-background]*Seen this value to be -1 in combination with data size of 0* | 16 | 2 | | Data runs offset (or mappings pairs offset) + Contains an offset relative from the start of the MFT attribute | 18 | 2 | | Compression unit size + Contains the compression unit size as `2^(n)` number of cluster blocks. + This value is used for compressed data in the data runs. + [yellow-background]*A value of 0 indicates the attribute data is uncompressed.?* + [yellow-background]*Seen on XP, compressed MFT attribute data with compression unit size of 0.* + [yellow-background]*So it looks more the default compression unit size (16 cluster blocks) should be used.* | 20 | 4 | | Padding + Contains zero-bytes | 24 | 8 | | Allocated data size (or allocated length) + Contains the allocated data size in number of bytes. + This value is not valid if the first VCN is nonzero. | 32 | 8 | | Data size (or file size) + Contains the data size in number of bytes. + This value is not valid if the first VCN is nonzero. | 40 | 8 | | Valid data size (or valid data length) + Contains the valid data size in number of bytes. This value is not valid if the first VCN is nonzero. 4+| _If compression unit size > 0_ | 48 | 8 | | Total allocated size + Contains the total allocated size in number of cluster blocks. |=== [NOTE] The total size of the data runs should be larger or equal to the data size. [NOTE] Windows will fill data ranges beyond the valid data size with 0-byte values. The data size remains unchanged. This applies to compressed and uncompressed data. If the first VCN is zero a valid data size of 0 represents a file entirely filled with 0-byte values. ==== [[attribute_name]]Attribute name The attribute name is of variable size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | ... | | Name + Contains an UTF-16 little-endian without end-of-string character |=== ==== Data runs The data runs are stored in a variable size (data) runlist. This runlist consists of runlist elements. A runlist element is of variable size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0.0  | 4 bits | | Number of cluster blocks value size + Contains the number of bytes used to store the data run size | 0.4 | 4 bits | | Cluster block number value size + Contains the number of bytes used to store the data run size | 1 | Size value size | | Data run number of cluster blocks + Contains the number of cluster blocks | ... | Cluster block number value size | | Data run cluster block number + See below. |=== The data run cluster block number is a singed value, where the MSB is the singed bit, e.g. if the data run cluster block contains \'dbc8' it corresponds to the 64-bit value 0xffffffffffffdbc8. The first data run offset contains the absolute cluster block number where successive data run offsets are relative to the last data run offset. [NOTE] The cluster block number byte size is the first nibble when reading the byte stream, but here it is represented as the upper nibble of the first byte. The last runlist element is an empty value size tuple; in other words a 0 byte. [yellow-background]*Does a data run with a "number of cluster blocks value size" of 0 represent this as well?* The MFT attribute data flag (ATTRIBUTE_FLAG_SPARSE) indicates if the data stream is sparse or not. A sparse data run has a "cluster block number value size" 0, representing there is no offset (cluster block number). A sparse data run should be filled with 0-byte values. [NOTE] Compressed files also define sparse data runs without setting the sparse flag. [yellow-background]*TODO: what about data runs with a cluster block number value size of 0 but without the necessary flags? Seen in ADS: $BadClus:$Bad. Assuming for now the data run is sparse.* The MFT attribute data flags (0x00ff) indicate if the data stream is compressed or not. The currently known value for LZNT1 compression is 1. [NOTE] Windows 10 supports Windows Overlay Filter (WOF) compressed data, which stores the LZXPRESS Huffman or LZX compressed data in alternate data stream named WofCompressedData and links it to the default data stream using a reparse point. The data is stored in compression unit blocks. A compression unit typically consists of 16 cluster blocks. However the actual value is stored in the non-resident MFT attribute. See <> for more information on how to determine which data runs store the compressed and which do not. [NOTE] Compression is supported upto NTFS file systems with a cluster block size of 4096 bytes or less. The compression is specified on a pre attribute basis. Where an attribute chain can consists of attribute with compressed and uncompressed attribute data. [yellow-background]*Note that it is unknown if mixing compressed and uncompressed attributes is supported by the Windows implementation.* According to `[RUSSON05]` the size of the runlist is rounded up to the next multitude of 4 bytes. The size of the trailing data can be even larger than 3 and are not always zero-bytes. See `[CARRIER05]` and/or `[RUSSON05]` for examples on reading the runlist. == The attributes === [[attribute_types]]The attribute types Technically the attribute types are stored in the `$AttrDef` metadata file. Also see section: <> [cols="1,1,5",options="header"] |=== | Value | Identifier | Description | 0x00000000 | | Unused | 0x00000010 | $STANDARD_INFORMATION | Standard information | 0x00000020 | $ATTRIBUTE_LIST | Attributes list | 0x00000030 | $FILE_NAME | The file or directory name | 0x00000040 | $VOLUME_VERSION | Volume version + Removed in NTFS version 3.0 | 0x00000040 | $OBJECT_ID | Object identifier + Introduced in NTFS version 3.0 | 0x00000050 | $SECURITY_DESCRIPTOR | Security descriptor | 0x00000060 | $VOLUME_NAME | Volume name | 0x00000070 | $VOLUME_INFORMATION | Volume information | 0x00000080 | $DATA | Data stream | 0x00000090 | $INDEX_ROOT | Index root | 0x000000a0 | $INDEX_ALLOCATION | Index allocation | 0x000000b0 | $BITMAP | Bitmap | 0x000000c0 | $SYMBOLIC_LINK | Symbolic link + Removed in NTFS version 3.0 | 0x000000c0 | $REPARSE_POINT | Reparse point + Introduced in NTFS version 3.0 | 0x000000d0 | $EA_INFORMATION | (HPFS) extended attribute information | 0x000000e0 | $EA | (HPFS) extended attribute | 0x000000f0 | $PROPERTY_SET | Property set + Removed in NTFS version 3.0 | 0x00000100 | $LOGGED_UTILITY_STREAM | Logged utility stream + Introduced in NTFS version 3.0 | | | | 0x00001000 | | First user defined attribute | | | | 0xffffffff | | End of attributes marker |=== === The standard information attribute The standard information attribute ($STANDARD_INFORMATION) contains the basic file entry metadata. It is stored as a resident MFT attribute. The standard information data (STANDARD_INFORMATION) is either 48 or 72 bytes in size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 8 | | Creation date and time + Contains a FILETIME | 8 | 8 | | Last modification date and time + (Also referred to as last written date and time) + Contains a FILETIME | 16 | 8 | | MFT entry last modification date and time + Contains a FILETIME | 24 | 8 | | Last access date and time + Contains a FILETIME | 32 | 4 | | File attribute flags + See section: <> | 36 | 4 | | [yellow-background]*Unknown (Maximum number of versions)* + [yellow-background]*What does it contain and what is it used for?* | 40 | 4 | | [yellow-background]*Unknown (Version number)* + [yellow-background]*What does it contain and what is it used for?* + [yellow-background]*On Windows 10 does a value of 1 indicate case-senstive folder?* | 44 | 4 | | [yellow-background]*Unknown (Class identifier)* + [yellow-background]*What does it contain and what is it used for?* 4+| _Introduced in NTFS version 3.0_ | 48 | 4 | | Owner identifier + [yellow-background]*What does it contain and what is it used for?* | 52 | 4 | | Security descriptor identifier + Contains the entry number in the security ID index ($Secure:$SII) + See section: <> | 56 | 8 | | Quota charged + [yellow-background]*What does it contain and what is it used for?* + [yellow-background]*Does this value correspond to StorageReservedID in fsutil layout output?* | 64 | 8 | | Update Sequence Number (USN) + [yellow-background]*What does it contain and what is it used for?* |=== [NOTE] MFT entries without a $STANDARD_INFORMATION attribute but with other attributes, such as $FILE_NAME, and an $I30 index have been observed. === The attribute list attribute The attribute list attribute ($ATTRIBUTE_LIST) is a list of attributes in an MFT entry. The attributes stored in the list are placeholders for other attributes. Some of these attributes could not be stored in the MFT entry due to space limitations. The attribute list attribute can be stored as either a resident (for a small amount of data) and non-resident MFT attribute. The attribute list data contains an array of attribute list entries and stored as a continous stream accross one or more cluster blocks. Note that MFT entry 0 also can contain an attribute list and allows to store listed attributes beyond the first data run. ==== The attribute list entry The attribute list entry consists of: * the attribute list entry header * the <> * alignment padding (8-byte alignment), can contain remnant data ===== The attribute list entry header The attribute list entry header (ATTRIBUTE_LIST_ENTRY) is 26 bytes in size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 4 | | Attribute type (or type code) + See section: <> | 4 | 2 | | Size (or record length) + The size of the attribute including the 6 bytes of the attribute type and size | 6 | 1 | | Name size (or name length) + Contains the number of characters without the end-of-string character | 7 | 1 | | Name offset + Contains an offset relative from the start of the attribute list entry | 8 | 8 | | Data first (or lowest) VCN | 16 | 8 | | File reference (or segment reference) + The file reference to the MFT entry that contains (part of) the attribute data + See section: <> | 24 | 2 | | Attribute identifier + [yellow-background]*An unique identifier to distinguish between attributes that contain segmented data.* |=== The data first VCN is used when the attribute data is stored. The attribute list contains an attribute list entry for every cluster block. The corresponding cluster block will contain an MFT attribute containing the attribute data. See `[CARRIER05]` pages 365 and 366 for more information. === [[file_name_attribute]]The file name attribute The file name attribute ($FILE_NAME) contains the basic file system information, like the parent file entry, MAC times and filename. It is stored as a resident MFT attribute. The file name data (FILE_NAME) is of variable size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 8 | | Parent file reference + See section: <> | 8 | 8 | | Creation date and time + Contains a FILETIME | 16 | 8 | | Last modification date and time + (Also referred to as last written date and time) + Contains a FILETIME | 24 | 8 | | MFT entry last modification date and time + Contains a FILETIME | 32 | 8 | | Last access date and time + Contains a FILETIME | 40 | 8 | | Allocated (or reserved) file size + See below. | 48 | 8 | | File size + See below. | 56 | 4 | | File attribute flags + See section: <> | 60 | 4 | | Extended data + See below. | 64 | 1 | | Name string size + Contains the number of characters without the end-of-string character | 65 | 1 | | Namespace of the name string | 66 | ... | | Name string Contains an UTF-16 little-endian without an end-of-string character |=== [NOTE] The name string is not strict UTF-16 since it allows for unpaired surrogates, such as "U+d800" and "U+dc00". The extended data contains: * the reparse point tag (see section <>) if the reparse point file attribute flag (FILE_ATTRIBUTE_REPARSE_POINT) is set; * [yellow-background]*the extended attribute data size.* The allocated file size and file size values do not always contain accurate values when stored in a MFT attribute, see `[CARRIER05]` page 363 for more information. [CARRIER05] also states that the file size values are accurate when 'used in a directory index' (stored in an index value), however this seems to be true for most files but not for all. At least the $MFT and $MFTMirr metadata file directory entries on a Windows Vista NTFS volume were found to contain the same value as the corresponding MFT entries, which were not equal to the size of the data stream. An MFT attribute can contain multiple file name attributes, e.g. for a separate (long) name and short name. In several cases on a Vista NTFS volume the MFT entry contained both a DOS & Windows and POSIX name space `$FILE_NAME` attribute. However the directory entry index (`$I30`) of the parent directory only contained the DOS & Windows name. In case of a hard link the MFT entry will contain additional file name attributes with the parent file reference of each hard link. ==== Namespace [cols="1,1,5",options="header"] |=== | Value | Identifier | Description | 0 | POSIX | Case sensitive character set that consists of all Unicode characters except for: + \0 (zero character), + / (forward slash). + + The : (colon) is valid for NTFS but not for Windows. | 1 | FILE_NAME_NTFS (or WINDOWS) | A case insensitive sub set of the POSIX character set that consists of all Unicode characters except for: + " * / : < > ? \ \| + + Note that names cannot end with a . (dot) or ' ' (space). | 2 | FILE_NAME_DOS (or DOS) | A case insensitive sub set of the WINDOWS character set that consists of all upper case ASCII characters except for: + " * + , / : ; < = > ? \ + + Note the name must follow the 8.3 format. | 3 | DOS_WINDOWS | Both the DOS and WINDOWS names are identical + [yellow-background]*Which is the same as the DOS character set, with the exception that lower case is used as well.* |=== [NOTE] The Windows API function CreateFile allows to create case sensitive file names when the flag FILE_FLAG_POSIX_SEMANTICS is set. ==== Long to short name conversion Basically the conversion from a long name to short name boils down to the approach mentioned below. Note that it differs from the approach mentioned in `[RUSSON05]`, in regard of the third case to make the short name unique. In the long name: * ignore Unicode characters beyond the first 8-bit (extended ASCII) * ignore control characters and spaces (character < 0x20) * ignore non-allowed characters (" * + , / : ; < = > ? \) * ignore dots except the last one, which is used for the extension * make all letters upper case Additional observations: * `[` or `]` are replaced by an underscore (`_`) Make the name unique: 1. use the characters 1 to 6 add ~1 and if the long name has an extension add the a dot and its first 3 letters 2. if the name already exists try \~2 up to ~9 3. if the name already exists use [yellow-background]*some 16-bit hexadecimal value* for characters 3 to 6 with ~1 [yellow-background]*`[MSDN]` Generates the next four letters of the short file name by mathematically manipulating the remaining letters of the long file name.* [yellow-background]*Note: behavior dependent on fsutil?* case 1: "Program Files" becomes "PROGRA~1" or " ~PLAYMOVIE.REG" becomes "\~PLAYM~1.REG" case 2: "Program Data", in the same directory as "Program Files", becomes "PROGRA~2" case 3: "x86_microsoft-windows-r..ry-editor.resources_31bf3856ad364e35_6.0.6000.16386_en-us_f89a7b0005d42fd4", in a directory with a lot of filenames starting with "x86_microsoft", becomes "X8FCA6~1.163" === The volume version attribute The volume version attribute ($VOLUME_VERSION) contains [yellow-background]*TODO* [yellow-background]*Need a pre NTFS 3.0 volume with this attribute. $AttrDef indicates the attribute to be 8 bytes in size.* === The object identifier attribute The object identifier attribute ($OBJECT_ID) contains distributed link tracker properties. It is stored as a resident MFT attribute. The object identifier data is either 16 or 64 bytes in size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 16 | | Droid file identifier + Contains a GUID | 16 | 16 | | Birth droid volume identifier + Contains a GUID | 32 | 16 | | Birth droid file identifier + Contains a GUID | 48 | 16 | | Birth droid domain identifier + Contains a GUID |=== Droid in this context refers to CDomainRelativeObjId. === The security descriptor attribute [yellow-background]*TODO: does this override any value in $Secure:$SDS?* The security descriptor attribute ($SECURITY_DESCRIPTOR) contains a Windows NT security descriptor. It can be stored as either a resident (for a small amount of data) and non-resident MFT attribute. See: https://github.com/libyal/libfwnt/blob/main/documentation/Security%20Descriptor.asciidoc[[LIBFWNT\]] === The volume name attribute The volume name attribute ($VOLUME_NAME) contains the name of the volume. It is stored as a resident MFT attribute. The volume name data is of variable size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | ... | | Name string + Contains an UTF-16 little-endian without an end-of-string character |=== The volume name attribute is used in the $Volume metadata file MFT entry. === The volume information attribute The volume information attribute ($VOLUME_INFORMATION) contains information about the volume. It is stored as a resident MFT attribute. The volume information data is 12 bytes in size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 8 | | [yellow-background]*Unknown (empty value?)* | 8 | 1 | | Major version number | 9 | 1 | | Minor version number | 10 | 2 | | Volume flags |=== The volume information attribute is used in the $Volume metadata file MFT entry. ==== Volume flags [cols="1,1,5",options="header"] |=== | Value | Identifier | Description | 0x0001 | VOLUME_IS_DIRTY | [yellow-background]*Is dirty* | 0x0002 | VOLUME_RESIZE_LOG_FILE | [yellow-background]*Re-size journal (LogFile)* | 0x0004 | VOLUME_UPGRADE_ON_MOUNT | [yellow-background]*Upgrade on next mount* | 0x0008 | VOLUME_MOUNTED_ON_NT4 | [yellow-background]*Mounted on Windows NT 4* | 0x0010 | VOLUME_DELETE_USN_UNDERWAY | [yellow-background]*Delete USN underway* | 0x0020 | VOLUME_REPAIR_OBJECT_ID | [yellow-background]*Repair object identifiers* | | | | 0x0080 | | [yellow-background]*Unknown* | | | | 0x4000 | VOLUME_CHKDSK_UNDERWAY | [yellow-background]*chkdsk underway* | 0x8000 | VOLUME_MODIFIED_BY_CHKDSK | [yellow-background]*Modified by chkdsk* |=== === The data stream attribute The data stream attribute ($DATA) contains the file data. It can be stored as either a resident (for a small amount of data) and non-resident MFT attribute. Also note that multiple data attributes for the same data stream can be used in the attribute list to define different parts of the data stream data. The first data stream attribute will contain the size of the entire data stream data. Other data stream attributes should have a size of 0. Also see: <>. === The index root attribute The index root attribute ($INDEX_ROOT) contains the root of the index tree. It is stored as a resident MFT attribute. See section: <> and <>. === The index allocation attribute The index allocation attribute ($INDEX_ALLOCATION) contains an array of index entries. It is stored as a non-resident MFT attribute. Note that the index allocation attribute itself does not define which attribute type it contains in the index value data. For this information it needs the corresponding index root attribute. Also note that multiple index allocation attributes for the same index can be used in the attribute list to define different parts of the index allocation data. The first index allocation attribute will contain the size of the entire index allocation data. Other index allocation attributes should have a size of 0. Also see: <>. See section: <>. === The bitmap attribute The bitmap attribute ($BITMAP) contains the allocation bitmap. It can be stored as either a resident (for a small amount of data) and non-resident MFT attribute. It is used to maintain information about which entry is used and which is not. Every bit in the bitmap represents an entry. The index is stored byte-wise with the LSB of the byte corresponds to the first allocation element; the allocation element can represent several things, see below. The allocation element is allocated if the corresponding bit contains 1 or unallocated if 0. It is known to be used in: * the MFT (nameless), where an allocation element represents a MFT entry; * indexes ($I##), where an allocation element represents an index entry. === The symbolic link attribute The symbolic link attribute ($SYMBOLIC_LINK) contains [yellow-background]*TODO* [yellow-background]*Need a pre NTFS 3.0 volume with this attribute. $AttrDef indicates the attribute is of variable size.* === The reparse point attribute The reparse point attribute ($REPARSE_POINT) contains information about a file system-level link. It is stored as a resident MFT attribute. See section: <>. === The (HPFS) extended attribute information The (HPFS) extended attribute information ($EA_INFORMATION) contains information about the extended attribute ($EA). The extended attribute information data is 8 bytes in size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 2 | | Size of an extended attribute entry | 2 | 2 | | Number of extended attributes which have NEED_EA set + [yellow-background]*TODO: determine what this flag is used for* | 4 | 4 | | Size of the extended attribute ($EA) data |=== E.g. .... 00000000: 08 00 00 00 18 00 00 00 ........ .... === The (HPFS) extended attribute The (HPFS) extended attribute ($EA) contains the extended attribute data. The extended attribute data is of variable size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 4 | | Offset to next extended attribute entry + The offset is relative from the start of the extended attribute data | 4 | 1 | | Flags + 0x80 => NEED_EA (Need EA) flag | 5 | 1 | | Number of characters of the extended attribute name | 6 | 2 | | Value data size | 8 | ... | | The extended attribute name + Contains an ASCII string + [yellow-background]*TODO: is this value 16-bit aligned?* | ... | ... | | Value data | ... | ... | | [yellow-background]*TODO: unknown trailing data* |=== E.g. .... 00000000: 18 00 00 00 00 09 04 00 2e 55 4e 49 58 41 54 54 ........ .UNIXATT 00000010: 52 00 b6 01 00 00 03 87 R....... .... ==== UNITATTR extended attribute value data [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 4 | | [yellow-background]*TODO: is this an equivalent of st_mode?* |=== === The property set attribute The property set attribute ($PROPERTY_SET) contains [yellow-background]*TODO* [yellow-background]*Need a pre NTFS 3.0 volume with this attribute. $AttrDef indicates does not seem to always define this attribute.* === The logged utility stream attribute [yellow-background]*attribute type for storing additional data for the files and directories* [yellow-background]*resident, known to cause problems when non-resident on Windows Vista* [cols="1,1,5",options="header"] |=== | Value | Identifier | Description | $EFS | | Encrypted NTFS (EFS) | $TXF_DATA | | Transactional NTFS (TxF) |=== [yellow-background]*TODO add text* === [[attribute_chains]]Attribute chains Multiple attributes can make up a single attribute, e.g. the attributes: 1. $INDEX_ALLOCATION ($I30) VCN: 0 2. $INDEX_ALLOCATION ($I30) VCN: 596 The first attribute will contain the size of the data defined by all the attributes. Other attributes should have a size of 0. It is assumed that the attributes in a chain must be continuous and defined in-order. == [[attribute_types]]The attribute types The attribute types are stored in the `$AttrDef` metadata file. [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 128 | | Attribute name + Contains an UTF-16 little-endian [yellow-background]*with end-of-string character?* + [yellow-background]*The unused bytes are filled with 0-byte values* | 128 | 4 | | Attribute type (or type code) | 132 | 8 | | [yellow-background]*Unknown (empty values?)* | 140 | 4 | | [yellow-background]*Unknown (flags?)* Seen: 0x40, 0x42, 0x80 | 144 | 8 | | [yellow-background]*Unknown (minimum attribute size?)* | 152 | 8 | | [yellow-background]*Unknown (maximum attribute size?)* + Seen: -1 (no maximum?), 48 |=== .... 00000000 24 00 53 00 54 00 41 00 4e 00 44 00 41 00 52 00 |$.S.T.A.N.D.A.R.| 00000010 44 00 5f 00 49 00 4e 00 46 00 4f 00 52 00 4d 00 |D._.I.N.F.O.R.M.| 00000020 41 00 54 00 49 00 4f 00 4e 00 00 00 00 00 00 00 |A.T.I.O.N.......| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000080 10 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 |............@...| 00000090 30 00 00 00 00 00 00 00 30 00 00 00 00 00 00 00 |0.......0.......| 000000a0 24 00 41 00 54 00 54 00 52 00 49 00 42 00 55 00 |$.A.T.T.R.I.B.U.| 000000b0 54 00 45 00 5f 00 4c 00 49 00 53 00 54 00 00 00 |T.E._.L.I.S.T...| 000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000120 20 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 | ...............| 00000130 00 00 00 00 00 00 00 00 ff ff ff ff ff ff ff ff |................| 00000140 24 00 46 00 49 00 4c 00 45 00 5f 00 4e 00 41 00 |$.F.I.L.E._.N.A.| .... == [[index]]The index The index structures are used for various purposes one of which are the directory entries. The root of the index is stored in index root. The index root attribute defines which type of attribute is stored in the index and the root index node. If the index is too large part of the index is stored in an index allocation attribute with the same attribute name. The index allocation attribute defines a data stream which contains index entries. Each index entry contains an index node. See `[CARRIER05]` page 378 for an illustration how the index root and index allocation attribute relate. An index consists of a tree, where both the branch and index leaf nodes contain the actual data. E.g. in case of a directory entries index, any node that contains index value data make up for the directory entries. The index value data in a branch node signifies the upper bound of the values in the that specific branch. E.g. if directory entries index branch node contains the name 'textfile.txt' all names in that index branch are smaller than 'textfile.txt'. Note the actual sorting order is dependent on the collation type defined in the index root attribute. The index allocation attribute is accompanied by a bitmap attribute with the corresponding attribute name. The bitmap attribute defines the allocation of virtual cluster blocks within the index allocation attribute data stream. [NOTE] The index allocation attribute can be present even though it is not used. === Common used indexes Indexes commonly used by NTFS are: [cols="1,1,5",options="header"] |=== | Value | Identifier | Description | $I30 | | Directory entries (used by directories) | $SDH | | Security descriptor hashes (used by $Secure) | $SII | | Security descriptor identifiers (used by $Secure) | $O | | Object identifiers (used by $ObjId) | $O | | Owner identifiers (used by $Quota) | $Q | | Quotas (used by $Quota) | $R | | Reparse points (used by $Reparse) |=== === [[index_root]]The index root The index root consists of: * index root header * index node header * an array of index values ==== The index root header The index root header is 16 bytes in size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 4 | | Attribute type + Contains the type of the indexed attribute or 0 if none | 4 | 4 | | Collation type + Contains a value to indicate the ordering of the index entries + See section: <> | 8 | 4 | | Index entry size | 12 | 4 | | Index entry number of cluster blocks |=== [NOTE] `[CARRIER05]` and `[RUSSON05]` state that the last 3 bytes are unused (alignment padding). However it is highly probably that the last value is 32-bit in size. [NOTE] In NT4 (version 1.2) the index entry size does not have to match the index entry size in the volume header. The correct size seems to be the value in the index root header. ==== [[collation_type]]Collation type [cols="1,1,5",options="header"] |=== | Value | Identifier | Description | 0x00000000 | COLLATION_BINARY | Binary + The first byte is most significant | 0x00000001 | COLLATION_FILENAME | Unicode strings case-insensitive | 0x00000002 | COLLATION_UNICODE_STRING | Unicode strings case-sensitive + Upper case letters should come first | | | | 0x00000010 | COLLATION_NTOFS_ULONG | Unsigned 32-bit little-endian integer | 0x00000011 | COLLATION_NTOFS_SID | NT security identifier (SID) | 0x00000012 | COLLATION_NTOFS_SECURITY_HASH | Security hash first, then NT security identifier | 0x00000013 | COLLATION_NTOFS_ULONGS | An array of unsigned 32-bit little-endian integer values |=== === The index entry The index entry consists of: * the index entry header * the index node header * the fix-up values * alignment padding (8-byte alignment), contains zero-bytes * an array of index values ==== The index entry header The index entry header is 24 bytes in size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 4 | "INDX" | Signature | 4 | 2 | | The fix-up values offset + Contains an offset relative from the start of the index entry header. | 6 | 2 | | The number of fix-up values | 8 | 8 | | Metadata transaction journal sequence number + Contains a $LogFile Sequence Number (LSN) | 16 | 8 | | Virtual Cluster Number (VCN) of the index entry |=== [NOTE] There can be more fix-up value than supported by the index entry data size. === The index node header The index node header is 16 bytes in size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 4 | | Index values offset + The offset is relative from the start of the index node header | 4 | 4 | | Index node size + The value includes the size of the index node header. See below. | 8 | 4 | | Allocated index node size + The value includes the size of the index node header | 12 | 4 | | Index node flags + See section: <> |=== Note that `[RUSSON05]` states that the last 3 bytes are unused (alignment padding), while `[CARRIER05]` states that the last value is 32-bit in size. Here we assume that the index node flags are a 32-bit value. In an index entry (index allocation attribute) the index node size includes the size of the fix-up values and the alignment padding following it. The remainder of the index node contains remnant data and/or zero-byte values. ==== [[index_node_flags]]The index node flags [cols="1,1,5",options="header"] |=== | Value | Identifier | Description | 0x00000001 | | Is branch node + Used to indicate if the node is a branch node that has sub nodes |=== === The index value The index value is of variable size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 8 | | File reference + See section: <> | 8 | 2 | | Index value size | 10 | 2 | | Index key data size | 12 | 4 | | Index value flags 4+| _If index key data size > 0_ | 16 | ... | | Index key data | ... | ... | | Index value data 4+| _If index value flag 0x00000001 (is branch node) is set_ | ... | 8 | | Sub node Virtual Cluster Number (VCN) |=== [NOTE] The index values ared stored 8 byte aligned. [NOTE] Some sources define the index value flags as a 16-bit value followed by 2 bytes of padding. ==== The index value flags [cols="1,1,5",options="header"] |=== | Value | Identifier | Description | 0x00000001 | | Has sub node + If set the index value contains a sub node Virtual Cluster Number (VCN) | 0x00000002 | | Is last + If set the index value is the last in the index values array |=== === Index key and value data ==== Directory entry index value The MFT attribute name of the directory entry index is: $I30. The directory entry index value contains a file name attribute in the index key data. See section: <>. The index value data seems to contain remnant data. [NOTE] Both the short and long names of the same file have a separate index value. The short name uses the DOS name space and the long name the WINDOWS name space. [yellow-background]*Index values with a single name use either the POSIX or DOS_WINDOWS name space?* A hard link to a file in the same directory will also have a separate index value. [yellow-background]*Does the hard link always has POSIX name space?* ==== Security descriptor hash index value The MFT attribute name of the security descriptor hash index is: $SDH. It appears to only to be used by the $Secure metadata file. See section: <> ==== Security descriptor identifier index value The MFT attribute name of the security descriptor identifier index is: $SII. It appears to only to be used by the $Secure metadata file. See section: <> == [[compression]]Compression Typically NTFS compression groups 16 cluster blocks together. This group of 16 cluster blocks also named a compression unit is either \'compressed' or uncompressed data. The term compressed is quoted here because, as you will see below, the group of cluster blocks can also contain uncompressed data. A group of cluster blocks is \'compressed' when it is compressed size is smaller than its uncompressed data size. [NOTE] The actual compression unit size is stored in the non-resident MFT attribute. Within a group of cluster blocks each of the 16 blocks is \'compressed' individually see <>. The maximum uncompressed data size is always the cluster size (in most cases 4096). The data runs in the $DATA stream define cluster block ranges. A simple example: .... 21 02 35 52 .... This data run defines 2 data blocks starting at block number 21045 followed by 14 sparse blocks. The total number of blocks is 16 which is the size of the compression unit. The data is stored compressed in the first 2 blocks and the 14 sparse blocks are only there to make sure the data runs add up to the compression unit size. They do not define actual sparse data. Another example: .... 21 40 37 52 .... This data run defines 64 data blocks starting at block number 21047. Since this data run is larger than the compression unit size the data is stored uncompressed. If the data run was e.g. 60 data blocks followed by 4 sparse blocks the first 3 compression units (blocks 1 to 48) would be uncompressed and the last compression unit (blocks 49 to 64) would be compressed. Also "sparse data" and "sparse compression unit" data runs can be mixed. If in the previous example the 60 data blocks would be followed by 20 sparse blocks the last compression unit (blocks 65 to 80) would be sparse. [NOTE] A compression unit can consists of multiple compressed data runs, e.g. 1 data block followed by 4 data blocks followed by 11 sparse blocks. Data runs have been observed where the last data run size does not align with the compression unit size. [NOTE] The sparse blocks data run can be stored in a subsequent attribute in an attribute chain and can be stored in multiple data runs. [yellow-background]*Does the sparse flag needs to be set for sparse compressed files?* [yellow-background]*Is resident data is always uncompressed?* Also see `[RUSSON05]` for more detailed examples. === [[compression_block_based_storage]]Block based storage NTFS compression stores the \'compressed' data in blocks. Each block has a 2 byte block header. The block is of variable size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 2 | | Block size | 2 | (compressed data size) | | |=== The upper 4 bits of the block size are used as flags. [cols="1,5",options="header"] |=== | Bit(s) | Description | 0 - 11 | Compressed data size | 12 - 14 | [yellow-background]*Unknown flags* | 15 | Data is compressed |=== === LZNT1 compression method For more information about LZNT1 see: https://github.com/libyal/libfwnt/blob/main/documentation/Compression%20methods.asciidoc[[LIBFWNT\]] Also see section: <> === Windows Overlay Filter (WOF) compressed data A MFT entry that contains Windows Overlay Filter (WOF) compressed data has the following attributes: * reparse point attribute with tag 0x80000017, which defines the compression method * a nameless data attribute that is sparse and contains the uncompressed data size * a data attribute named WofCompressedData that contains LZXPRESS Huffman or LZX compressed data [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description 4+| _Chunk offset table_ | 0 | ... | | Array of 32-bit of 64-bit compressed data chunk offsets + The offset is relative from the start of the data chunks 4+| _Data chunks_ | ... | ... | | One or more compressed or uncompressed data chunks |=== [NOTE] If the chunk size equals the size of the uncompressed data the chunk is stored (as-is) uncompressed. The size of the chunk offset table is: .... number of chunk offsets = uncompressed size / compression unit size .... The offset of the first compressed data chunk is at the end of the chunk offset table and is not stored in the chunk offset table. For more information about the compression methods see section <> == [[reparse_point]]The reparse point The reparse point is used to create file system-level links. Reparse data is stored in the reparse point attribute. The reparse point data (REPARSE_DATA_BUFFER) is of variable size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 4 | | Reparse point tag | 4 | 2 | | Reparse data size | 6 | 2 | 0 | [yellow-background]*Unknown (Reserved)* | 8 | ... | | Reparse data |=== [yellow-background]*What about the GUID mentioned in `[RUSSON05]` in third party reparse points.* [yellow-background]*`[MSDN]` ReparseGuid: A 16-byte GUID that uniquely identifies the owner of the reparse point. Reparse pointGUIDs are assigned by the implementer of a file system, the file system filter driver, or the minifilter driver. The implementer must generate one GUID to use with their assigned reparse point tag, and must always use this GUID as the ReparseGuid for that tag.* === [[reparse_point_tag]]Reparse point tag [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0.0  | 16 bits | | Type | 2.0  | 12 bits | | [yellow-background]*Unknown (Reserved)* | 3.4 | 4 bits | | Flags |=== ==== Predefined reparse point tag values Predefined reparse point tag values according to `[MSDN]`: [cols="1,1,5",options="header"] |=== | Value | Identifier | Description | 0x00000000 | IO_REPARSE_TAG_RESERVED_ZERO | [yellow-background]*Unknown (Reserved)* | 0x00000001 | IO_REPARSE_TAG_RESERVED_ONE | [yellow-background]*Unknown (Reserved)* | 0x00000002 | IO_REPARSE_TAG_RESERVED_TWO | [yellow-background]*Unknown (Reserved)* | | | | 0x80000005 | IO_REPARSE_TAG_DRIVE_EXTENDER | Used by Home server drive extender | 0x80000006 | IO_REPARSE_TAG_HSM2 | Used by Hierarchical Storage Manager Product | 0x80000007 | IO_REPARSE_TAG_SIS | Used by single-instance storage (SIS) filter driver | 0x80000008 | IO_REPARSE_TAG_WIM | Used by the WIM Mount filter | 0x80000009 | IO_REPARSE_TAG_CSV | Used by Clustered Shared Volumes (CSV) version 1 | 0x8000000a | IO_REPARSE_TAG_DFS | Used by the Distributed File System (DFS) | 0x8000000b | IO_REPARSE_TAG_FILTER_MANAGER | Used by filter manager test harness | | | | 0x80000012 | IO_REPARSE_TAG_DFSR | Used by the Distributed File System (DFS) | 0x80000013 | IO_REPARSE_TAG_DEDUP | Used by the Data Deduplication (Dedup) | 0x80000014 | IO_REPARSE_TAG_NFS | Used by the Network File System (NFS) | 0x80000015 | IO_REPARSE_TAG_FILE_PLACEHOLDER | Used by Windows Shell for placeholder files | 0x80000016 | IO_REPARSE_TAG_DFM | Used by Dynamic File filter | 0x80000017 | IO_REPARSE_TAG_WOF | Used by Windows Overlay Filter (WOF), for either WIMBoot or compression + See section: <> | 0x80000018 | IO_REPARSE_TAG_WCI | Used by Windows Container Isolation (WCI) + See section: <> | | | | 0x8000001b | IO_REPARSE_TAG_APPEXECLINK | Used by Universal Windows Platform (UWP) packages to encode information that allows the application to be launched by CreateProcess | | | | 0x8000001e | IO_REPARSE_TAG_STORAGE_SYNC | Used by the Azure File Sync (AFS) filter | | | | 0x80000020 | IO_REPARSE_TAG_UNHANDLED | Used by Windows Container Isolation (WCI) | 0x80000021 | IO_REPARSE_TAG_ONEDRIVE | [yellow-background]*Unknown (Not used)* | | | | 0x80000023 | IO_REPARSE_TAG_AF_UNIX | Used by the Windows Subsystem for Linux (WSL) to represent a UNIX domain socket | 0x80000024 | IO_REPARSE_TAG_LX_FIFO | Used by the Windows Subsystem for Linux (WSL) to represent a UNIX FIFO (named pipe) | 0x80000025 | IO_REPARSE_TAG_LX_CHR | Used by the Windows Subsystem for Linux (WSL) to represent a UNIX character special file | 0x80000036 | IO_REPARSE_TAG_LX_BLK | Used by the Windows Subsystem for Linux (WSL) to represent a UNIX block special file | | | | 0x9000001c | IO_REPARSE_TAG_PROJFS | Used by the Windows Projected File System filter, for files managed by a user mode provider such as VFS for Git | | | | 0x90001018 | IO_REPARSE_TAG_WCI_1 | Used by Windows Container Isolation (WCI) | | | | 0x9000101a | IO_REPARSE_TAG_CLOUD_1 | Used by the Cloud Files filter, for files managed by a sync engine such as OneDrive | | | | 0x9000201a | IO_REPARSE_TAG_CLOUD_2 | Used by the Cloud Files filter, for files managed by a sync engine such as OneDrive | | | | 0x9000301a | IO_REPARSE_TAG_CLOUD_3 | Used by the Cloud Files filter, for files managed by a sync engine such as OneDrive | | | | 0x9000401a | IO_REPARSE_TAG_CLOUD_4 | Used by the Cloud Files filter, for files managed by a sync engine such as OneDrive | | | | 0x9000501a | IO_REPARSE_TAG_CLOUD_5 | Used by the Cloud Files filter, for files managed by a sync engine such as OneDrive | | | | 0x9000601a | IO_REPARSE_TAG_CLOUD_6 | Used by the Cloud Files filter, for files managed by a sync engine such as OneDrive | | | | 0x9000701a | IO_REPARSE_TAG_CLOUD_7 | Used by the Cloud Files filter, for files managed by a sync engine such as OneDrive | | | | 0x9000801a | IO_REPARSE_TAG_CLOUD_8 | Used by the Cloud Files filter, for files managed by a sync engine such as OneDrive | | | | 0x9000901a | IO_REPARSE_TAG_CLOUD_9 | Used by the Cloud Files filter, for files managed by a sync engine such as OneDrive | | | | 0x9000a01a | IO_REPARSE_TAG_CLOUD_A | Used by the Cloud Files filter, for files managed by a sync engine such as OneDrive | | | | 0x9000b01a | IO_REPARSE_TAG_CLOUD_B | Used by the Cloud Files filter, for files managed by a sync engine such as OneDrive | | | | 0x9000c01a | IO_REPARSE_TAG_CLOUD_C | Used by the Cloud Files filter, for files managed by a sync engine such as OneDrive | | | | 0x9000d01a | IO_REPARSE_TAG_CLOUD_D | Used by the Cloud Files filter, for files managed by a sync engine such as OneDrive | | | | 0x9000e01a | IO_REPARSE_TAG_CLOUD_E | Used by the Cloud Files filter, for files managed by a sync engine such as OneDrive | | | | 0x9000f01a | IO_REPARSE_TAG_CLOUD_F | Used by the Cloud Files filter, for files managed by a sync engine such as OneDrive | | | | 0xa0000003 | IO_REPARSE_TAG_MOUNT_POINT | Junction or mount point + See section: <> | | | | 0xa000000c | IO_REPARSE_TAG_SYMLINK | Symbolic link + See section: <> | | | | 0xa0000010 | IO_REPARSE_TAG_IIS_CACHE | Used by Microsoft Internet Information Services (IIS) caching | | | | 0xa0000019 | IO_REPARSE_TAG_GLOBAL_REPARSE | Used by NPFS to indicate a named pipe symbolic link from a server silo into the host silo | 0xa000001a | IO_REPARSE_TAG_CLOUD | Used by the Cloud Files filter, for files managed by a sync engine such as Microsoft OneDrive | | | | 0xa000001d | IO_REPARSE_TAG_LX_SYMLINK | Used by the Windows Subsystem for Linux (WSL) to represent a UNIX symbolic link | | | | 0xa000001f | IO_REPARSE_TAG_WCI_TOMBSTONE | Used by Windows Container Isolation (WCI) | | | | 0xa0000022 | IO_REPARSE_TAG_PROJFS_TOMBSTONE | Used by the Windows Projected File System filter, for files managed by a user mode provider such as VFS for Git | | | | 0xa0000027 | IO_REPARSE_TAG_WCI_LINK | Used by Windows Container Isolation (WCI) | | | | 0xa0001027 | IO_REPARSE_TAG_WCI_LINK_1 | Used by Windows Container Isolation (WCI) | | | | 0xc0000004 | IO_REPARSE_TAG_HSM | Used by Hierarchical Storage Manager Product | | | | 0xc0000014 | IO_REPARSE_TAG_APPXSTRM | [yellow-background]*Unknown (Not used)* |=== ==== Notes [yellow-background]*single-instance storage (SIS): An NTFS feature that implements links with the semantics of copies for files stored on an NTFSvolume. SIS uses copy-on-close to implement the copy semantics of its links.* .... Is this documentation wrong or are these alternative values? Flag Description 0x68000005 NSS 0x68000006 NSS recover 0x68000007 SIS 0x68000008 DFS 0x88000003 Mount point 0xA8000004 HSM 0xE8000000 Symbolic link .... ==== Reparse point tag flags [cols="1,1,5",options="header"] |=== | Value | Identifier | Description | 0x1 | | [yellow-background]*Unknown (Reserved)* + Reserved according to `[MSDN]` | 0x2 | | Is alias (Name surrogate bit) + If this bit is set, the file or directory represents another named entity in the system. | 0x4 | | Is high-latency media + Reserved according to `[MSDN]` | 0x8 | | Is native (Microsoft-bit) + [yellow-background]*Does this flag influence the reparse point GUID?* |=== === [[junction_reparse_data]]Junction or mount point reparse data A reparse point with tag IO_REPARSE_TAG_MOUNT_POINT (0xa0000003) contains junction or mount point reparse data. The junction or mount point reparse data is of variable size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 2 | | Substitute name offset + The offset is relative from the start of the reparse name data | 2 | 2 | | Substitute name size + Value in bytes, the size of the end-of-string character is not included | 4 | 2 | | Print name offset + The offset is relative from the start of the reparse name data | 6 | 2 | | Print name size + Value in bytes, the size of the end-of-string character is not included 4+| _Reparse name data_ | 8 | ... | | Substitute name + Contains an UTF-16 little-endian [yellow-background]*with the end-of-string character?* | ... | ... | | Print name + Contains an UTF-16 little-endian [yellow-background]*with the end-of-string character?* |=== [yellow-background]*TODO: what do byte values like 0x02 represent in the substitute name?* .... 00000010: 5c 00 3f 00 3f 00 02 00 43 00 3a 00 5c 00 55 00 \.?.?... C.:.\.U. 00000020: 73 00 65 00 72 00 73 00 5c 00 74 00 65 00 73 00 s.e.r.s. \.t.e.s. 00000030: 74 00 5c 00 44 00 6f 00 63 00 75 00 6d 00 65 00 t.\.D.o. c.u.m.e. 00000040: 6e 00 74 00 73 00 00 00 n.t.s... .... === [[symbolic_link_reparse_data]]Symbolic link reparse data A reparse point with tag IO_REPARSE_TAG_SYMLINK (0xa000000c0) contains symbolic link reparse data. The symbolic link reparse data is of variable size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 2 | | Substitute name offset + The offset is relative from the start of the reparse name data | 2 | 2 | | Substitute name size + Value in bytes | 4 | 2 | | Print name offset + The offset is relative from the start of the reparse name data | 6 | 2 | | Print name size + Value in bytes | 8 | 4 | | Symbolic link flags 4+| _Reparse name data_ | 12 | ... | | Substitute name + Contains an UTF-16 little-endian without end-of-string character | ... | ... | | Print name + Contains an UTF-16 little-endian without end-of-string character |=== ==== Symbolic link flags [cols="1,1,5",options="header"] |=== | Value | Identifier | Description | 0x00000001 | SYMLINK_FLAG_RELATIVE | The substitute name is a path name relative to the directory containing the symbolic link. |=== === [[wof_reparse_data]]Windows Overlay Filter (WOF) reparse data A reparse point with tag IO_REPARSE_TAG_WOF (0x80000017) contains Windows Overlay Filter (WOF) reparse data. The Windows Overlay Filter (WOF) reparse data is 16 bytes in size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description 4+| _External provider information_ | 0 | 4 | 1 | [yellow-background]*Unknown (WOF version)* | 4 | 4 | 2 | [yellow-background]*Unknown (WOF provider)* 4+| _Internal provider information_ | 8 | 4 | 1 | [yellow-background]*Unknown (file information version)* | 12 | 4 | | Compression method + See section <> |=== ==== [[wof_compression_method]]Windows Overlay Filter (WOF) compression method [cols="1,1,5",options="header"] |=== | Value | Identifier | Description | 0 | | LZXPRESS Huffman with 4k window (compression unit) | 1 | | LZX with 32k window (compression unit) | 2 | | LZXPRESS Huffman with 8k window (compression unit) | 3 | | LZXPRESS Huffman with 16k window (compression unit) |=== For more information about LZXPRESS Huffman see: https://github.com/libyal/libfwnt/blob/main/documentation/Compression%20methods.asciidoc[[LIBFWNT\]] === [[wci_reparse_data]]Windows Container Isolation (WCI) reparse data A reparse point with tag IO_REPARSE_TAG_WCI (0x80000018) contains Windows Container Isolation (WCI) reparse data. The Windows Container Isolation (WCI) reparse data is of variable size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 4 | 1 | Version | 4 | 4 | 0 | [yellow-background]*Unknown (reserved)* | 8 | 16 | | Look-up identifier + Contains a GUID | 24 | 2 | | Name size + Value in bytes | 26 | ... | | Name + Contains an UTF-16 little-endian without end-of-string character |=== == The allocation bitmap The metadata file $Bitmap contains the allocation bitmap. Every bit in the allocation bitmap represents a block the size of the cluster block, where the LSB is the first bit in a byte. [yellow-background]*TODO determine and describe what the $SRAT data stream is used for.* == [[access_control]]Access control The $Secure metadata file contains the security descriptors used for access control. [cols="1,1,5",options="header"] |=== | Type | Name | Description | Data | $SDS | Security descriptor data stream + Contains all the Security descriptors on the volume | Index | $SDH | Security descriptor hash index | Index | $SII | Security descriptor identifier index + Contains the mapping of the security descriptor identifier (in $STANDARD_INFORMATION) to the offset of the security descriptor data (in $Secure:$SDS) |=== [yellow-background]*TODO add text* [yellow-background]*In the $SII index do the index values contain a 32-bit checksum?* === Security descriptor hash ($SDH) index ==== [[security_descriptor_hash_index_value]]The security descriptor hash index value [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description 4+| _Key data_ | 0 | 4 | | Security descriptor hash | 4 | 4 | | Security descriptor identifier 4+| _Value data_ | 8 | 4 | | Security descriptor hash | 12 | 4 | | Security descriptor identifier | 16 | 8 | | Security descriptor data offset (in $SDS) | 24 | 4 | | Security descriptor data size (in $SDS) | 28 | 4 | | [yellow-background]*Alignment padding (8-byte alignment)* + [yellow-background]*Contains string "I\x00I\x00" ?* |=== === Security descriptor identifier ($SII) index ==== [[security_descriptor_identifier_index_value]]The security descriptor identifier index value [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description 4+| _Key data_ | 0 | 4 | | Security descriptor identifier 4+| _Value data_ | 4 | 4 | | Security descriptor hash + [yellow-background]*TODO describe the hash algorithm* | 8 | 4 | | Security descriptor identifier | 12 | 8 | | Security descriptor data offset (in $SDS) | 20 | 4 | | Security descriptor data size (in $SDS) |=== === Security descriptor ($SDS) data stream [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 4 | | Security descriptor hash | 4 | 4 | | Security descriptor identifier | 12 | 8 | | Security descriptor data offset (in $SDS) | 20 | 4 | | Security descriptor data size (in $SDS) | 24 | ... | | Security descriptor data + See: https://github.com/libyal/libfwnt/blob/main/documentation/Security%20Descriptor.asciidoc[[LIBFWNT\]] | ... | ... | | 16-bit alignment padding. |=== == The object identifiers [yellow-background]*TODO add text* === $ObjID:$O [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description 4+| _Key data_ | 0 | 16 | | File (or object) identifier + Contains a GUID 4+| _Value data_ | 4 | 8 | | File reference + See section: <> | 12 | 16 | | Birth droid volume identifier + Contains a GUID | 28 | 16 | | Birth droid file (or object) identifier + Contains a GUID | 44 | 16 | | Birth droid domain identifier + Contains a GUID |=== .... 00000000 00 00 00 00 13 00 00 00 00 10 00 00 01 00 00 00 |................| 00000010 10 00 00 00 88 00 00 00 88 00 00 00 01 00 00 00 |................| 00000020 20 00 38 00 00 00 00 00 60 00 10 00 01 00 00 00 | .8.....`.......| OBJECT_ID: 43ecee59-e2b3-11dc-ad7e-001c2582598f of root directory 00000030 59 ee ec 43 b3 e2 dc 11 ad 7e 00 1c 25 82 59 8f |Y..C.....~..%.Y.| MFT file reference OBJECT_ID: e6a67b60-c0b5-4b53-b8fe-94470c83df89 of $Volume 00000040 05 00 00 00 00 00 05 00 60 7b a6 e6 b5 c0 53 4b |........`{....SK| 00000050 b8 fe 94 47 0c 83 df 89 59 ee ec 43 b3 e2 dc 11 |...G....Y..C....| 00000060 ad 7e 00 1c 25 82 59 8f 00 00 00 00 00 00 00 00 |.~..%.Y.........| 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000080 00 00 00 00 00 00 00 00 18 00 00 00 03 00 00 00 |................| 00000090 01 00 00 00 00 00 00 00 |........| .... == [[log_file]]Metadata transaction journal (log file) The metadata file $LogFile contains the metadata transaction journal. [yellow-background]*TODO add text.* * Log File Service restart page header * <> === Log File service restart page header The Log File service restart page header (LFS_RESTART_PAGE_HEADER) is 30 bytes in size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description 4+| _MULTI_SECTOR_HEADER_ | 0 | 4 | "CHKD" + "RCRD" + "RSTR" | Signature | 4 | 2 | | The fix-up values offset + Contains an offset relative from the start of the restart page header + According to `[MSDN]` this value is the update sequence array offset | 6 | 2 | | The number of fix-up values + According to `[MSDN]` this value is the update sequence array size. 4+| | 8 | 8 | | Checkdisk last LSN | 16 | 4 | | System page size | 20 | 4 | | Log page size | 24 | 2 | | Restart offset | 26 | 2 | | Minor format version | 28 | 2 | | Major format version + -1 => Beta Version + 0 => Transition + 1 => Update sequence support |=== === Notes Log File Service record header (LFS_RECORD_HEADER) [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 8 | | Metadata transaction journal sequence number + Contains a $LogFile Sequence Number (LSN) | 8 | 8 | | Previous metadata transaction journal sequence number + Contains a $LogFile Sequence Number (LSN) | 16 | 8 | | Undo next metadata transaction journal sequence number + Contains a $LogFile Sequence Number (LSN) |=== .... LFS_RECORD_HEADER { // // The following field is the size of data area for this record. The // log record header will be padded if necessary to fill to a 64-bit // boundary, so the client data will begin on a 64-bit boundary to // insure that all of his data is 64-bit aligned. The below value // has not been padded to 64 bits however. // ULONG ClientDataLength; // // Client ID. This identifies the owner of this log record. The owner // is uniquely identified by his offset in the client array and the // sequence number associated with that client record. // LFS_CLIENT_ID ClientId; // // This the Log Record type. This could be a commit protocol record, // a client restart area or a client update record. // LFS_RECORD_TYPE RecordType; // // Transaction ID. This is used externally by a client (Transaction // Manager) to group log file entries. // TRANSACTION_ID TransactionId; // // Log record flags. // USHORT Flags; // // Alignment field. // USHORT AlignWord; .... == [[usn_change_journal]]USN change journal The metadata file $Extend\$UsnJrnl contains the USN change journal. It is a sparse file in which NTFS stores records of changes to files and directories. Applications make use of the journal to respond to file and directory changes as they occur, like e.g. the Windows File Replication Service (FRS) and the Windows (Desktop) Search service. The USN change journal consists of: * the $UsnJrnl:$Max data stream, containing metadata like the maximum size of the journal * the $UsnJrnl:$J data stream, containing the update (or change) entries. The $UsnJrnl:$J data stream is sparse. === USN change journal metadata The USN change journal metadata is 32 bytes in size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 8 | | Maximum size + Contains the number of bytes | 8 | 8 | | Allocation delta + Contains the number of bytes | 16 | 8 | | Update (USN) journal identifier + Contains a FILETIME | 24 | 8 | | [yellow-background]*Unknown (empty)* |=== === USN change journal entries The $UsnJrnl:$J data stream consists of an array of USN change journal entries. The USN change journal entries are stored on a per block-basis and 64-bit aligned. Therefore the remainder of the block can contain 0-byte values. [yellow-background]*TODO: The journal block size seems to be 4096 bytes, but could this be defined by the index entry size? It does not match the cluster block size.* Once the stream reaches maximum size the earliest USN change journal entries are removed from the stream and replaced with a sparse data run. ==== USN change journal entry The USN change journal entry (USN_RECORD_V2) is of variable size and consists of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 4 | | Entry (or record) size | 4 | 2 | 2 | Major version | 6 | 2 | 0 | Minor version | 8 | 8 | | File reference | 16 | 8 | | Parent file reference | 24 | 8 | | Update sequence number (USN) + Contains the file offset of the USN change journal entry which is used as a unique identifier | 32 | 8 | | Update date and time + Contains a FILETIME | 40 | 4 | | Update reason flags + See section: <> | 44 | 4 | | Update source flags + See section: <> | 48 | 4 | | Security descriptor identifier + Contains the entry number in the security ID index ($Secure:$SII) + See section: <> | 52 | 4 | | File attribute flags + See section: <> | 56 | 2 | | Name size + Contains the byte size of the name | 58 | 2 | | Name offset + The offset is relative from the start of the USN change journal entry | 60 | (name size) | | Name | ... | ... | 0x00 | Padding |=== ==== [[update_reason_flags]]Update reason flags [cols="1,1,5",options="header"] |=== | Value | Identifier | Description | 0x00000001 | USN_REASON_DATA_OVERWRITE | The data in the file or directory is overwritten. + [yellow-background]*The default (unnamed) $DATA attribute was overwritten* | 0x00000002 | USN_REASON_DATA_EXTEND | The file or directory is extended + [yellow-background]*The default (unnamed) $DATA attribute was extended* | 0x00000004 | USN_REASON_DATA_TRUNCATION | The file or directory is truncated. + [yellow-background]*The default (unnamed) $DATA attribute was truncated* | | | | 0x00000010 | USN_REASON_NAMED_DATA_OVERWRITE | One or more named data streams ($DATA attributes) of file were overwritten | 0x00000020 | USN_REASON_NAMED_DATA_EXTEND | One or more named data streams ($DATA attributes) of file were extended | 0x00000040 | USN_REASON_NAMED_DATA_TRUNCATION | One or more named data streams ($DATA attributes) of a file were truncated | | | | 0x00000100 | USN_REASON_FILE_CREATE | The file or directory was created | 0x00000200 | USN_REASON_FILE_DELETE | The file or directory was deleted | 0x00000400 | USN_REASON_EA_CHANGE | The extended attributes of the file were changed | 0x00000800 | USN_REASON_SECURITY_CHANGE | The access rights (security descriptor) of a file or directory were changed | 0x00001000 | USN_REASON_RENAME_OLD_NAME | The name changed + The USN change journal entry contains the old name | 0x00002000 | USN_REASON_RENAME_NEW_NAME | The name changed + The USN change journal entry contains the new name | 0x00004000 | USN_REASON_INDEXABLE_CHANGE | Content indexed status changed + the file attribute: FILE_ATTRIBUTE_NOT_CONTENT_INDEXED was changed | 0x00008000 | USN_REASON_BASIC_INFO_CHANGE | Basic file or directory attributes changed + One or more file or directory attributes were changed e.g. read-only, hidden, system, archive, or sparse attribute, or one or more time stamps. | 0x00010000 | USN_REASON_HARD_LINK_CHANGE | A hard link was created or deleted | 0x00020000 | USN_REASON_COMPRESSION_CHANGE | The file or directory was compressed or decompressed | 0x00040000 | USN_REASON_ENCRYPTION_CHANGE | The file or directory was encrypted or decrypted | 0x00080000 | USN_REASON_OBJECT_ID_CHANGE | The object identifier of a file or directory was changed | 0x00100000 | USN_REASON_REPARSE_POINT_CHANGE | The reparse point that in a file or directory was changed, or a reparse point was added to or deleted from a file or directory. | 0x00200000 | USN_REASON_STREAM_CHANGE | A named data stream ($DATA attribute) is added to or removed from a file, or a named stream is renamed | 0x00400000 | USN_REASON_TRANSACTED_CHANGE | [yellow-background]*Unknown found in TxF USN change journal entry list* | | | | 0x80000000 | USN_REASON_CLOSE | The file or directory was closed |=== ==== [[update_source_flags]]Update source flags [cols="1,1,5",options="header"] |=== | Value | Identifier | Description | 0x00000001 | USN_SOURCE_DATA_MANAGEMENT | The operation added a private data stream to a file or directory. The modifications did not change the application data. | 0x00000002 | USN_SOURCE_AUXILIARY_DATA | The operation was caused by the operating system. Although a write operation is performed on the item, the data was not changed. | 0x00000004 | USN_SOURCE_REPLICATION_MANAGEMENT | The operation was caused by file replication |=== == Alternate data streams [cols="1,5",options="header"] |=== | Data stream name | Description | ♣BnhqlkugBim0elg1M1pt2tjdZe + ♣SummaryInformation + {4c8cc155-6c1e-11d1-8e41-00c04fb9386d} | Used to store property sets + Where ♣ is Unicode character U+2663 also known as black club | {59828bbb-3f72-4c1b-a420-b51ad66eb5d3}.XPRESS | Used during remote differential compression | AFP_AfpInfo + AFP_Resource | Used to store Macintosh operating system property lists | encryptable | Used to store attributes relating to thumbnails in the thumbnails database | favicon | Used to store favorite icons for web pages. | ms-properties | [yellow-background]*Unknown (Used to store property sets)* | OECustomProperty | Used to store custom properties related to email files | Zone.Identifier | Used to store URL security zones |=== === ms-properties .... 00000000 e9 00 00 00 8c 00 00 00 31 53 50 53 53 f1 ef fc |........1SPSS...| 00000010 39 e8 f3 4c a9 e7 ea 22 83 20 94 b8 25 00 00 00 |9..L...". ..%...| 00000020 6f 00 00 00 00 1f 10 00 00 01 00 00 00 08 00 00 |o...............| 00000030 00 50 00 72 00 69 00 76 00 61 00 74 00 65 00 00 |.P.r.i.v.a.t.e..| 00000040 00 25 00 00 00 6c 00 00 00 00 1f 00 00 00 09 00 |.%...l..........| 00000050 00 00 53 00 6b 00 79 00 44 00 72 00 69 00 76 00 |..S.k.y.D.r.i.v.| 00000060 65 00 00 00 00 00 11 00 00 00 6d 00 00 00 00 13 |e.........m.....| 00000070 00 00 00 00 0d 04 00 15 00 00 00 6e 00 00 00 00 |...........n....| 00000080 15 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000090 59 00 00 00 31 53 50 53 d6 b9 f9 b2 c4 fe d5 4d |Y...1SPS.......M| 000000a0 94 d7 89 57 48 8c 80 7b 3d 00 00 00 03 00 00 00 |...WH..{=.......| 000000b0 00 1f 00 00 00 15 00 00 00 37 00 46 00 30 00 39 |.........7.F.0.9| 000000c0 00 35 00 31 00 34 00 39 00 30 00 32 00 37 00 38 |.5.1.4.9.0.2.7.8| 000000d0 00 34 00 38 00 45 00 44 00 21 00 31 00 30 00 33 |.4.8.E.D.!.1.0.3| 000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 |.............| 000000ed .... === Zone.Identifier .... 00000000 5b 5a 6f 6e 65 54 72 61 6e 73 66 65 72 5d 0d 0a |[ZoneTransfer]..| 00000010 5a 6f 6e 65 49 64 3d 33 0d 0a |ZoneId=3..| 0000001a .... == [[transactional_ntfs]]Transactional NTFS (TxF) As of Vista ([yellow-background]*or windows server 2003?*) Transactional NTFS (TxF) was added. In TxF the resource manager (RM) keeps track of transactional metadata and log files. The TxF related metadata files are stored in the metadata directory: .... $Extend\$RmMetadata .... === Resource manager repair information The resource manager repair information metadata file: $Extend\$RmMetadata\$Repair consists of the following data streams: * the default (unnamed) data stream, [yellow-background]*purpose unknown* * the $Config data stream, contains the resource manager repair configuration information ==== Resource manager repair configuration information The $Repair:$Config data streams contains: [yellow-background]*TODO* .... 00000000 01 00 00 00 01 00 00 00 |........| .... [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 4 | | [yellow-background]*Unknown* | 4 | 4 | | [yellow-background]*Unknown* |=== === Transactional NTFS (TxF) metadata directory The transactional NTFS (TxF) metadata directory: $Extend\$RmMetadata\$Txf is used to isolate files for delete or overwrite operations. File format? All files seem to start with similar information === TxF Old Page Stream (TOPS) file The TxF Old Page Stream (TOPS) file: $Extend\$RmMetadata\$TxfLog\$Tops consists of the following data streams: * the default (unnamed) data stream, contains metadata about the resource manager, such as its GUID, its CLFS log policy, and the LSN at which recovery should start * the $T data stream, contains the file data that is partially overwritten by a transaction as opposed to a full overwrite, which would move the file into the Transactional NTFS (TxF) metadata directory ==== TxF Old Page Stream (TOPS) metadata The $Tops default (unnamed) data streams contains: [yellow-background]*TODO* [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 2 | 0x000a | [yellow-background]*Unknown* | 2 | 2 | 0x0064 | [yellow-background]*Size of TOPS metadata* | 4 | 4 | 0x0001 | [yellow-background]*Unknown* + [yellow-background]*Number of resource managers/streams?* | 8 | 16 | | Resource Manager (RM) identifier + Contains a GUID | 24 | 8 | | [yellow-background]*Unknown (empty)* | 32 | 8 | | [yellow-background]*Base (or log start)* LSN of TxFLog stream | 40 | 8 | | [yellow-background]*Unknown* | 48 | 8 | | [yellow-background]*Last* flushed LSN of TxFLog stream | 56 | 8 | | [yellow-background]*Unknown* | 64 | 8 | | [yellow-background]*Unknown (empty)* | 72 | 8 | | [yellow-background]*Restart LSN?* | 80 | 20 | | [yellow-background]*Unknown* |=== ==== TxF Old Page Stream (TOPS) file data The $Tops:$T data streams contains the file data that is partially overwritten by a transaction. It consists of multiple pending transaction XML-documents. [yellow-background]*Note that the start of each sector contains 0x0001, is this a value indication the sector is empty? Or are there fix-up values stored somewhere else?* A pending transaction XML-document starts with an UTF-8 byte-order-mark. Is roughly contains the following data: .... ... ... ... ... .... === Transactional NTFS (TxF) Common Log File System (CLFS) files TxF uses a Common Log File System (CLFS) log store and the logged utility stream attribute named $TXF_DATA. See `[RUSSNOVICH09]`, `[MSDN]` and `[LIBFSCLFS]` for more information about CLFS. The base log file (BLF) of the TxF log store is: .... $Extend\$RmMetadata\$TxfLog\TxfLog.blf .... Commonly the corresponding container files are: .... $Extend\$RmMetadata\$TxfLog\TxfLogContainer00000000000000000001 $Extend\$RmMetadata\$TxfLog\TxfLogContainer00000000000000000002 .... TxF uses a multiplexed log store which contains two streams: * the KtmLog stream used for Kernel Transaction Manager (KTM) metadata records * TxfLog stream, which contains the TxF log records. === Transactional data logged utility stream attribute The transactional data ($TXF_DATA) logged utility stream attribute is 56 bytes in size and consist of: [cols="1,1,1,5",options="header"] |=== | Offset | Size | Value | Description | 0 | 6 | | [yellow-background]*Unknown (remnant data)* | 6 | 8 | | Resource manager root file reference + Contains an NTFS file reference that refers to the MFT | 14 | 8 | | [yellow-background]*USN index?* | 22 | 8 | | File identifier (TxID) + Contains a TxF file identifier | 30 | 8 | | Data LSN + Contains a CLFS LSN of file data transaction records | 38 | 8 | | Metadata LSN + Contains a CLFS LSN of file system metadata transaction records | 46 | 8 | | Directory index LSN + Contains a CLFS LSN of directory index transaction records | 54 | 2 | | [yellow-background]*Flags?* + [yellow-background]*Seen: 0x0000, 0x0002* |=== [yellow-background]*Note there can be more than 1 per MTF entry* == Windows definitions === [[file_attribute_flags]]File attribute flags The file attribute flags consist of the following values: [cols="1,1,5",options="header"] |=== | Value | Identifier | Description | 0x00000001 | FILE_ATTRIBUTE_READONLY | Is read-only | 0x00000002 | FILE_ATTRIBUTE_HIDDEN | Is hidden | 0x00000004 | FILE_ATTRIBUTE_SYSTEM | Is a system file or directory | 0x00000008 | | Is a volume label + [yellow-background]*Not used by NTFS* | 0x00000010 | FILE_ATTRIBUTE_DIRECTORY | Is a directory + [yellow-background]*Not used by NTFS* | 0x00000020 | FILE_ATTRIBUTE_ARCHIVE | Should be archived | 0x00000040 | FILE_ATTRIBUTE_DEVICE | Is a device + [yellow-background]*Not used by NTFS* | 0x00000080 | FILE_ATTRIBUTE_NORMAL | Is normal + None of the other flags should be set | 0x00000100 | FILE_ATTRIBUTE_TEMPORARY | Is temporary | 0x00000200 | FILE_ATTRIBUTE_SPARSE_FILE | Is a sparse file | 0x00000400 | FILE_ATTRIBUTE_REPARSE_POINT | Is a reparse point or symbolic link | 0x00000800 | FILE_ATTRIBUTE_COMPRESSED | Is compressed | 0x00001000 | FILE_ATTRIBUTE_OFFLINE | Is offline + The data of the file is stored on an offline storage. | 0x00002000 | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | Do not index content + The content of the file or directory should not be indexed by the indexing service. | 0x00004000 | FILE_ATTRIBUTE_ENCRYPTED | Is encrypted | 0x00008000 | | [yellow-background]*Unknown (seen on Windows 95 FAT)* | 0x00010000 | FILE_ATTRIBUTE_VIRTUAL | Is virtual 3+| _The following flags are mainly used in the file name attribute and sparsely in the standard information attribute;_ + _it could be that they have a different meaning in both types of attributes or that the standard information flags are not updated._ + _For now the latter is assumed._ | 0x10000000 | | [yellow-background]*Unknown* + [yellow-background]*Is directory (or has $I30 index ?) used instead of 0x00000010 ? Seen $Extend directory without this flag* | 0x20000000 | | [yellow-background]*Is index view* + [yellow-background]*(copy from corresponding bit in MFT record)* |=== == [[corruption_scenarios]]Corruption scenarios === Data steam with inconsistent data flags An MFT entry contains an $ATTRIBUTE_LIST attribute that contains multiple $DATA attributes. The $DATA attributes define a LZNT1 compressed data stream though only the first $DATA attribute has the compressed data flag set. [NOTE] It is unclear if this is a corruption scenario or not. .... MFT entry: 220 information: Is allocated : true File reference : 220-59 Base record file reference : Not set (0) Journal sequence number : 51876429013 Number of attributes : 5 Attribute: 1 Type : $STANDARD_INFORMATION (0x00000010) Creation time : Jun 05, 2019 06:56:26.032730300 UTC Modification time : Oct 05, 2019 06:56:04.150940700 UTC Access time : Oct 05, 2019 06:56:04.150940700 UTC Entry modification time : Oct 05, 2019 06:56:04.150940700 UTC Owner identifier : 0 Security descriptor identifier : 5862 Update sequence number : 11553149976 File attribute flags : 0x00000820 Should be archived (FILE_ATTRIBUTE_ARCHIVE) Is compressed (FILE_ATTRIBUTE_COMPRESSED) Attribute: 2 Type : $ATTRIBUTE_LIST (0x00000020) Attribute: 3 Type : $FILE_NAME (0x00000030) Parent file reference : 33996-57 Creation time : Jun 05, 2019 06:56:26.032730300 UTC Modification time : Oct 05, 2019 06:56:03.510061800 UTC Access time : Oct 05, 2019 06:56:03.510061800 UTC Entry modification time : Oct 05, 2019 06:56:03.510061800 UTC File attribute flags : 0x00000020 Should be archived (FILE_ATTRIBUTE_ARCHIVE) Namespace : POSIX (0) Name : setupapi.dev.20191005_085603.log Attribute: 4 Type : $DATA (0x00000080) Data VCN range : 513 - 1103 Data flags : 0x0000 Attribute: 5 Type : $DATA (0x00000080) Data VCN range : 0 - 512 Data size : 4487594 bytes Data flags : 0x0001 .... === Directory entry with outdated file reference The directory entry: \ProgramData\McAfee\Common Framework\Task\5.ini .... File entry: Path : \ProgramData\McAfee\Common Framework\Task\5.ini File reference : 51106-400 Name : 5.ini Parent file reference : 65804-10 Size : 723 Creation time : Sep 16, 2011 20:47:54.561041200 UTC Modification time : Apr 07, 2012 21:07:02.684060000 UTC Access time : Apr 07, 2012 21:07:02.652810200 UTC Entry modification time : Apr 07, 2012 21:07:02.684060000 UTC File attribute flags : 0x00002020 Should be archived (FILE_ATTRIBUTE_ARCHIVE) Content should not be indexed (FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) .... The corresponding MFT entry: .... MFT entry: 51106 information: Is allocated : true File reference : 51106-496 Base record file reference : Not set (0) Journal sequence number : 0 Number of attributes : 3 Attribute: 1 Type : $STANDARD_INFORMATION (0x00000010) Creation time : Sep 16, 2011 20:47:54.561041200 UTC Modification time : Apr 07, 2012 21:07:02.684060000 UTC Access time : Apr 07, 2012 21:07:02.652810200 UTC Entry modification time : Apr 07, 2012 21:07:02.684060000 UTC Owner identifier : 0 Security descriptor identifier : 1368 Update sequence number : 1947271600 File attribute flags : 0x00002020 Should be archived (FILE_ATTRIBUTE_ARCHIVE) Content should not be indexed (FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) Attribute: 2 Type : $FILE_NAME (0x00000030) Parent file reference : 65804-10 Creation time : Sep 16, 2011 20:47:54.561041200 UTC Modification time : Apr 07, 2012 21:07:02.652810200 UTC Access time : Apr 07, 2012 21:07:02.652810200 UTC Entry modification time : Apr 07, 2012 21:07:02.652810200 UTC File attribute flags : 0x00002020 Should be archived (FILE_ATTRIBUTE_ARCHIVE) Content should not be indexed (FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) Namespace : DOS and Windows (3) Name : 1.ini Attribute: 3 Type : $DATA (0x00000080) Data size : 723 bytes Data flags : 0x0000 .... [yellow-background]*TODO look into using $LogFile* === LZNT1 compressed block with data size of 0 Not sure if this is a corruption scenario or a data format edge case. A compression unit (index 30) consisting of the following data runs: .... reading data run: 60. data run: 00000000: 11 01 01 ... value sizes : 1, 1 number of cluster blocks : 1 (size: 4096) cluster block number : 687143 (1) (offset: 0xa7c27000) reading data run: 61. data run: 00000000: 01 0f .. value sizes : 1, 0 number of cluster blocks : 15 (size: 61440) cluster block number : 0 (0) (offset: 0x00000000) Is sparse .... Contains the following data: .... a7c27000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| ... a7c27ff0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| .... This relates to an empty LZNT1 compressed block. .... compressed data offset : 0 (0x00000000) compression chunk header : 0x0000 compressed chunk size : 1 signature value : 0 is compressed flag : 0 .... It was observed in 2 differnt NTFS implementations that the entire block is filled with 0-byte values. TODO: verify behavior of Windows NTFS implementation. === Truncated LZNT1 compressed block Not sure if this is a corruption scenario or a data format edge case. A compression unit (index 0) consisting of the following data runs: .... reading data run: 0. data run: 00000000: 31 08 48 d8 01 1.H.. value sizes : 1, 3 number of cluster blocks : 8 (size: 32768) cluster block number : 120904 (120904) (offset: 0x1d848000) reading data run: 1. data run: 00000000: 01 08 .. value sizes : 1, 0 number of cluster blocks : 8 (size: 32768) cluster block number : 0 (0) (offset: 0x00000000) Is sparse .... Contains the following data: .... 1d848000 bd b7 50 44 46 50 00 01 00 01 00 40 e0 00 07 0b |..PDFP.....@....| ... 1d84c000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 1d84fff0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| .... This relates to a LZNT1 compressed block that appears to be truncated at offset 16384 (0x00004000). .... compressed data offset : 16384 (0x00004000) compression flag byte : 0x00 .... Different behavior was observed in 2 differnt NTFS implementations: * one implementation fills the compressed block with the uncompressed data it could read and the rest with with 0-byte values * another implementation seems to provide the data that was already in its buffer TODO: verify behavior of Windows NTFS implementation. == Notes Signatures as indicated in `[RUSSON05]`: .... "HOLE" == ??? (NTFS 3.0+?) .... === NTFS reserved file names [cols="1,1,5",options="header"] |=== | MFT entry index | Filename | Description | | \$Extend\$Config | Used for NTFS repair activity | | \$Extend\$Delete | Delete file name | | \$Extend\$Repair.log | Repair log name | | \$Extend\$Tops | | | \$Extend\$TxfLog | Transactional NTFS log |=== === File system flags .... fsutil fsinfo volumeinfo C: .... .... FILE_CASE_PRESERVED_NAMES 0x00000002 The specified volume supports preserved case of file names when it places a name on disk. FILE_CASE_SENSITIVE_SEARCH 0x00000001 The specified volume supports case-sensitive file names. FILE_FILE_COMPRESSION 0x00000010 The specified volume supports file-based compression. FILE_NAMED_STREAMS 0x00040000 The specified volume supports named streams. FILE_PERSISTENT_ACLS 0x00000008 The specified volume preserves and enforces access control lists (ACL). For example, the NTFS file system preserves and enforces ACLs, and the FAT file system does not. FILE_READ_ONLY_VOLUME 0x00080000 The specified volume is read-only. Windows 2000: This value is not supported. FILE_SEQUENTIAL_WRITE_ONCE 0x00100000 The specified volume supports a single sequential write. Windows 2000: This value is not supported. FILE_SUPPORTS_ENCRYPTION 0x00020000 The specified volume supports the Encrypted File System (EFS). For more information, see File Encryption. FILE_SUPPORTS_EXTENDED_ATTRIBUTES 0x00800000 The specified volume supports extended attributes. An extended attribute is a piece of application-specific metadata that an application can associate with a file and is not part of the file's data. Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP/2000: This value is not supported until Windows Server 2008 R2 and Windows 7. FILE_SUPPORTS_HARD_LINKS 0x00400000 The specified volume supports hard links. For more information, see Hard Links and Junctions. Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP/2000: This value is not supported until Windows Server 2008 R2 and Windows 7. FILE_SUPPORTS_OBJECT_IDS 0x00010000 The specified volume supports object identifiers. FILE_SUPPORTS_OPEN_BY_FILE_ID 0x01000000 The file system supports open by FileID. For more information, see FILE_ID_BOTH_DIR_INFO. Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP/2000: This value is not supported until Windows Server 2008 R2 and Windows 7. FILE_SUPPORTS_REPARSE_POINTS 0x00000080 The specified volume supports re-parse points. FILE_SUPPORTS_SPARSE_FILES 0x00000040 The specified volume supports sparse files. FILE_SUPPORTS_TRANSACTIONS 0x00200000 The specified volume supports transactions. For more information, see About KTM. Windows 2000: This value is not supported. FILE_SUPPORTS_USN_JOURNAL 0x02000000 The specified volume supports update sequence number (USN) journals. For more information, see Change Journal Records. Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP/2000: This value is not supported until Windows Server 2008 R2 and Windows 7. FILE_UNICODE_ON_DISK 0x00000004 The specified volume supports Unicode in file names as they appear on disk. FILE_VOLUME_IS_COMPRESSED 0x00008000 The specified volume is a compressed volume, for example, a DoubleSpace volume. FILE_VOLUME_QUOTAS 0x00000020 The specified volume supports disk quotas. .... === $MFT metadata file only parsing What file system metadata is missing: * Attribute lists are stored outside the $MFT * $I30 indexes are stored outside the $MFT * How to map MFT entry to parent? what if parent MFT entry has changed? :numbered!: [appendix] == References `[CARRIER05]` [cols="1,5",options="header"] |=== | Title | File System Forensic Analysis | Author(s) | Brian Carrier | Date | 2005 | ISBN-10 | 0-321-26817-2 |=== `[RUSSON05]` [cols="1,5",options="header"] |=== | Title | NTFS Documentation | Author(s) | Richard Russon, Yuval Fiedel | Date | 2005 | URL | https://flatcap.github.io/linux-ntfs/ntfs/ |=== `[APPLE06]` [cols="1,5",options="header"] |=== | Title | ntfs_layout.h - NTFS associated on-disk structures | URL | https://opensource.apple.com/source/ntfs/ntfs-65.2/kext/ntfs_layout.h.auto.html |=== `[RUSSNOVICH09]` [cols="1,5",options="header"] |=== | Title | Windows Internals 5 - Covering Windows Server 2008 and Windows Vista | Author(s) | Mark E. Russinovich and David A. Solomon | Date | June 17, 2009 | ISBN-13 | 978-0735625303 |=== `[LIBBDE]` [cols="1,5",options="header"] |=== | Title | BitLocker Drive Encryption (BDE) format specification - Analysis of theBitLocker Drive Encryption (BDE) volume format | Date | March 2011 | Author(s) | Joachim Metz | URL | https://github.com/libyal/libbde/blob/main/documentation/BitLocker%20Drive%20Encryption%20(BDE)%20format.asciidoc |=== `[LIBFSCLFS]` [cols="1,5",options="header"] |=== | Title | Common Log File System – Analysis of the Windows ARIES log system | Date | November 2010 | Author(s) | Joachim Metz | URL | https://github.com/libyal/libfsclfs/blob/main/documenation/Common%20Log%20File%20System%20(CLFS).asciidoc |=== `[LIBVSHADOW]` [cols="1,5",options="header"] |=== | Title | Volume Shadow Snapshot (VSS) - Analysis the Windows NT VSS format | Date | March 2011 | Author(s) | Joachim Metz | URL | https://github.com/libyal/libvshadow/blob/master/documentation/Volume%20Shadow%20Snapshot%20(VSS)%20format.asciidoc |=== `[MSDN]` [cols="1,5",options="header"] |=== | Title | How NTFS Works | URL | https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc781134(v=ws.10) |=== [cols="1,5",options="header"] |=== | Subject | Master File Table | URL | https://learn.microsoft.com/en-us/windows/win32/devnotes/master-file-table |=== [cols="1,5",options="header"] |=== | Subject | WIN32_FIND_DATAA structure (minwinbase.h) | URL | https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-win32_find_dataa |=== [cols="1,5",options="header"] |=== | Subject | Reparse point | URL | http://msdn.microsoft.com/en-us/library/aa365511%28v=VS.85%29.aspx + http://msdn.microsoft.com/en-us/library/dd541667%28PROT.13%29.aspx + http://msdn.microsoft.com/en-us/library/cc232005%28v=PROT.13%29.aspx + http://msdn.microsoft.com/en-us/library/cc232006%28v=PROT.13%29.aspx + http://msdn.microsoft.com/en-us/library/cc232007%28v=PROT.13%29.aspx |=== [cols="1,5",options="header"] |=== | Subject | Update (or change) journal | URL | http://msdn.microsoft.com/en-us/library/aa363798.aspx + http://msdn.microsoft.com/en-us/library/aa363803%28VS.85%29.aspx + http://msdn.microsoft.com/en-us/library/aa365722%28VS.85%29.aspx |=== [cols="1,5",options="header"] |=== | Subject | Known Alternate Stream Names | URL | https://msdn.microsoft.com/en-us/library/dn365326.aspx |=== [cols="1,5",options="header"] |=== | Subject | transactional NTFS | URL | http://msdn.microsoft.com/en-us/library/bb968806%28v=VS.85%29.aspx + http://msdn.microsoft.com/en-us/library/bb986748%28VS.85%29.aspx + http://msdn.microsoft.com/en-us/library/bb540368%28VS.85%29.aspx |=== `[WIKI]` [cols="1,5",options="header"] |=== | URL | http://en.wikipedia.org/wiki/NTFS + http://en.wikipedia.org/wiki/BIOS_parameter_block + http://en.wikipedia.org/wiki/Transactional_NTFS |=== `[WIN32PROG]` [cols="1,5",options="header"] |=== | Title | The Win32 Programming Tutorials For Fun – Appendix E. NTFS On-Disk Structure | URL | http://www.installsetupconfig.com/win32programming/1996%20AppE_apnilife.pdf |=== [appendix] == GNU Free Documentation License Version 1.3, 3 November 2008 Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. === 0. PREAMBLE The purpose of this License is to make a manual, textbook, or other functional and useful document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. === 1. APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not "Transparent" is called "Opaque". Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. The "publisher" means any person or entity that distributes copies of the Document to the public. A section "Entitled XYZ" means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as "Acknowledgements", "Dedications", "Endorsements", or "History".) To "Preserve the Title" of such a section when you modify the Document means that it remains a section "Entitled XYZ" according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. === 2. VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. === 3. COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. === 4. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. C. State on the Title page the name of the publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the Document. E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. H. Include an unaltered copy of this License. I. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. K. For any section Entitled "Acknowledgements" or "Dedications", Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. M. Delete any section Entitled "Endorsements". Such a section may not be included in the Modified Version. N. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any Invariant Section. O. Preserve any Warranty Disclaimers. If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section Entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties—for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. === 5. COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled "History" in the various original documents, forming one section Entitled "History"; likewise combine any sections Entitled "Acknowledgements", and any sections Entitled "Dedications". You must delete all sections Entitled "Endorsements". === 6. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. === 7. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an "aggregate" if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. === 8. TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. If a section in the Document is Entitled "Acknowledgements", "Dedications", or "History", the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. === 9. TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, or distribute it is void, and will automatically terminate your rights under this License. However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, receipt of a copy of some or all of the same material does not give you any rights to use it. === 10. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. If the Document specifies that a proxy can decide which future versions of this License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Document. === 11. RELICENSING "Massive Multiauthor Collaboration Site" (or "MMC Site") means any World Wide Web server that publishes copyrightable works and also provides prominent facilities for anybody to edit those works. A public wiki that anybody can edit is an example of such a server. A "Massive Multiauthor Collaboration" (or "MMC") contained in the site means any set of copyrightable works thus published on the MMC site. "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 license published by Creative Commons Corporation, a not-for-profit corporation with a principal place of business in San Francisco, California, as well as future copyleft versions of that license published by that same organization. "Incorporate" means to publish or republish a Document, in whole or in part, as part of another Document. An MMC is "eligible for relicensing" if it is licensed under this License, and if all works that were first published under this License somewhere other than this MMC, and subsequently incorporated in whole or in part into the MMC, (1) had no cover texts or invariant sections, and (2) were thus incorporated prior to November 1, 2008. The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is eligible for relicensing. ================================================ FILE: dpkg/changelog.in ================================================ libfsntfs (@VERSION@-1) unstable; urgency=low * Auto-generated -- Joachim Metz @DPKG_DATE@ ================================================ FILE: dpkg/compat ================================================ 10 ================================================ FILE: dpkg/control ================================================ Source: libfsntfs Priority: extra Maintainer: Joachim Metz Build-Depends: debhelper (>= 9), dh-autoreconf, dh-python, pkg-config, libssl-dev, python3-dev, python3-setuptools, libfuse-dev Standards-Version: 4.1.4 Section: libs Homepage: https://github.com/libyal/libfsntfs Vcs-Git: https://github.com/libyal/libfsntfs.git Package: libfsntfs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Conflicts: libfsntfs1 Replaces: libfsntfs1 Suggests: libfsntfs-dbg Description: Library to access the New Technology File System (NTFS) format libfsntfs is a library to access the New Technology File System (NTFS) format. Package: libfsntfs-dbg Architecture: any Section: debug Depends: libfsntfs (= ${binary:Version}), ${misc:Depends} Description: Debugging symbols for libfsntfs Debugging symbols for libfsntfs. Package: libfsntfs-dev Section: libdevel Architecture: any Depends: libfsntfs (= ${binary:Version}), ${misc:Depends} Description: Header files and libraries for developing applications for libfsntfs Header files and libraries for developing applications for libfsntfs. Package: libfsntfs-tools Section: utils Architecture: any Depends: libfsntfs (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} Conflicts: libfsntfs-utils Replaces: libfsntfs-utils Description: Several tools for reading New Technology File System (NTFS) volumes Several tools for reading New Technology File System (NTFS) volumes. Package: libfsntfs-tools-dbg Section: debug Architecture: any Depends: libfsntfs-tools (= ${binary:Version}), ${misc:Depends} Description: Debugging symbols for libfsntfs-tools Debugging symbols for libfsntfs-tools. Package: libfsntfs-python3 Section: python Architecture: any Depends: libfsntfs (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} Conflicts: python3-libfsntfs Replaces: python3-libfsntfs Suggests: libfsntfs-python3-dbg Description: Python 3 bindings for libfsntfs Python 3 bindings for libfsntfs. Package: libfsntfs-python3-dbg Section: debug Architecture: any Depends: libfsntfs-python3 (= ${binary:Version}), ${misc:Depends} Description: Debugging symbols for libfsntfs-python3 Debugging symbols for libfsntfs-python3. ================================================ FILE: dpkg/copyright ================================================ Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: libfsntfs Source: https://github.com/libyal/libfsntfs Files: * Copyright: 2010-2026, Joachim Metz License: LGPL-3.0+ License: LGPL-3.0+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. . This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. . You should have received a copy of the GNU General Public License along with this program. If not, see . . On Debian systems, the complete text of the GNU Lesser General Public License can be found in "/usr/share/common-licenses/LGPL-3". ================================================ FILE: dpkg/libfsntfs-dev.install ================================================ usr/include/* usr/lib/*-*/lib*.a usr/lib/*-*/lib*.so usr/lib/*-*/pkgconfig/* usr/share/man/man3 ================================================ FILE: dpkg/libfsntfs-python3.install ================================================ /usr/lib/python3* ================================================ FILE: dpkg/libfsntfs-tools.install ================================================ usr/bin usr/share/man/man1 ================================================ FILE: dpkg/libfsntfs.install ================================================ usr/lib/*-*/lib*.so.* ================================================ FILE: dpkg/rules ================================================ #!/usr/bin/make -f # -*- makefile -*- # Uncomment for debhelper verbose output. # export DH_VERBOSE=1 export SKIP_PYTHON_TESTS=1 %: dh $@ --buildsystem=autoconf --with=autoreconf,python3 .PHONY: override_dh_auto_configure override_dh_auto_configure: dh_auto_configure -- --enable-python CFLAGS="-g" .PHONY: override_dh_install override_dh_install: dh_install --fail-missing -X.la -X/pyfsntfs.a .PHONY: override_dh_missing override_dh_missing: dh_missing -X.la -X/pyfsntfs.a --fail-missing .PHONY: override_dh_strip override_dh_strip: ifeq (,$(filter nostrip,$(DEB_BUILD_OPTIONS))) dh_strip -plibfsntfs --dbg-package=libfsntfs-dbg dh_strip -plibfsntfs-tools --dbg-package=libfsntfs-tools-dbg dh_strip -plibfsntfs-python3 --dbg-package=libfsntfs-python3-dbg endif ================================================ FILE: dpkg/source/format ================================================ 3.0 (quilt) ================================================ FILE: fsntfstools/Makefile.am ================================================ AM_CPPFLAGS = \ -I../include -I$(top_srcdir)/include \ -I../common -I$(top_srcdir)/common \ @LIBCERROR_CPPFLAGS@ \ @LIBCDATA_CPPFLAGS@ \ @LIBCLOCALE_CPPFLAGS@ \ @LIBCNOTIFY_CPPFLAGS@ \ @LIBCSPLIT_CPPFLAGS@ \ @LIBUNA_CPPFLAGS@ \ @LIBCFILE_CPPFLAGS@ \ @LIBCPATH_CPPFLAGS@ \ @LIBBFIO_CPPFLAGS@ \ @LIBFCACHE_CPPFLAGS@ \ @LIBFDATA_CPPFLAGS@ \ @LIBFDATETIME_CPPFLAGS@ \ @LIBFGUID_CPPFLAGS@ \ @LIBFUSN_CPPFLAGS@ \ @LIBFWNT_CPPFLAGS@ \ @LIBHMAC_CPPFLAGS@ \ @LIBCRYPTO_CPPFLAGS@ \ @LIBFUSE_CPPFLAGS@ \ @PTHREAD_CPPFLAGS@ \ @LIBFSNTFS_DLL_IMPORT@ AM_LDFLAGS = @STATIC_LDFLAGS@ bin_PROGRAMS = \ fsntfsinfo \ fsntfsmount fsntfsinfo_SOURCES = \ bodyfile.c bodyfile.h \ digest_hash.c digest_hash.h \ fsntfsinfo.c \ fsntfstools_getopt.c fsntfstools_getopt.h \ fsntfstools_i18n.h \ fsntfstools_libbfio.h \ fsntfstools_libcerror.h \ fsntfstools_libclocale.h \ fsntfstools_libcnotify.h \ fsntfstools_libfcache.h \ fsntfstools_libfdata.h \ fsntfstools_libfdatetime.h \ fsntfstools_libfguid.h \ fsntfstools_libfsntfs.h \ fsntfstools_libfusn.h \ fsntfstools_libfwnt.h \ fsntfstools_libhmac.h \ fsntfstools_libuna.h \ fsntfstools_output.c fsntfstools_output.h \ fsntfstools_signal.c fsntfstools_signal.h \ fsntfstools_unused.h \ info_handle.c info_handle.h \ path_string.c path_string.h fsntfsinfo_LDADD = \ @LIBHMAC_LIBADD@ \ @LIBCRYPTO_LIBADD@ \ @LIBDL_LIBADD@ \ @LIBFWNT_LIBADD@ \ @LIBFUSN_LIBADD@ \ @LIBFGUID_LIBADD@ \ @LIBFDATETIME_LIBADD@ \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ \ @LIBINTL@ fsntfsmount_SOURCES = \ fsntfsmount.c \ fsntfstools_getopt.c fsntfstools_getopt.h \ fsntfstools_i18n.h \ fsntfstools_libbfio.h \ fsntfstools_libcerror.h \ fsntfstools_libclocale.h \ fsntfstools_libcnotify.h \ fsntfstools_libcpath.h \ fsntfstools_libfsntfs.h \ fsntfstools_libuna.h \ fsntfstools_output.c fsntfstools_output.h \ fsntfstools_signal.c fsntfstools_signal.h \ fsntfstools_unused.h \ mount_dokan.c mount_dokan.h \ mount_file_entry.c mount_file_entry.h \ mount_file_system.c mount_file_system.h \ mount_fuse.c mount_fuse.h \ mount_handle.c mount_handle.h \ mount_path_string.c mount_path_string.h fsntfsmount_LDADD = \ @LIBFUSE_LIBADD@ \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ \ @LIBINTL@ DISTCLEANFILES = \ Makefile \ Makefile.in splint-local: @echo "Running splint on fsntfsinfo ..." -splint -preproc -redef $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(fsntfsinfo_SOURCES) ================================================ FILE: fsntfstools/bodyfile.c ================================================ /* * Bodyfile functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include "bodyfile.h" #include "fsntfstools_libcerror.h" #include "fsntfstools_libfsntfs.h" #include "fsntfstools_libuna.h" /* Copies the path from a comparable file entry path * Returns 1 if successful or -1 on error */ int bodyfile_path_string_copy_from_file_entry_path( system_character_t **path, size_t *path_size, const system_character_t *file_entry_path, size_t file_entry_path_length, libcerror_error_t **error ) { system_character_t *safe_path = NULL; static char *function = "bodyfile_path_string_copy_from_file_entry_path"; libuna_unicode_character_t unicode_character = 0; system_character_t escape_character = 0; size_t file_entry_path_index = 0; size_t path_index = 0; size_t safe_path_size = 0; int print_count = 0; int result = 0; if( path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); return( -1 ); } if( path_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path size.", function ); return( -1 ); } if( file_entry_path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry path.", function ); return( -1 ); } if( ( file_entry_path_length == 0 ) || ( file_entry_path_length > (size_t) ( SSIZE_MAX - 1 ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid file entry path length value out of bounds.", function ); return( -1 ); } /* Note that there is a worst-case of a 1 to 10 ratio for each escaped character. */ if( file_entry_path_length > (size_t) ( ( SSIZE_MAX - 1 ) / ( sizeof( system_character_t ) * 10 ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid value string length value exceeds maximum.", function ); return( -1 ); } safe_path_size = ( file_entry_path_length * 10 ) + 1; safe_path = system_string_allocate( safe_path_size ); if( safe_path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create path.", function ); goto on_error; } escape_character = (system_character_t) '\\'; /* Using UCS-2 or RFC 2279 UTF-8 to support unpaired UTF-16 surrogates */ while( file_entry_path_index < file_entry_path_length ) { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libuna_unicode_character_copy_from_ucs2( &unicode_character, (libuna_utf16_character_t *) file_entry_path, file_entry_path_length, &file_entry_path_index, error ); #else result = libuna_unicode_character_copy_from_utf8_rfc2279( &unicode_character, (libuna_utf8_character_t *) file_entry_path, file_entry_path_length, &file_entry_path_index, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_INPUT_FAILED, "%s: unable to copy Unicode character from value string.", function ); goto on_error; } /* Replace by \x##: * Control characters ([U+0-U+1f, U+7f-U+9f]) */ if( ( unicode_character <= 0x1f ) || ( ( unicode_character >= 0x7f ) && ( unicode_character <= 0x9f ) ) ) { print_count = system_string_sprintf( &( safe_path[ path_index ] ), safe_path_size - path_index, _SYSTEM_STRING( "%" PRIc_SYSTEM "x%02" PRIx32 "" ), escape_character, unicode_character ); if( print_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_INPUT_FAILED, "%s: unable to copy escaped Unicode character to path.", function ); goto on_error; } path_index += print_count; } /* Replace by \U########: * Unicode surrogate characters ([U+d800-U+dfff]) * Undefined Unicode characters ([ * U+fdd0-U+fddf, U+fffe-U+ffff, U+1fffe-U+1ffff, U+2fffe-U+2ffff, * U+3fffe-U+3ffff, U+4fffe-U+4ffff, U+5fffe-U+5ffff, U+6fffe-U+6ffff, * U+7fffe-U+7ffff, U+8fffe-U+8ffff, U+9fffe-U+9ffff, U+afffe-U+affff, * U+bfffe-U+bffff, U+cfffe-U+cffff, U+dfffe-U+dffff, U+efffe-U+effff, * U+ffffe-U+fffff, U+10fffe-U+ffffffff]) * Observed unprintable characters ([ * U+2028, U+2029, U+e000, U+f8ff, U+f0000, U+ffffd, U+100000, U+10fffd]) */ else if( ( ( unicode_character >= 0x00002028UL ) && ( unicode_character <= 0x00002029UL ) ) || ( ( unicode_character >= 0x0000d800UL ) && ( unicode_character <= 0x0000dfffUL ) ) || ( unicode_character == 0x0000e000UL ) || ( unicode_character == 0x0000f8ffUL ) || ( ( unicode_character >= 0x0000fdd0UL ) && ( unicode_character <= 0x0000fddfUL ) ) || ( ( ( unicode_character & 0x0000ffffUL ) >= 0x0000fffeUL ) && ( ( unicode_character & 0x0000ffffUL ) <= 0x0000ffffUL ) ) || ( unicode_character == 0x000f0000UL ) || ( unicode_character == 0x000ffffdUL ) || ( unicode_character == 0x00100000UL ) || ( unicode_character >= 0x0010fffdUL ) ) { print_count = system_string_sprintf( &( safe_path[ path_index ] ), safe_path_size - path_index, _SYSTEM_STRING( "%" PRIc_SYSTEM "U%08" PRIx32 "" ), escape_character, unicode_character ); if( print_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_INPUT_FAILED, "%s: unable to copy escaped Unicode character to path.", function ); goto on_error; } path_index += print_count; } /* Replace: * Escape character (\) by \\ * Bodyfile value seperator (|) by \| */ else if( ( unicode_character == (libuna_unicode_character_t) escape_character ) || ( unicode_character == '|' ) ) { if( ( path_index + 2 ) > safe_path_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid path index value out of bounds.", function ); goto on_error; } safe_path[ path_index++ ] = escape_character; safe_path[ path_index++ ] = (system_character_t) unicode_character; } else { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libuna_unicode_character_copy_to_utf16( unicode_character, (libuna_utf16_character_t *) safe_path, safe_path_size, &path_index, error ); #else result = libuna_unicode_character_copy_to_utf8( unicode_character, (libuna_utf8_character_t *) safe_path, safe_path_size, &path_index, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_INPUT_FAILED, "%s: unable to copy Unicode character to path.", function ); goto on_error; } } } safe_path[ path_index ] = 0; *path = safe_path; *path_size = safe_path_size; return( 1 ); on_error: if( safe_path != NULL ) { memory_free( safe_path ); } return( -1 ); } ================================================ FILE: fsntfstools/bodyfile.h ================================================ /* * Bodyfile functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _BODYFILE_H ) #define _BODYFILE_H #include #include #include "fsntfstools_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif int bodyfile_path_string_copy_from_file_entry_path( system_character_t **path, size_t *path_size, const system_character_t *file_entry_path, size_t file_entry_path_length, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _BODYFILE_H ) */ ================================================ FILE: fsntfstools/digest_hash.c ================================================ /* * Crypographic digest hash * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include "digest_hash.h" #include "fsntfstools_libcerror.h" /* Converts the digest hash to a printable string * Returns 1 if successful or -1 on error */ int digest_hash_copy_to_string( const uint8_t *digest_hash, size_t digest_hash_size, char *string, size_t string_size, libcerror_error_t **error ) { static char *function = "digest_hash_copy_to_string"; size_t string_iterator = 0; size_t digest_hash_iterator = 0; uint8_t digest_digit = 0; if( digest_hash == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid digest hash.", function ); return( -1 ); } if( digest_hash_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid digest hash size value exceeds maximum.", function ); return( -1 ); } if( string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid string.", function ); return( -1 ); } if( string_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid string size value exceeds maximum.", function ); return( -1 ); } /* The string requires space for 2 characters per digest hash digit and a end of string */ if( string_size < ( ( 2 * digest_hash_size ) + 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: string too small.", function ); return( -1 ); } for( digest_hash_iterator = 0; digest_hash_iterator < digest_hash_size; digest_hash_iterator++ ) { digest_digit = digest_hash[ digest_hash_iterator ] / 16; if( digest_digit <= 9 ) { string[ string_iterator++ ] = (char) ( (uint8_t) '0' + digest_digit ); } else { string[ string_iterator++ ] = (char) ( (uint8_t) 'a' + ( digest_digit - 10 ) ); } digest_digit = digest_hash[ digest_hash_iterator ] % 16; if( digest_digit <= 9 ) { string[ string_iterator++ ] = (char) ( (uint8_t) '0' + digest_digit ); } else { string[ string_iterator++ ] = (char) ( (uint8_t) 'a' + ( digest_digit - 10 ) ); } } string[ string_iterator ] = 0; return( 1 ); } ================================================ FILE: fsntfstools/digest_hash.h ================================================ /* * Crypographic digest hash * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _DIGEST_HASH_H ) #define _DIGEST_HASH_H #include #include #include "fsntfstools_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif int digest_hash_copy_to_string( const uint8_t *digest_hash, size_t digest_hash_size, char *string, size_t string_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _DIGEST_HASH_H ) */ ================================================ FILE: fsntfstools/fsntfsinfo.c ================================================ /* * Shows information obtained from a New Technology File System (NTFS) volume. * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #if defined( HAVE_IO_H ) || defined( WINAPI ) #include #endif #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #if defined( HAVE_UNISTD_H ) #include #endif #include "fsntfstools_getopt.h" #include "fsntfstools_libcerror.h" #include "fsntfstools_libclocale.h" #include "fsntfstools_libcnotify.h" #include "fsntfstools_libfsntfs.h" #include "fsntfstools_output.h" #include "fsntfstools_signal.h" #include "fsntfstools_unused.h" #include "info_handle.h" enum FSNTFSINFO_MODES { FSNTFSINFO_MODE_FILE_ENTRY, FSNTFSINFO_MODE_FILE_SYSTEM_HIERARCHY, FSNTFSINFO_MODE_MFT_ENTRY, FSNTFSINFO_MODE_USN_CHANGE_JOURNAL, FSNTFSINFO_MODE_VOLUME }; info_handle_t *fsntfsinfo_info_handle = NULL; int fsntfsinfo_abort = 0; /* Prints usage information */ void usage_fprint( FILE *stream ) { if( stream == NULL ) { return; } fprintf( stream, "Use fsntfsinfo to determine information about a New\n" " Technology File System (NTFS) volume.\n\n" ); fprintf( stream, "Usage: fsntfsinfo [ -B bodyfile ] [ -E mft_entry_index ] [ -F path ]\n" " [ -o offset ] [ -dhHUvV ] source\n\n" ); fprintf( stream, "\tsource: the source file or device\n\n" ); fprintf( stream, "\t-B: output file system hierarchy as a bodyfile\n" ); fprintf( stream, "\t-d: calculate a MD5 hash of a file entry to include in the bodyfile\n" ); fprintf( stream, "\t-E: show information about a specific MFT entry index\n" "\t or \"all\".\n" ); fprintf( stream, "\t-F: show information about a specific file entry path.\n" ); fprintf( stream, "\t-h: shows this help\n" ); fprintf( stream, "\t-H: shows the file system hierarchy\n" ); fprintf( stream, "\t-o: specify the volume offset\n" ); fprintf( stream, "\t-U: shows information from the USN change journal ($UsnJrnl)\n" ); fprintf( stream, "\t-v: verbose output to stderr\n" ); fprintf( stream, "\t-V: print version\n" ); } /* Signal handler for fsntfsinfo */ void fsntfsinfo_signal_handler( fsntfstools_signal_t signal FSNTFSTOOLS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; static char *function = "fsntfsinfo_signal_handler"; FSNTFSTOOLS_UNREFERENCED_PARAMETER( signal ) fsntfsinfo_abort = 1; if( fsntfsinfo_info_handle != NULL ) { if( info_handle_signal_abort( fsntfsinfo_info_handle, &error ) != 1 ) { libcnotify_printf( "%s: unable to signal info handle to abort.\n", function ); libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } } /* Force stdin to close otherwise any function reading it will remain blocked */ #if defined( WINAPI ) && !defined( __CYGWIN__ ) if( _close( 0 ) != 0 ) #else if( close( 0 ) != 0 ) #endif { libcnotify_printf( "%s: unable to close stdin.\n", function ); } } /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc, wchar_t * const argv[] ) #else int main( int argc, char * const argv[] ) #endif { libcerror_error_t *error = NULL; system_character_t *option_bodyfile = NULL; system_character_t *option_file_entry = NULL; system_character_t *option_mft_entry_index = NULL; system_character_t *option_volume_offset = NULL; system_character_t *source = NULL; char *program = "fsntfsinfo"; system_integer_t option = 0; size_t string_length = 0; uint64_t mft_entry_index = 0; uint8_t calculate_md5 = 0; int option_mode = FSNTFSINFO_MODE_VOLUME; int result = 0; int verbose = 0; libcnotify_stream_set( stderr, NULL ); libcnotify_verbose_set( 1 ); if( libclocale_initialize( "fsntfstools", &error ) != 1 ) { fprintf( stderr, "Unable to initialize locale values.\n" ); goto on_error; } if( fsntfstools_output_initialize( _IONBF, &error ) != 1 ) { fprintf( stderr, "Unable to initialize output settings.\n" ); goto on_error; } fsntfstools_output_version_fprint( stdout, program ); while( ( option = fsntfstools_getopt( argc, argv, _SYSTEM_STRING( "B:dE:F:hHo:UvV" ) ) ) != (system_integer_t) -1 ) { switch( option ) { case (system_integer_t) '?': default: fprintf( stderr, "Invalid argument: %" PRIs_SYSTEM "\n", argv[ optind - 1 ] ); usage_fprint( stdout ); return( EXIT_FAILURE ); case (system_integer_t) 'B': option_bodyfile = optarg; break; case (system_integer_t) 'd': calculate_md5 = 1; break; case (system_integer_t) 'E': option_mode = FSNTFSINFO_MODE_MFT_ENTRY; option_mft_entry_index = optarg; break; case (system_integer_t) 'F': option_mode = FSNTFSINFO_MODE_FILE_ENTRY; option_file_entry = optarg; break; case (system_integer_t) 'h': usage_fprint( stdout ); return( EXIT_SUCCESS ); case (system_integer_t) 'H': option_mode = FSNTFSINFO_MODE_FILE_SYSTEM_HIERARCHY; break; case (system_integer_t) 'o': option_volume_offset = optarg; break; case (system_integer_t) 'U': option_mode = FSNTFSINFO_MODE_USN_CHANGE_JOURNAL; break; case (system_integer_t) 'v': verbose = 1; break; case (system_integer_t) 'V': fsntfstools_output_copyright_fprint( stdout ); return( EXIT_SUCCESS ); } } if( optind == argc ) { fprintf( stderr, "Missing source file or device.\n" ); usage_fprint( stdout ); return( EXIT_FAILURE ); } source = argv[ optind ]; libcnotify_verbose_set( verbose ); libfsntfs_notify_set_stream( stderr, NULL ); libfsntfs_notify_set_verbose( verbose ); if( info_handle_initialize( &fsntfsinfo_info_handle, calculate_md5, &error ) != 1 ) { fprintf( stderr, "Unable to initialize info handle.\n" ); goto on_error; } if( option_bodyfile != NULL ) { if( info_handle_set_bodyfile( fsntfsinfo_info_handle, option_bodyfile, &error ) != 1 ) { fprintf( stderr, "Unable to set bodyfile.\n" ); goto on_error; } } if( option_volume_offset != NULL ) { if( info_handle_set_volume_offset( fsntfsinfo_info_handle, option_volume_offset, &error ) != 1 ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); fprintf( stderr, "Unsupported volume offset defaulting to: %" PRIi64 ".\n", fsntfsinfo_info_handle->volume_offset ); } } /* TODO check for BDE */ if( info_handle_open_input( fsntfsinfo_info_handle, source, &error ) != 1 ) { fprintf( stderr, "Unable to open: %" PRIs_SYSTEM ".\n", source ); goto on_error; } switch( option_mode ) { case FSNTFSINFO_MODE_FILE_ENTRY: if( fsntfsinfo_info_handle->input_volume == NULL ) { fprintf( stderr, "Unable to print file entry information.\n" ); goto on_error; } if( info_handle_file_entry_fprint_by_path( fsntfsinfo_info_handle, option_file_entry, &error ) != 1 ) { fprintf( stderr, "Unable to print file entry information.\n" ); goto on_error; } break; case FSNTFSINFO_MODE_FILE_SYSTEM_HIERARCHY: if( info_handle_file_system_hierarchy_fprint( fsntfsinfo_info_handle, &error ) != 1 ) { fprintf( stderr, "Unable to print file system hierarchy.\n" ); goto on_error; } break; case FSNTFSINFO_MODE_MFT_ENTRY: if( option_mft_entry_index == NULL ) { fprintf( stderr, "Mising MFT entry index string.\n" ); goto on_error; } string_length = system_string_length( option_mft_entry_index ); if( ( string_length == 3 ) && ( system_string_compare( option_mft_entry_index, _SYSTEM_STRING( "all" ), 3 ) == 0 ) ) { if( info_handle_mft_entries_fprint( fsntfsinfo_info_handle, &error ) != 1 ) { fprintf( stderr, "Unable to print MFT entries.\n" ); goto on_error; } } else if( fsntfstools_system_string_copy_decimal_to_integer_64_bit( option_mft_entry_index, string_length + 1, &mft_entry_index, &error ) == 1 ) { if( mft_entry_index > (uint64_t) INT64_MAX ) { fprintf( stderr, "Invalid MFT entry index value out of bounds." ); goto on_error; } result = info_handle_mft_entry_fprint( fsntfsinfo_info_handle, mft_entry_index, &error ); if( result == -1 ) { fprintf( stderr, "Error printing MFT entry: %" PRIu64 ".\n", mft_entry_index ); goto on_error; } else if( result == 0 ) { fprintf( stderr, "Unable to print MFT entry: %" PRIu64 ".\n", mft_entry_index ); goto on_error; } } else { fprintf( stderr, "Unable to copy MFT entry index string to 64-bit decimal.\n" ); goto on_error; } break; case FSNTFSINFO_MODE_USN_CHANGE_JOURNAL: if( fsntfsinfo_info_handle->input_volume == NULL ) { fprintf( stderr, "Unable to print USN change journal ($UsnJrnl) information.\n" ); goto on_error; } if( info_handle_usn_change_journal_fprint( fsntfsinfo_info_handle, &error ) != 1 ) { fprintf( stderr, "Unable to print USN change journal ($UsnJrnl) information.\n" ); goto on_error; } break; case FSNTFSINFO_MODE_VOLUME: default: if( info_handle_volume_fprint( fsntfsinfo_info_handle, &error ) != 1 ) { fprintf( stderr, "Unable to print volume information.\n" ); goto on_error; } break; } if( info_handle_close_input( fsntfsinfo_info_handle, &error ) != 0 ) { fprintf( stderr, "Unable to close info handle.\n" ); goto on_error; } if( info_handle_free( &fsntfsinfo_info_handle, &error ) != 1 ) { fprintf( stderr, "Unable to free info handle.\n" ); goto on_error; } return( EXIT_SUCCESS ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } if( fsntfsinfo_info_handle != NULL ) { info_handle_free( &fsntfsinfo_info_handle, NULL ); } return( EXIT_FAILURE ); } ================================================ FILE: fsntfstools/fsntfsmount.c ================================================ /* * Mounts a New Technology File System (NTFS) volume. * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #if defined( HAVE_IO_H ) || defined( WINAPI ) #include #endif #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #if defined( HAVE_UNISTD_H ) #include #endif #include "fsntfstools_getopt.h" #include "fsntfstools_i18n.h" #include "fsntfstools_libcerror.h" #include "fsntfstools_libclocale.h" #include "fsntfstools_libcnotify.h" #include "fsntfstools_libfsntfs.h" #include "fsntfstools_output.h" #include "fsntfstools_signal.h" #include "fsntfstools_unused.h" #include "mount_dokan.h" #include "mount_fuse.h" #include "mount_handle.h" mount_handle_t *fsntfsmount_mount_handle = NULL; int fsntfsmount_abort = 0; /* Prints usage information */ void usage_fprint( FILE *stream ) { if( stream == NULL ) { return; } fprintf( stream, "Use fsntfsmount to mount a New Technology File System (NTFS) volume\n\n" ); fprintf( stream, "Usage: fsntfsmount [ -o offset ] [ -X extended_options ] [ -hvV ] volume\n" " mount_point\n\n" ); fprintf( stream, "\tvolume: a New Technology File System (NTFS) volume\n\n" ); fprintf( stream, "\tmount_point: the directory to serve as mount point\n\n" ); fprintf( stream, "\t-h: shows this help\n" ); fprintf( stream, "\t-o: specify the volume offset in bytes\n" ); fprintf( stream, "\t-v: verbose output to stderr, while fsntfsmount will remain running in the\n" "\t foreground\n" ); fprintf( stream, "\t-V: print version\n" ); fprintf( stream, "\t-X: extended options to pass to sub system\n" ); } /* Signal handler for fsntfsmount */ void fsntfsmount_signal_handler( fsntfstools_signal_t signal FSNTFSTOOLS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; static char *function = "fsntfsmount_signal_handler"; FSNTFSTOOLS_UNREFERENCED_PARAMETER( signal ) fsntfsmount_abort = 1; if( fsntfsmount_mount_handle != NULL ) { if( mount_handle_signal_abort( fsntfsmount_mount_handle, &error ) != 1 ) { libcnotify_printf( "%s: unable to signal mount handle to abort.\n", function ); libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } } /* Force stdin to close otherwise any function reading it will remain blocked */ #if defined( WINAPI ) && !defined( __CYGWIN__ ) if( _close( 0 ) != 0 ) #else if( close( 0 ) != 0 ) #endif { libcnotify_printf( "%s: unable to close stdin.\n", function ); } } /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc, wchar_t * const argv[] ) #else int main( int argc, char * const argv[] ) #endif { libfsntfs_error_t *error = NULL; system_character_t *mount_point = NULL; system_character_t *option_extended_options = NULL; system_character_t *option_offset = NULL; system_character_t *source = NULL; char *program = "fsntfsmount"; system_integer_t option = 0; int result = 0; int verbose = 0; #if defined( HAVE_LIBFUSE ) || defined( HAVE_LIBFUSE3 ) || defined( HAVE_LIBOSXFUSE ) struct fuse_operations fsntfsmount_fuse_operations; #if defined( HAVE_LIBFUSE3 ) /* Need to set this to 1 even if there no arguments, otherwise this causes * fuse: empty argv passed to fuse_session_new() */ char *fuse_argv[ 2 ] = { program, NULL }; struct fuse_args fsntfsmount_fuse_arguments = FUSE_ARGS_INIT(1, fuse_argv); #else struct fuse_args fsntfsmount_fuse_arguments = FUSE_ARGS_INIT(0, NULL); struct fuse_chan *fsntfsmount_fuse_channel = NULL; #endif struct fuse *fsntfsmount_fuse_handle = NULL; #elif defined( HAVE_LIBDOKAN ) DOKAN_OPERATIONS fsntfsmount_dokan_operations; DOKAN_OPTIONS fsntfsmount_dokan_options; #endif libcnotify_stream_set( stderr, NULL ); libcnotify_verbose_set( 1 ); if( libclocale_initialize( "fsntfstools", &error ) != 1 ) { fprintf( stderr, "Unable to initialize locale values.\n" ); goto on_error; } if( fsntfstools_output_initialize( _IONBF, &error ) != 1 ) { fprintf( stderr, "Unable to initialize output settings.\n" ); goto on_error; } fsntfstools_output_version_fprint( stdout, program ); while( ( option = fsntfstools_getopt( argc, argv, _SYSTEM_STRING( "ho:vVX:" ) ) ) != (system_integer_t) -1 ) { switch( option ) { case (system_integer_t) '?': default: fprintf( stderr, "Invalid argument: %" PRIs_SYSTEM "\n", argv[ optind - 1 ] ); usage_fprint( stdout ); return( EXIT_FAILURE ); case (system_integer_t) 'h': usage_fprint( stdout ); return( EXIT_SUCCESS ); case (system_integer_t) 'o': option_offset = optarg; break; case (system_integer_t) 'v': verbose = 1; break; case (system_integer_t) 'V': fsntfstools_output_copyright_fprint( stdout ); return( EXIT_SUCCESS ); case (system_integer_t) 'X': option_extended_options = optarg; break; } } if( optind == argc ) { fprintf( stderr, "Missing source volume.\n" ); usage_fprint( stdout ); return( EXIT_FAILURE ); } source = argv[ optind++ ]; if( optind == argc ) { fprintf( stderr, "Missing mount point.\n" ); usage_fprint( stdout ); return( EXIT_FAILURE ); } mount_point = argv[ optind ]; libcnotify_verbose_set( verbose ); libfsntfs_notify_set_stream( stderr, NULL ); libfsntfs_notify_set_verbose( verbose ); if( mount_handle_initialize( &fsntfsmount_mount_handle, &error ) != 1 ) { fprintf( stderr, "Unable to initialize mount handle.\n" ); goto on_error; } if( option_offset != NULL ) { if( mount_handle_set_offset( fsntfsmount_mount_handle, option_offset, &error ) != 1 ) { fprintf( stderr, "Unable to set volume offset.\n" ); goto on_error; } } if( mount_handle_open( fsntfsmount_mount_handle, source, &error ) != 1 ) { fprintf( stderr, "Unable to open source volume\n" ); goto on_error; } #if defined( HAVE_LIBFUSE ) || defined( HAVE_LIBFUSE3 ) || defined( HAVE_LIBOSXFUSE ) if( option_extended_options != NULL ) { #if defined( HAVE_LIBFUSE3 ) // fuse_opt_add_arg: Assertion `!args->argv || args->allocated' failed. fsntfsmount_fuse_arguments.argc = 0; fsntfsmount_fuse_arguments.argv = NULL; #endif /* This argument is required but ignored */ if( fuse_opt_add_arg( &fsntfsmount_fuse_arguments, "" ) != 0 ) { fprintf( stderr, "Unable add fuse arguments.\n" ); goto on_error; } if( fuse_opt_add_arg( &fsntfsmount_fuse_arguments, "-o" ) != 0 ) { fprintf( stderr, "Unable add fuse arguments.\n" ); goto on_error; } if( fuse_opt_add_arg( &fsntfsmount_fuse_arguments, option_extended_options ) != 0 ) { fprintf( stderr, "Unable add fuse arguments.\n" ); goto on_error; } } if( memory_set( &fsntfsmount_fuse_operations, 0, sizeof( struct fuse_operations ) ) == NULL ) { fprintf( stderr, "Unable to clear fuse operations.\n" ); goto on_error; } fsntfsmount_fuse_operations.open = &mount_fuse_open; fsntfsmount_fuse_operations.read = &mount_fuse_read; fsntfsmount_fuse_operations.release = &mount_fuse_release; fsntfsmount_fuse_operations.opendir = &mount_fuse_opendir; fsntfsmount_fuse_operations.readdir = &mount_fuse_readdir; fsntfsmount_fuse_operations.releasedir = &mount_fuse_releasedir; fsntfsmount_fuse_operations.getattr = &mount_fuse_getattr; fsntfsmount_fuse_operations.readlink = &mount_fuse_readlink; fsntfsmount_fuse_operations.destroy = &mount_fuse_destroy; #if defined( HAVE_LIBFUSE3 ) fsntfsmount_fuse_handle = fuse_new( &fsntfsmount_fuse_arguments, &fsntfsmount_fuse_operations, sizeof( struct fuse_operations ), fsntfsmount_mount_handle ); if( fsntfsmount_fuse_handle == NULL ) { fprintf( stderr, "Unable to create fuse handle.\n" ); goto on_error; } result = fuse_mount( fsntfsmount_fuse_handle, mount_point ); if( result != 0 ) { fprintf( stderr, "Unable to fuse mount file system.\n" ); goto on_error; } #else fsntfsmount_fuse_channel = fuse_mount( mount_point, &fsntfsmount_fuse_arguments ); if( fsntfsmount_fuse_channel == NULL ) { fprintf( stderr, "Unable to create fuse channel.\n" ); goto on_error; } fsntfsmount_fuse_handle = fuse_new( fsntfsmount_fuse_channel, &fsntfsmount_fuse_arguments, &fsntfsmount_fuse_operations, sizeof( struct fuse_operations ), fsntfsmount_mount_handle ); if( fsntfsmount_fuse_handle == NULL ) { fprintf( stderr, "Unable to create fuse handle.\n" ); goto on_error; } #endif /* defined( HAVE_LIBFUSE3 ) */ if( verbose == 0 ) { if( fuse_daemonize( 0 ) != 0 ) { fprintf( stderr, "Unable to daemonize fuse.\n" ); goto on_error; } } result = fuse_loop( fsntfsmount_fuse_handle ); if( result != 0 ) { fprintf( stderr, "Unable to run fuse loop.\n" ); goto on_error; } fuse_destroy( fsntfsmount_fuse_handle ); fuse_opt_free_args( &fsntfsmount_fuse_arguments ); return( EXIT_SUCCESS ); #elif defined( HAVE_LIBDOKAN ) if( memory_set( &fsntfsmount_dokan_operations, 0, sizeof( DOKAN_OPERATIONS ) ) == NULL ) { fprintf( stderr, "Unable to clear dokan operations.\n" ); goto on_error; } if( memory_set( &fsntfsmount_dokan_options, 0, sizeof( DOKAN_OPTIONS ) ) == NULL ) { fprintf( stderr, "Unable to clear dokan options.\n" ); goto on_error; } fsntfsmount_dokan_options.Version = DOKAN_VERSION; fsntfsmount_dokan_options.MountPoint = mount_point; #if DOKAN_MINIMUM_COMPATIBLE_VERSION >= 200 fsntfsmount_dokan_options.SingleThread = TRUE; #else fsntfsmount_dokan_options.ThreadCount = 0; #endif if( verbose != 0 ) { fsntfsmount_dokan_options.Options |= DOKAN_OPTION_STDERR; #if defined( HAVE_DEBUG_OUTPUT ) fsntfsmount_dokan_options.Options |= DOKAN_OPTION_DEBUG; #endif } /* This will only affect the drive properties fsntfsmount_dokan_options.Options |= DOKAN_OPTION_REMOVABLE; */ #if ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) fsntfsmount_dokan_options.Options |= DOKAN_OPTION_KEEP_ALIVE; fsntfsmount_dokan_operations.CreateFile = &mount_dokan_CreateFile; fsntfsmount_dokan_operations.OpenDirectory = &mount_dokan_OpenDirectory; fsntfsmount_dokan_operations.CreateDirectory = NULL; fsntfsmount_dokan_operations.Cleanup = NULL; fsntfsmount_dokan_operations.CloseFile = &mount_dokan_CloseFile; fsntfsmount_dokan_operations.ReadFile = &mount_dokan_ReadFile; fsntfsmount_dokan_operations.WriteFile = NULL; fsntfsmount_dokan_operations.FlushFileBuffers = NULL; fsntfsmount_dokan_operations.GetFileInformation = &mount_dokan_GetFileInformation; fsntfsmount_dokan_operations.FindFiles = &mount_dokan_FindFiles; fsntfsmount_dokan_operations.FindFilesWithPattern = NULL; fsntfsmount_dokan_operations.SetFileAttributes = NULL; fsntfsmount_dokan_operations.SetFileTime = NULL; fsntfsmount_dokan_operations.DeleteFile = NULL; fsntfsmount_dokan_operations.DeleteDirectory = NULL; fsntfsmount_dokan_operations.MoveFile = NULL; fsntfsmount_dokan_operations.SetEndOfFile = NULL; fsntfsmount_dokan_operations.SetAllocationSize = NULL; fsntfsmount_dokan_operations.LockFile = NULL; fsntfsmount_dokan_operations.UnlockFile = NULL; fsntfsmount_dokan_operations.GetFileSecurity = NULL; fsntfsmount_dokan_operations.SetFileSecurity = NULL; fsntfsmount_dokan_operations.GetDiskFreeSpace = NULL; fsntfsmount_dokan_operations.GetVolumeInformation = &mount_dokan_GetVolumeInformation; fsntfsmount_dokan_operations.Unmount = &mount_dokan_Unmount; #else fsntfsmount_dokan_operations.ZwCreateFile = &mount_dokan_ZwCreateFile; fsntfsmount_dokan_operations.Cleanup = NULL; fsntfsmount_dokan_operations.CloseFile = &mount_dokan_CloseFile; fsntfsmount_dokan_operations.ReadFile = &mount_dokan_ReadFile; fsntfsmount_dokan_operations.WriteFile = NULL; fsntfsmount_dokan_operations.FlushFileBuffers = NULL; fsntfsmount_dokan_operations.GetFileInformation = &mount_dokan_GetFileInformation; fsntfsmount_dokan_operations.FindFiles = &mount_dokan_FindFiles; fsntfsmount_dokan_operations.FindFilesWithPattern = NULL; fsntfsmount_dokan_operations.SetFileAttributes = NULL; fsntfsmount_dokan_operations.SetFileTime = NULL; fsntfsmount_dokan_operations.DeleteFile = NULL; fsntfsmount_dokan_operations.DeleteDirectory = NULL; fsntfsmount_dokan_operations.MoveFile = NULL; fsntfsmount_dokan_operations.SetEndOfFile = NULL; fsntfsmount_dokan_operations.SetAllocationSize = NULL; fsntfsmount_dokan_operations.LockFile = NULL; fsntfsmount_dokan_operations.UnlockFile = NULL; fsntfsmount_dokan_operations.GetFileSecurity = NULL; fsntfsmount_dokan_operations.SetFileSecurity = NULL; fsntfsmount_dokan_operations.GetDiskFreeSpace = NULL; fsntfsmount_dokan_operations.GetVolumeInformation = &mount_dokan_GetVolumeInformation; fsntfsmount_dokan_operations.Unmounted = NULL; fsntfsmount_dokan_operations.FindStreams = NULL; fsntfsmount_dokan_operations.Mounted = NULL; #endif /* ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) */ #if DOKAN_MINIMUM_COMPATIBLE_VERSION >= 200 DokanInit(); #endif result = DokanMain( &fsntfsmount_dokan_options, &fsntfsmount_dokan_operations ); #if DOKAN_MINIMUM_COMPATIBLE_VERSION >= 200 DokanShutdown(); #endif switch( result ) { case DOKAN_SUCCESS: break; case DOKAN_ERROR: fprintf( stderr, "Unable to run dokan main: generic error\n" ); break; case DOKAN_DRIVE_LETTER_ERROR: fprintf( stderr, "Unable to run dokan main: bad drive letter\n" ); break; case DOKAN_DRIVER_INSTALL_ERROR: fprintf( stderr, "Unable to run dokan main: unable to load driver\n" ); break; case DOKAN_START_ERROR: fprintf( stderr, "Unable to run dokan main: driver error\n" ); break; case DOKAN_MOUNT_ERROR: fprintf( stderr, "Unable to run dokan main: unable to assign drive letter\n" ); break; case DOKAN_MOUNT_POINT_ERROR: fprintf( stderr, "Unable to run dokan main: mount point error\n" ); break; default: fprintf( stderr, "Unable to run dokan main: unknown error: %d\n", result ); break; } return( EXIT_SUCCESS ); #else fprintf( stderr, "No sub system to mount New Technology File System (NTFS) format.\n" ); return( EXIT_FAILURE ); #endif /* defined( HAVE_LIBFUSE ) || defined( HAVE_LIBFUSE3 ) || defined( HAVE_LIBOSXFUSE ) */ on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } #if defined( HAVE_LIBFUSE ) || defined( HAVE_LIBFUSE3 ) || defined( HAVE_LIBOSXFUSE ) if( fsntfsmount_fuse_handle != NULL ) { fuse_destroy( fsntfsmount_fuse_handle ); } fuse_opt_free_args( &fsntfsmount_fuse_arguments ); #endif if( fsntfsmount_mount_handle != NULL ) { mount_handle_free( &fsntfsmount_mount_handle, NULL ); } return( EXIT_FAILURE ); } ================================================ FILE: fsntfstools/fsntfstools_getopt.c ================================================ /* * GetOpt functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfstools_getopt.h" #include "fsntfstools_libcnotify.h" #if !defined( HAVE_GETOPT ) /* The option index * Start with argument 1 (argument 0 is the program name) */ int optind = 1; /* The current option argument */ system_character_t *optarg = NULL; /* Value to indicate the current option */ system_integer_t optopt = 0; /* The next option in a group */ system_character_t *next_option = NULL; /* Get the program options * Function for platforms that do not have the getopt function * Returns the option character processed, or -1 on error, * ? if the option was not in the options string, : if the option argument was missing */ system_integer_t fsntfstools_getopt( int argument_count, system_character_t * const argument_values[], const system_character_t *options_string ) { system_character_t *argument_value = NULL; system_character_t *option_value = NULL; static char *function = "fsntfstools_getopt"; size_t options_string_length = 0; if( next_option != NULL ) { argument_value = next_option; next_option = NULL; } else if( optind >= argument_count ) { return( (system_integer_t) -1 ); } else { argument_value = argument_values[ optind ]; /* Check if the argument value is not an empty string */ if( *argument_value == (system_character_t) '\0' ) { return( (system_integer_t) -1 ); } /* Check if the first character is a option marker '-' */ if( *argument_value != (system_character_t) '-' ) { return( (system_integer_t) -1 ); } argument_value++; /* Check if long options are provided '--' */ if( *argument_value == (system_character_t) '-' ) { optind++; return( (system_integer_t) -1 ); } } options_string_length = system_string_length( options_string ); optopt = *argument_value; option_value = system_string_search_character( options_string, optopt, options_string_length ); argument_value++; /* Check if an argument was specified or that the option was not found * in the option string */ if( ( optopt == (system_integer_t) ':' ) || ( option_value == NULL ) ) { if( *argument_value == (system_character_t) '\0' ) { optind++; } if( ( *options_string != (system_character_t) ':' ) && ( optopt != (system_integer_t) '?' ) ) { libcnotify_printf( "%s: no such option: %" PRIc_SYSTEM ".\n", function, optopt ); } return( (system_integer_t) '?' ); } option_value++; /* Check if no option argument is required */ if( *option_value != (system_character_t) ':' ) { optarg = NULL; if( *argument_value == (system_character_t) '\0' ) { optind++; } else { /* Multiple options are grouped */ next_option = argument_value; } } /* Check if the argument is right after the option flag with no space in between */ else if( *argument_value != (system_character_t) '\0' ) { optarg = argument_value; optind++; } else { optind++; /* Check if the argument was provided as the next argument value */ if( argument_count <= optind ) { if( *option_value == ':' ) { return( (system_integer_t) ':' ); } libcnotify_printf( "%s: option: %" PRIc_SYSTEM " requires an argument.\n", function, optopt ); return( (system_integer_t) '?' ); } optarg = argument_values[ optind ]; optind++; } return( optopt ); } #endif /* !defined( HAVE_GETOPT ) */ ================================================ FILE: fsntfstools/fsntfstools_getopt.h ================================================ /* * GetOpt functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_GETOPT_H ) #define _FSNTFSTOOLS_GETOPT_H #include #include /* unistd.h is included here to export getopt, optarg, optind and optopt */ #if defined( HAVE_UNISTD_H ) #include #endif #if defined( __cplusplus ) extern "C" { #endif #if defined( HAVE_GETOPT ) #define fsntfstools_getopt( argument_count, argument_values, options_string ) \ getopt( argument_count, argument_values, options_string ) #else #if !defined( __CYGWIN__ ) extern int optind; extern system_character_t *optarg; extern system_integer_t optopt; #else int optind; system_character_t *optarg; system_integer_t optopt; #endif /* !defined( __CYGWIN__ ) */ system_integer_t fsntfstools_getopt( int argument_count, system_character_t * const argument_values[], const system_character_t *options_string ); #endif /* defined( HAVE_GETOPT ) */ #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFSTOOLS_GETOPT_H ) */ ================================================ FILE: fsntfstools/fsntfstools_i18n.h ================================================ /* * Internationalization (i18n) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_I18N_H ) #define _FSNTFSTOOLS_I18N_H #include #if defined( HAVE_LIBINTL_H ) #include #endif #if defined( __cplusplus ) extern "C" { #endif /* TODO for now do nothing i18n-like #define _( string ) \ gettext( string ) */ #define _( string ) \ string #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFSTOOLS_I18N_H ) */ ================================================ FILE: fsntfstools/fsntfstools_libbfio.h ================================================ /* * The libbfio header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_LIBBFIO_H ) #define _FSNTFSTOOLS_LIBBFIO_H #include /* Define HAVE_LOCAL_LIBBFIO for local use of libbfio */ #if defined( HAVE_LOCAL_LIBBFIO ) #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBBFIO_DLL_IMPORT * before including libbfio.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) && !defined( HAVE_STATIC_EXECUTABLES ) #define LIBBFIO_DLL_IMPORT #endif #include #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( LIBBFIO_HAVE_MULTI_THREAD_SUPPORT ) #error Multi-threading support requires libbfio with multi-threading support #endif #endif /* defined( HAVE_LOCAL_LIBBFIO ) */ #endif /* !defined( _FSNTFSTOOLS_LIBBFIO_H ) */ ================================================ FILE: fsntfstools/fsntfstools_libcerror.h ================================================ /* * The libcerror header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_LIBCERROR_H ) #define _FSNTFSTOOLS_LIBCERROR_H #include /* Define HAVE_LOCAL_LIBCERROR for local use of libcerror */ #if defined( HAVE_LOCAL_LIBCERROR ) #include #include #include #include #else /* If libtool DLL support is enabled set LIBCERROR_DLL_IMPORT * before including libcerror.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) && !defined( HAVE_STATIC_EXECUTABLES ) #define LIBCERROR_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBCERROR ) */ #endif /* !defined( _FSNTFSTOOLS_LIBCERROR_H ) */ ================================================ FILE: fsntfstools/fsntfstools_libclocale.h ================================================ /* * The libclocale header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_LIBCLOCALE_H ) #define _FSNTFSTOOLS_LIBCLOCALE_H #include /* Define HAVE_LOCAL_LIBCLOCALE for local use of libclocale */ #if defined( HAVE_LOCAL_LIBCLOCALE ) #include #include #include #include #else /* If libtool DLL support is enabled set LIBCLOCALE_DLL_IMPORT * before including libclocale.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) && !defined( HAVE_STATIC_EXECUTABLES ) #define LIBCLOCALE_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBCLOCALE ) */ #endif /* !defined( _FSNTFSTOOLS_LIBCLOCALE_H ) */ ================================================ FILE: fsntfstools/fsntfstools_libcnotify.h ================================================ /* * The libcnotify header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_LIBCNOTIFY_H ) #define _FSNTFSTOOLS_LIBCNOTIFY_H #include /* Define HAVE_LOCAL_LIBCNOTIFY for local use of libcnotify */ #if defined( HAVE_LOCAL_LIBCNOTIFY ) #include #include #include #include #else /* If libtool DLL support is enabled set LIBCNOTIFY_DLL_IMPORT * before including libcnotify.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) && !defined( HAVE_STATIC_EXECUTABLES ) #define LIBCNOTIFY_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBCNOTIFY ) */ #endif /* !defined( _FSNTFSTOOLS_LIBCNOTIFY_H ) */ ================================================ FILE: fsntfstools/fsntfstools_libcpath.h ================================================ /* * The libcpath header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_LIBCPATH_H ) #define _FSNTFSTOOLS_LIBCPATH_H #include /* Define HAVE_LOCAL_LIBCPATH for local use of libcpath */ #if defined( HAVE_LOCAL_LIBCPATH ) #include #include #else /* If libtool DLL support is enabled set LIBCPATH_DLL_IMPORT * before including libcpath.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) && !defined( HAVE_STATIC_EXECUTABLES ) #define LIBCPATH_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBCPATH ) */ #endif /* !defined( _FSNTFSTOOLS_LIBCPATH_H ) */ ================================================ FILE: fsntfstools/fsntfstools_libfcache.h ================================================ /* * The libfcache header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_LIBFCACHE_H ) #define _FSNTFSTOOLS_LIBFCACHE_H #include /* Define HAVE_LOCAL_LIBFCACHE for local use of libfcache */ #if defined( HAVE_LOCAL_LIBFCACHE ) #include #include #include #include #else /* If libtool DLL support is enabled set LIBFCACHE_DLL_IMPORT * before including libfcache.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) && !defined( HAVE_STATIC_EXECUTABLES ) #define LIBFCACHE_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBFCACHE ) */ #endif /* !defined( _FSNTFSTOOLS_LIBFCACHE_H ) */ ================================================ FILE: fsntfstools/fsntfstools_libfdata.h ================================================ /* * The libfdata header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_LIBFDATA_H ) #define _FSNTFSTOOLS_LIBFDATA_H #include /* Define HAVE_LOCAL_LIBFDATA for local use of libfdata */ #if defined( HAVE_LOCAL_LIBFDATA ) #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBFDATA_DLL_IMPORT * before including libfdata.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) && !defined( HAVE_STATIC_EXECUTABLES ) #define LIBFDATA_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBFDATA ) */ #endif /* !defined( _FSNTFSTOOLS_LIBFDATA_H ) */ ================================================ FILE: fsntfstools/fsntfstools_libfdatetime.h ================================================ /* * The libfdatetime header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_LIBFDATETIME_H ) #define _FSNTFSTOOLS_LIBFDATETIME_H #include /* Define HAVE_LOCAL_LIBFDATETIME for local use of libfdatetime */ #if defined( HAVE_LOCAL_LIBFDATETIME ) #include #include #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBFDATETIME_DLL_IMPORT * before including libfdatetime.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) && !defined( HAVE_STATIC_EXECUTABLES ) #define LIBFDATETIME_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBFDATETIME ) */ #endif /* !defined( _FSNTFSTOOLS_LIBFDATETIME_H ) */ ================================================ FILE: fsntfstools/fsntfstools_libfguid.h ================================================ /* * The libfguid header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_LIBFGUID_H ) #define _FSNTFSTOOLS_LIBFGUID_H #include /* Define HAVE_LOCAL_LIBFGUID for local use of libfguid */ #if defined( HAVE_LOCAL_LIBFGUID ) #include #include #include #else /* If libtool DLL support is enabled set LIBFGUID_DLL_IMPORT * before including libfguid.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) && !defined( HAVE_STATIC_EXECUTABLES ) #define LIBFGUID_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBFGUID ) */ #endif /* !defined( _FSNTFSTOOLS_LIBFGUID_H ) */ ================================================ FILE: fsntfstools/fsntfstools_libfsntfs.h ================================================ /* * The libfsntfs header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_LIBFSNTFS_H ) #define _FSNTFSTOOLS_LIBFSNTFS_H #include #include #endif /* !defined( _FSNTFSTOOLS_LIBFSNTFS_H ) */ ================================================ FILE: fsntfstools/fsntfstools_libfusn.h ================================================ /* * The libfusn header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_LIBFUSN_H ) #define _FSNTFSTOOLS_LIBFUSN_H #include /* Define HAVE_LOCAL_LIBFUSN for local use of libfusn */ #if defined( HAVE_LOCAL_LIBFUSN ) #include #include #include #else /* If libtool DLL support is enabled set LIBFUSN_DLL_IMPORT * before including libfusn.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) && !defined( HAVE_STATIC_EXECUTABLES ) #define LIBFUSN_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBFUSN ) */ #endif /* !defined( _FSNTFSTOOLS_LIBFUSN_H ) */ ================================================ FILE: fsntfstools/fsntfstools_libfwnt.h ================================================ /* * The libfwnt header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_LIBFWNT_H ) #define _FSNTFSTOOLS_LIBFWNT_H #include /* Define HAVE_LOCAL_LIBFWNT for local use of libfwnt */ #if defined( HAVE_LOCAL_LIBFWNT ) #include #include #include #include #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBFWNT_DLL_IMPORT * before including libfwnt.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) && !defined( HAVE_STATIC_EXECUTABLES ) #define LIBFWNT_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBFWNT ) */ #endif /* !defined( _FSNTFSTOOLS_LIBFWNT_H ) */ ================================================ FILE: fsntfstools/fsntfstools_libhmac.h ================================================ /* * The libhmac header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_LIBHMAC_H ) #define _FSNTFSTOOLS_LIBHMAC_H #include #if defined( HAVE_LOCAL_LIBHMAC ) #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBHMAC_DLL_IMPORT * before including libhmac.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) && !defined( HAVE_STATIC_EXECUTABLES ) #define LIBHMAC_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBHMAC ) */ #endif /* !defined( _FSNTFSTOOLS_LIBHMAC_H ) */ ================================================ FILE: fsntfstools/fsntfstools_libuna.h ================================================ /* * The libuna header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_LIBUNA_H ) #define _FSNTFSTOOLS_LIBUNA_H #include /* Define HAVE_LOCAL_LIBUNA for local use of libuna */ #if defined( HAVE_LOCAL_LIBUNA ) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBUNA_DLL_IMPORT * before including libuna.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) && !defined( HAVE_STATIC_EXECUTABLES ) #define LIBUNA_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBUNA ) */ #endif /* !defined( _FSNTFSTOOLS_LIBUNA_H ) */ ================================================ FILE: fsntfstools/fsntfstools_output.c ================================================ /* * Common output functions for the fsntfstools * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "fsntfstools_i18n.h" #include "fsntfstools_libbfio.h" #include "fsntfstools_libcerror.h" #include "fsntfstools_libclocale.h" #include "fsntfstools_libcnotify.h" #include "fsntfstools_libfcache.h" #include "fsntfstools_libfdata.h" #include "fsntfstools_libfdatetime.h" #include "fsntfstools_libfguid.h" #include "fsntfstools_libfsntfs.h" #include "fsntfstools_libfusn.h" #include "fsntfstools_libfwnt.h" #include "fsntfstools_libuna.h" #include "fsntfstools_output.h" /* Initializes output settings * Returns 1 if successful or -1 on error */ int fsntfstools_output_initialize( int stdio_mode, libcerror_error_t **error ) { static char *function = "fsntfstools_output_initialize"; if( ( stdio_mode != _IOFBF ) && ( stdio_mode != _IOLBF ) && ( stdio_mode != _IONBF ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported standard IO mode.", function ); return( -1 ); } #if !defined( __BORLANDC__ ) if( setvbuf( stdout, NULL, stdio_mode, 0 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set IO mode of stdout.", function ); return( -1 ); } if( setvbuf( stderr, NULL, stdio_mode, 0 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set IO mode of stderr.", function ); return( -1 ); } #endif /* !defined( __BORLANDC__ ) */ return( 1 ); } /* Prints the copyright information */ void fsntfstools_output_copyright_fprint( FILE *stream ) { if( stream == NULL ) { return; } /* TRANSLATORS: This is a proper name. */ fprintf( stream, _( "Copyright (C) 2010-2026, %s.\n" ), _( "Joachim Metz" ) ); fprintf( stream, _( "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" ) ); /* TRANSLATORS: The placeholder indicates the bug-reporting address * for this package. Please add _another line_ saying * "Report translation bugs to <...>\n" with the address for translation * bugs (typically your translation team's web or email address). */ fprintf( stream, _( "Report bugs to <%s>.\n" ), PACKAGE_BUGREPORT ); } /* Prints the version information */ void fsntfstools_output_version_fprint( FILE *stream, const char *program ) { if( stream == NULL ) { return; } if( program == NULL ) { return; } fprintf( stream, "%s %s\n\n", program, LIBFSNTFS_VERSION_STRING ); } /* Prints the detailed version information */ void fsntfstools_output_version_detailed_fprint( FILE *stream, const char *program ) { if( stream == NULL ) { return; } if( program == NULL ) { return; } fprintf( stream, "%s %s (libfsntfs %s", program, LIBFSNTFS_VERSION_STRING, LIBFSNTFS_VERSION_STRING ); fprintf( stream, ", libuna %s", LIBUNA_VERSION_STRING ); fprintf( stream, ", libbfio %s", LIBBFIO_VERSION_STRING ); fprintf( stream, ", libfcache %s", LIBFCACHE_VERSION_STRING ); fprintf( stream, ", libfdata %s", LIBFDATA_VERSION_STRING ); fprintf( stream, ", libfdatetime %s", LIBFDATETIME_VERSION_STRING ); fprintf( stream, ", libfguid %s", LIBFGUID_VERSION_STRING ); fprintf( stream, ", libfusn %s", LIBFUSN_VERSION_STRING ); fprintf( stream, ", libfwnt %s", LIBFWNT_VERSION_STRING ); fprintf( stream, ")\n\n" ); } ================================================ FILE: fsntfstools/fsntfstools_output.h ================================================ /* * Common output functions for the fsntfstools * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_OUTPUT_H ) #define _FSNTFSTOOLS_OUTPUT_H #include #include #include #include "fsntfstools_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif int fsntfstools_output_initialize( int stdio_mode, libcerror_error_t **error ); void fsntfstools_output_copyright_fprint( FILE *stream ); void fsntfstools_output_version_fprint( FILE *stream, const char *program ); void fsntfstools_output_version_detailed_fprint( FILE *stream, const char *program ); #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFSTOOLS_OUTPUT_H ) */ ================================================ FILE: fsntfstools/fsntfstools_signal.c ================================================ /* * Signal handling functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_SIGNAL_H ) #include #endif #if defined( _MSC_VER ) #include #endif #include "fsntfstools_libcerror.h" #include "fsntfstools_signal.h" #if defined( WINAPI ) void (*fsntfstools_signal_signal_handler)( fsntfstools_signal_t ) = NULL; /* Signal handler for Ctrl+C or Ctrl+Break signals */ BOOL WINAPI fsntfstools_signal_handler( fsntfstools_signal_t signal ) { static char *function = "fsntfstools_signal_handler"; switch( signal ) { /* use Ctrl+C or Ctrl+Break to simulate SERVICE_CONTROL_STOP in debug mode */ case CTRL_BREAK_EVENT: case CTRL_C_EVENT: if( fsntfstools_signal_signal_handler != NULL ) { fsntfstools_signal_signal_handler( signal ); } return( TRUE ); default: break; } return( FALSE ); } #if defined( _MSC_VER ) /* Initialize memory usage and leakage debugging */ void fsntfstools_signal_initialize_memory_debug( void ) { int flag = 0; /* Get the current state of the flag and store it in a temporary variable */ flag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); /* Turn on client block identifiers and automatic leak detection */ flag |= ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); /* Set the new state for the flag */ _CrtSetDbgFlag( flag ); } #endif /* defined( _MSC_VER ) */ /* Attaches a signal handler for Ctrl+C or Ctrl+Break signals * Returns 1 if successful or -1 on error */ int fsntfstools_signal_attach( void (*signal_handler)( fsntfstools_signal_t ), libcerror_error_t **error ) { static char *function = "fsntfstools_signal_attach"; if( signal_handler == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid signal handler.", function ); return( -1 ); } fsntfstools_signal_signal_handler = signal_handler; if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) fsntfstools_signal_handler, TRUE ) == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to attach signal handler.", function ); return( -1 ); } if( SetConsoleCtrlHandler( NULL, FALSE ) == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to attach break signal.", function ); return( -1 ); } #if defined( _MSC_VER ) fsntfstools_signal_initialize_memory_debug(); #endif SetErrorMode( SEM_FAILCRITICALERRORS ); #if defined( LOCALE_SUPPORT ) /* Allow subsequent threads to have their own locale. * If the application is single threaded this call has * no practical effect. */ _configthreadlocale( _ENABLE_PER_THREAD_LOCALE ); /* Set the current thread locale to the user default * ANSI code page. */ setlocale( LC_ALL, "" ); /* Set the the code page used by multibyte functions * to use the same code page as the previous call to setlocale. */ _setmbcp( _MB_CP_LOCALE ); #endif /* defined( LOCALE_SUPPORT ) */ return( 1 ); } /* Detaches a signal handler for Ctrl+C or Ctrl+Break signals * Returns 1 if successful or -1 on error */ int fsntfstools_signal_detach( libcerror_error_t **error ) { static char *function = "fsntfstools_signal_detach"; if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) fsntfstools_signal_handler, FALSE ) == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to detach signal handler.", function ); return( -1 ); } fsntfstools_signal_signal_handler = NULL; return( 1 ); } #else /* Attaches a signal handler for SIGINT * Returns 1 if successful or -1 on error */ int fsntfstools_signal_attach( void (*signal_handler)( fsntfstools_signal_t ), libcerror_error_t **error ) { static char *function = "fsntfstools_signal_attach"; if( signal_handler == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid signal handler.", function ); return( -1 ); } if( signal( SIGINT, signal_handler ) == SIG_ERR ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to attach signal handler.", function ); return( -1 ); } return( 1 ); } /* Detaches a signal handler for SIGINT * Returns 1 if successful or -1 on error */ int fsntfstools_signal_detach( libcerror_error_t **error ) { static char *function = "fsntfstools_signal_detach"; if( signal( SIGINT, SIG_DFL ) == SIG_ERR ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to detach signal handler.", function ); return( -1 ); } return( 1 ); } #endif /* defined( WINAPI ) */ ================================================ FILE: fsntfstools/fsntfstools_signal.h ================================================ /* * Signal handling functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_SIGNAL_H ) #define _FSNTFSTOOLS_SIGNAL_H #include #include #include "fsntfstools_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif #if !defined( HAVE_SIGNAL_H ) && !defined( WINAPI ) #error missing signal functions #endif #if defined( WINAPI ) typedef unsigned long fsntfstools_signal_t; #else typedef int fsntfstools_signal_t; #endif /* defined( WINAPI ) */ #if defined( WINAPI ) BOOL WINAPI fsntfstools_signal_handler( fsntfstools_signal_t signal ); #if defined( _MSC_VER ) void fsntfstools_signal_initialize_memory_debug( void ); #endif /* defined( _MSC_VER ) */ #endif /* defined( WINAPI ) */ int fsntfstools_signal_attach( void (*signal_handler)( fsntfstools_signal_t ), libcerror_error_t **error ); int fsntfstools_signal_detach( libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFSTOOLS_SIGNAL_H ) */ ================================================ FILE: fsntfstools/fsntfstools_unused.h ================================================ /* * Definitions to silence compiler warnings about unused function attributes/parameters. * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFSTOOLS_UNUSED_H ) #define _FSNTFSTOOLS_UNUSED_H #include #if !defined( FSNTFSTOOLS_ATTRIBUTE_UNUSED ) #if defined( __GNUC__ ) && __GNUC__ >= 3 #define FSNTFSTOOLS_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) #else #define FSNTFSTOOLS_ATTRIBUTE_UNUSED #endif /* defined( __GNUC__ ) && __GNUC__ >= 3 */ #endif /* !defined( FSNTFSTOOLS_ATTRIBUTE_UNUSED ) */ #if defined( _MSC_VER ) #define FSNTFSTOOLS_UNREFERENCED_PARAMETER( parameter ) \ UNREFERENCED_PARAMETER( parameter ); #else #define FSNTFSTOOLS_UNREFERENCED_PARAMETER( parameter ) \ /* parameter */ #endif /* defined( _MSC_VER ) */ #endif /* !defined( _FSNTFSTOOLS_UNUSED_H ) */ ================================================ FILE: fsntfstools/info_handle.c ================================================ /* * Info handle * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include "bodyfile.h" #include "digest_hash.h" #include "fsntfstools_libbfio.h" #include "fsntfstools_libcerror.h" #include "fsntfstools_libclocale.h" #include "fsntfstools_libcnotify.h" #include "fsntfstools_libcpath.h" #include "fsntfstools_libfdatetime.h" #include "fsntfstools_libfguid.h" #include "fsntfstools_libfwnt.h" #include "fsntfstools_libfsntfs.h" #include "fsntfstools_libfusn.h" #include "fsntfstools_libhmac.h" #include "fsntfstools_libuna.h" #include "info_handle.h" #include "path_string.h" #if !defined( LIBFSNTFS_HAVE_BFIO ) extern \ int libfsntfs_check_volume_signature_file_io_handle( libbfio_handle_t *file_io_handle, libcerror_error_t **error ); extern \ int libfsntfs_volume_open_file_io_handle( libfsntfs_volume_t *volume, libbfio_handle_t *file_io_handle, int access_flags, libcerror_error_t **error ); extern \ int libfsntfs_mft_metadata_file_open_file_io_handle( libfsntfs_mft_metadata_file_t *mft_metadata_file, libbfio_handle_t *file_io_handle, int access_flags, libcerror_error_t **error ); #endif /* !defined( LIBFSNTFS_HAVE_BFIO ) */ #define DIGEST_HASH_STRING_SIZE_MD5 33 #define INFO_HANDLE_NOTIFY_STREAM stdout /* Copies a string of a decimal value to a 64-bit value * Returns 1 if successful or -1 on error */ int fsntfstools_system_string_copy_decimal_to_integer_64_bit( const system_character_t *string, size_t string_size, uint64_t *value_64bit, libcerror_error_t **error ) { static char *function = "fsntfstools_system_string_copy_decimal_to_integer_64_bit"; system_character_t character_value = 0; size_t string_index = 0; uint64_t safe_value_64bit = 0; uint8_t maximum_string_index = 20; int8_t sign = 1; if( string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid string.", function ); return( -1 ); } if( ( string_size == 0 ) || ( string_size > (size_t) SSIZE_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid string size value out of bounds.", function ); return( -1 ); } if( value_64bit == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid value 64-bit.", function ); return( -1 ); } if( string[ string_index ] == (system_character_t) '-' ) { string_index++; maximum_string_index++; sign = -1; } else if( string[ string_index ] == (system_character_t) '+' ) { string_index++; maximum_string_index++; } while( string_index < string_size ) { if( string[ string_index ] == 0 ) { break; } if( string_index > (size_t) maximum_string_index ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_LARGE, "%s: string too large.", function ); return( -1 ); } safe_value_64bit *= 10; character_value = string[ string_index ]; if( ( character_value >= (system_character_t) '0' ) && ( character_value <= (system_character_t) '9' ) ) { safe_value_64bit += (uint8_t) ( character_value - (system_character_t) '0' ); } else { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported character value: %" PRIc_SYSTEM " at index: %d.", function, character_value, string_index ); return( -1 ); } string_index++; } if( sign == -1 ) { safe_value_64bit *= (uint64_t) -1; } *value_64bit = safe_value_64bit; return( 1 ); } /* Prints the file attribute flags to the notify stream */ void info_handle_file_attribute_flags_fprint( uint32_t file_attribute_flags, FILE *notify_stream ) { if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_READ_ONLY ) != 0 ) { fprintf( notify_stream, "\t\tIs read-only (FILE_ATTRIBUTE_READ_ONLY)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_HIDDEN ) != 0 ) { fprintf( notify_stream, "\t\tIs hidden (FILE_ATTRIBUTE_HIDDEN)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_SYSTEM ) != 0 ) { fprintf( notify_stream, "\t\tIs system (FILE_ATTRIBUTE_SYSTEM)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_DIRECTORY ) != 0 ) { fprintf( notify_stream, "\t\tIs directory (FILE_ATTRIBUTE_DIRECTORY)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_ARCHIVE ) != 0 ) { fprintf( notify_stream, "\t\tShould be archived (FILE_ATTRIBUTE_ARCHIVE)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_DEVICE ) != 0 ) { fprintf( notify_stream, "\t\tIs device (FILE_ATTRIBUTE_DEVICE)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_NORMAL ) != 0 ) { fprintf( notify_stream, "\t\tIs normal (FILE_ATTRIBUTE_NORMAL)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_TEMPORARY ) != 0 ) { fprintf( notify_stream, "\t\tIs temporary (FILE_ATTRIBUTE_TEMPORARY)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_SPARSE_FILE ) != 0 ) { fprintf( notify_stream, "\t\tIs a sparse file (FILE_ATTRIBUTE_SPARSE_FILE)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_REPARSE_POINT ) != 0 ) { fprintf( notify_stream, "\t\tIs a reparse point or symbolic link (FILE_ATTRIBUTE_FLAG_REPARSE_POINT)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_COMPRESSED ) != 0 ) { fprintf( notify_stream, "\t\tIs compressed (FILE_ATTRIBUTE_COMPRESSED)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_OFFLINE ) != 0 ) { fprintf( notify_stream, "\t\tIs offline (FILE_ATTRIBUTE_OFFLINE)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_NOT_CONTENT_INDEXED ) != 0 ) { fprintf( notify_stream, "\t\tContent should not be indexed (FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_ENCRYPTED ) != 0 ) { fprintf( notify_stream, "\t\tIs encrypted (FILE_ATTRIBUTE_ENCRYPTED)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_VIRTUAL ) != 0 ) { fprintf( notify_stream, "\t\tIs virtual (FILE_ATTRIBUTE_VIRTUAL)\n" ); } if( ( file_attribute_flags & 0x10000000UL ) != 0 ) { fprintf( notify_stream, "\t\tUnknown (0x10000000)\n" ); } if( ( file_attribute_flags & 0x20000000UL ) != 0 ) { fprintf( notify_stream, "\t\tIs index view (0x20000000)\n" ); } } /* Prints the volume information flags to the notify stream */ void info_handle_volume_information_flags_fprint( uint16_t volume_information_flags, FILE *notify_stream ) { if( ( volume_information_flags & 0x0001 ) != 0 ) { fprintf( notify_stream, "\t\t(VOLUME_IS_DIRTY)\n" ); } if( ( volume_information_flags & 0x0002 ) != 0 ) { fprintf( notify_stream, "\t\t(VOLUME_RESIZE_LOG_FILE)\n" ); } if( ( volume_information_flags & 0x0004 ) != 0 ) { fprintf( notify_stream, "\t\t(VOLUME_UPGRADE_ON_MOUNT)\n" ); } if( ( volume_information_flags & 0x0008 ) != 0 ) { fprintf( notify_stream, "\t\t(VOLUME_MOUNTED_ON_NT4)\n" ); } if( ( volume_information_flags & 0x0010 ) != 0 ) { fprintf( notify_stream, "\t\t(VOLUME_DELETE_USN_UNDERWAY)\n" ); } if( ( volume_information_flags & 0x0020 ) != 0 ) { fprintf( notify_stream, "\t\t(VOLUME_REPAIR_OBJECT_ID)\n" ); } if( ( volume_information_flags & 0x4000 ) != 0 ) { fprintf( notify_stream, "\t\t(VOLUME_CHKDSK_UNDERWAY)\n" ); } if( ( volume_information_flags & 0x8000 ) != 0 ) { fprintf( notify_stream, "\t\t(VOLUME_MODIFIED_BY_CHKDSK)\n" ); } } /* Retrieves a string containing the access control entry type */ const char *info_handle_get_access_control_entry_type( uint8_t entry_type ) { switch( entry_type ) { case 0x00: case 0x04: case 0x05: case 0x09: case 0x0b: return( "Access allowed" ); case 0x01: case 0x06: case 0x0a: case 0x0c: return( "Access denied" ); case 0x02: case 0x07: case 0x0d: case 0x0f: return( "System-audit" ); case 0x03: case 0x08: case 0x0e: case 0x10: return( "System-alarm" ); case 0x11: return( "Mandatory label" ); } return( "UNKNOWN" ); } /* Retrieves the attribute type description */ const char *info_handle_get_attribute_type_description( uint32_t attribute_type ) { switch( attribute_type ) { case LIBFSNTFS_ATTRIBUTE_TYPE_UNUSED: return( "Unused" ); case LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION: return( "$STANDARD_INFORMATION" ); case LIBFSNTFS_ATTRIBUTE_TYPE_ATTRIBUTE_LIST: return( "$ATTRIBUTE_LIST" ); case LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME: return( "$FILE_NAME" ); case LIBFSNTFS_ATTRIBUTE_TYPE_OBJECT_IDENTIFIER: return( "$OBJECT_ID" ); case LIBFSNTFS_ATTRIBUTE_TYPE_SECURITY_DESCRIPTOR: return( "$SECURITY_DESCRIPTOR" ); case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME: return( "$VOLUME_NAME" ); case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_INFORMATION: return( "$VOLUME_INFORMATION" ); case LIBFSNTFS_ATTRIBUTE_TYPE_DATA: return( "$DATA" ); case LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ROOT: return( "$INDEX_ROOT" ); case LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ALLOCATION: return( "$INDEX_ALLOCATION" ); case LIBFSNTFS_ATTRIBUTE_TYPE_BITMAP: return( "$BITMAP" ); case LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT: return( "$REPARSE_POINT" ); case LIBFSNTFS_ATTRIBUTE_TYPE_EXTENDED_INFORMATION: return( "$EA_INFORMATION" ); case LIBFSNTFS_ATTRIBUTE_TYPE_EXTENDED: return( "$EA" ); case LIBFSNTFS_ATTRIBUTE_TYPE_PROPERTY_SET: return( "$PROPERTY_SET" ); case LIBFSNTFS_ATTRIBUTE_TYPE_LOGGED_UTILITY_STREAM: return( "$LOGGED_UTILITY_STREAM" ); } return( "Unknown" ); } /* Creates an info handle * Make sure the value info_handle is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int info_handle_initialize( info_handle_t **info_handle, uint8_t calculate_md5, libcerror_error_t **error ) { static char *function = "info_handle_initialize"; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( *info_handle != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid info handle value already set.", function ); return( -1 ); } *info_handle = memory_allocate_structure( info_handle_t ); if( *info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create info handle.", function ); goto on_error; } if( memory_set( *info_handle, 0, sizeof( info_handle_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear info handle.", function ); memory_free( *info_handle ); *info_handle = NULL; return( -1 ); } if( libbfio_file_range_initialize( &( ( *info_handle )->input_file_io_handle ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize input file IO handle.", function ); goto on_error; } ( *info_handle )->calculate_md5 = calculate_md5; ( *info_handle )->notify_stream = INFO_HANDLE_NOTIFY_STREAM; return( 1 ); on_error: if( *info_handle != NULL ) { if( ( *info_handle )->input_file_io_handle != NULL ) { libbfio_handle_free( &( ( *info_handle )->input_file_io_handle ), NULL ); } memory_free( *info_handle ); *info_handle = NULL; } return( -1 ); } /* Frees an info handle * Returns 1 if successful or -1 on error */ int info_handle_free( info_handle_t **info_handle, libcerror_error_t **error ) { static char *function = "info_handle_free"; int result = 1; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( *info_handle != NULL ) { if( ( *info_handle )->bodyfile_stream != NULL ) { if( file_stream_close( ( *info_handle )->bodyfile_stream ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close bodyfile stream.", function ); result = -1; } ( *info_handle )->bodyfile_stream = NULL; } if( ( *info_handle )->input_volume != NULL ) { if( libfsntfs_volume_free( &( ( *info_handle )->input_volume ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free input volume.", function ); result = -1; } } if( ( *info_handle )->input_mft_metadata_file != NULL ) { if( libfsntfs_mft_metadata_file_free( &( ( *info_handle )->input_mft_metadata_file ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free input MFT metadata file.", function ); result = -1; } } if( libbfio_handle_free( &( ( *info_handle )->input_file_io_handle ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free input file IO handle.", function ); result = -1; } memory_free( *info_handle ); *info_handle = NULL; } return( result ); } /* Signals the info handle to abort * Returns 1 if successful or -1 on error */ int info_handle_signal_abort( info_handle_t *info_handle, libcerror_error_t **error ) { static char *function = "info_handle_signal_abort"; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } info_handle->abort = 1; if( info_handle->input_volume != NULL ) { if( libfsntfs_volume_signal_abort( info_handle->input_volume, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to signal input volume to abort.", function ); return( -1 ); } } return( 1 ); } /* Sets the bodyfile * Returns 1 if successful or -1 on error */ int info_handle_set_bodyfile( info_handle_t *info_handle, const system_character_t *filename, libcerror_error_t **error ) { static char *function = "info_handle_set_bodyfile"; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( info_handle->bodyfile_stream != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid info handle - bodyfile stream value already set.", function ); return( -1 ); } if( filename == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid filename.", function ); return( -1 ); } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) info_handle->bodyfile_stream = file_stream_open_wide( filename, L"wb" ); #else info_handle->bodyfile_stream = file_stream_open( filename, "wb" ); #endif if( info_handle->bodyfile_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open bodyfile stream.", function ); return( -1 ); } return( 1 ); } /* Sets the volume offset * Returns 1 if successful or -1 on error */ int info_handle_set_volume_offset( info_handle_t *info_handle, const system_character_t *string, libcerror_error_t **error ) { static char *function = "info_handle_set_volume_offset"; size_t string_length = 0; uint64_t value_64bit = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } string_length = system_string_length( string ); if( fsntfstools_system_string_copy_decimal_to_integer_64_bit( string, string_length + 1, &value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy string of decimal to 64-bit integer.", function ); return( -1 ); } info_handle->volume_offset = (off64_t) value_64bit; return( 1 ); } /* Opens the input * Returns 1 if successful or -1 on error */ int info_handle_open_input( info_handle_t *info_handle, const system_character_t *filename, libcerror_error_t **error ) { static char *function = "info_handle_open_input"; size_t filename_length = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } filename_length = system_string_length( filename ); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) if( libbfio_file_range_set_name_wide( info_handle->input_file_io_handle, filename, filename_length, error ) != 1 ) #else if( libbfio_file_range_set_name( info_handle->input_file_io_handle, filename, filename_length, error ) != 1 ) #endif { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set file name.", function ); goto on_error; } if( libbfio_file_range_set( info_handle->input_file_io_handle, info_handle->volume_offset, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set range.", function ); goto on_error; } result = libfsntfs_check_volume_signature_file_io_handle( info_handle->input_file_io_handle, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to check volume signature.", function ); goto on_error; } if( result != 0 ) { if( libfsntfs_volume_initialize( &( info_handle->input_volume ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize input volume.", function ); goto on_error; } if( libfsntfs_volume_open_file_io_handle( info_handle->input_volume, info_handle->input_file_io_handle, LIBFSNTFS_OPEN_READ, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open input volume.", function ); goto on_error; } } else { if( libbfio_file_range_set( info_handle->input_file_io_handle, 0, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set range.", function ); goto on_error; } if( libfsntfs_mft_metadata_file_initialize( &( info_handle->input_mft_metadata_file ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize input MFT metadata file.", function ); goto on_error; } if( libfsntfs_mft_metadata_file_open_file_io_handle( info_handle->input_mft_metadata_file, info_handle->input_file_io_handle, LIBFSNTFS_OPEN_READ, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open input MFT metadata file.", function ); goto on_error; } } return( 1 ); on_error: if( info_handle->input_mft_metadata_file != NULL ) { libfsntfs_mft_metadata_file_free( &( info_handle->input_mft_metadata_file ), NULL ); } if( info_handle->input_volume != NULL ) { libfsntfs_volume_free( &( info_handle->input_volume ), NULL ); } return( -1 ); } /* Closes the input * Returns the 0 if succesful or -1 on error */ int info_handle_close_input( info_handle_t *info_handle, libcerror_error_t **error ) { static char *function = "info_handle_close_input"; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( info_handle->input_volume != NULL ) { if( libfsntfs_volume_close( info_handle->input_volume, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close input volume.", function ); return( -1 ); } } if( info_handle->input_mft_metadata_file != NULL ) { if( libfsntfs_mft_metadata_file_close( info_handle->input_mft_metadata_file, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close input MFT metadata file.", function ); return( -1 ); } } return( 0 ); } /* Calculates the MD5 of the contents of a file entry * Returns 1 if successful or -1 on error */ int info_handle_file_entry_calculate_md5( info_handle_t *info_handle, libfsntfs_file_entry_t *file_entry, char *md5_string, size_t md5_string_size, libcerror_error_t **error ) { uint8_t md5_hash[ LIBHMAC_MD5_HASH_SIZE ]; uint8_t read_buffer[ 4096 ]; libhmac_md5_context_t *md5_context = NULL; static char *function = "info_handle_file_entry_calculate_md5"; size64_t data_size = 0; size_t read_size = 0; ssize_t read_count = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( libfsntfs_file_entry_get_size( file_entry, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size.", function ); goto on_error; } if( libfsntfs_file_entry_seek_offset( file_entry, 0, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek offset: 0 in file entry.", function ); goto on_error; } if( libhmac_md5_initialize( &md5_context, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize MD5 context.", function ); goto on_error; } while( data_size > 0 ) { read_size = 4096; if( (size64_t) read_size > data_size ) { read_size = (size_t) data_size; } read_count = libfsntfs_file_entry_read_buffer( file_entry, read_buffer, read_size, error ); if( read_count != (ssize_t) read_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read from file entry.", function ); goto on_error; } data_size -= read_size; if( libhmac_md5_update( md5_context, read_buffer, read_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to update MD5 hash.", function ); goto on_error; } } if( libhmac_md5_finalize( md5_context, md5_hash, LIBHMAC_MD5_HASH_SIZE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to finalize MD5 hash.", function ); goto on_error; } if( libhmac_md5_free( &md5_context, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free MD5 context.", function ); goto on_error; } if( digest_hash_copy_to_string( md5_hash, LIBHMAC_MD5_HASH_SIZE, md5_string, md5_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set MD5 hash string.", function ); goto on_error; } return( 1 ); on_error: if( md5_context != NULL ) { libhmac_md5_free( &md5_context, NULL ); } return( -1 ); } /* Prints a file entry or data stream name * Returns 1 if successful or -1 on error */ int info_handle_name_value_fprint( info_handle_t *info_handle, const system_character_t *value_string, size_t value_string_length, libcerror_error_t **error ) { system_character_t *escaped_value_string = NULL; static char *function = "info_handle_name_value_fprint"; size_t escaped_value_string_size = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( path_string_copy_from_file_entry_path( &escaped_value_string, &escaped_value_string_size, value_string, value_string_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy path from file entry path.", function ); goto on_error; } if( escaped_value_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing escaped value string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "%" PRIs_SYSTEM "", escaped_value_string ); memory_free( escaped_value_string ); return( 1 ); on_error: if( escaped_value_string != NULL ) { memory_free( escaped_value_string ); } return( -1 ); } /* Prints a FILETIME value * Returns 1 if successful or -1 on error */ int info_handle_filetime_value_fprint( info_handle_t *info_handle, const char *value_name, uint64_t value_64bit, libcerror_error_t **error ) { system_character_t date_time_string[ 48 ]; libfdatetime_filetime_t *filetime = NULL; static char *function = "info_handle_filetime_value_fprint"; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( value_name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid value name.", function ); return( -1 ); } if( value_64bit == 0 ) { fprintf( info_handle->notify_stream, "%s: Not set (0)\n", value_name ); } else { if( libfdatetime_filetime_initialize( &filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create FILETIME.", function ); goto on_error; } if( libfdatetime_filetime_copy_from_64bit( filetime, value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy 64-bit value to FILETIME.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfdatetime_filetime_copy_to_utf16_string( filetime, (uint16_t *) date_time_string, 48, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ); #else result = libfdatetime_filetime_copy_to_utf8_string( filetime, (uint8_t *) date_time_string, 48, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy FILETIME to string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "%s: %" PRIs_SYSTEM " UTC\n", value_name, date_time_string ); if( libfdatetime_filetime_free( &filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free FILETIME.", function ); goto on_error; } } return( 1 ); on_error: if( filetime != NULL ) { libfdatetime_filetime_free( &filetime, NULL ); } return( -1 ); } /* Prints a security descriptor * Returns 1 if successful or -1 on error */ int info_handle_security_descriptor_fprint( info_handle_t *info_handle, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { libfwnt_access_control_entry_t *access_control_entry = NULL; libfwnt_access_control_list_t *access_control_list = NULL; libfwnt_security_descriptor_t *security_descriptor = NULL; libfwnt_security_identifier_t *security_identifier = NULL; system_character_t *value_string = NULL; static char *function = "info_handle_security_descriptor_fprint"; size_t value_string_size = 0; uint32_t access_mask = 0; uint8_t access_control_entry_flags = 0; uint8_t access_control_entry_type = 0; int entry_index = 0; int number_of_entries = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( libfwnt_security_descriptor_initialize( &security_descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create security descriptor.", function ); goto on_error; } if( libfwnt_security_descriptor_copy_from_byte_stream( security_descriptor, data, data_size, LIBFWNT_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy security descriptor from byte stream.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tSecurity descriptor:\n" ); result = libfwnt_security_descriptor_get_owner( security_descriptor, &security_identifier, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve owner SID.", function ); goto on_error; } else if( result != 0 ) { if( libfwnt_security_identifier_get_string_size( security_identifier, &value_string_size, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve owner SID string size.", function ); goto on_error; } if( value_string_size > 0 ) { value_string = system_string_allocate( value_string_size ); if( value_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create owner SID string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfwnt_security_identifier_copy_to_utf16_string( security_identifier, (uint16_t *) value_string, value_string_size, 0, error ); #else result = libfwnt_security_identifier_copy_to_utf8_string( security_identifier, (uint8_t *) value_string, value_string_size, 0, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve owner SID string.", function ); goto on_error; } if( libfwnt_security_identifier_free( &security_identifier, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free owner SID.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\t\tOwner SID\t\t: %" PRIs_SYSTEM "\n", value_string ); memory_free( value_string ); value_string = NULL; } } result = libfwnt_security_descriptor_get_group( security_descriptor, &security_identifier, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve group SID.", function ); goto on_error; } else if( result != 0 ) { if( libfwnt_security_identifier_get_string_size( security_identifier, &value_string_size, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve group SID string size.", function ); goto on_error; } if( value_string_size > 0 ) { value_string = system_string_allocate( value_string_size ); if( value_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create group SID string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfwnt_security_identifier_copy_to_utf16_string( security_identifier, (uint16_t *) value_string, value_string_size, 0, error ); #else result = libfwnt_security_identifier_copy_to_utf8_string( security_identifier, (uint8_t *) value_string, value_string_size, 0, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve group SID string.", function ); goto on_error; } if( libfwnt_security_identifier_free( &security_identifier, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free group SID.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\t\tGroup SID\t\t: %" PRIs_SYSTEM "\n", value_string ); memory_free( value_string ); value_string = NULL; } } result = libfwnt_security_descriptor_get_discretionary_acl( security_descriptor, &access_control_list, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve discretionary access control list (ACL).", function ); goto on_error; } else if( result != 0 ) { fprintf( info_handle->notify_stream, "\t\tDiscretionary ACL:\n" ); if( libfwnt_access_control_list_get_number_of_entries( access_control_list, &number_of_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of discretionary access control entries (ACE).", function ); goto on_error; } for( entry_index = 0; entry_index < number_of_entries; entry_index++ ) { if( libfwnt_access_control_list_get_entry_by_index( access_control_list, entry_index, &access_control_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve discretionary access control entry (ACE): %d.", function, entry_index ); goto on_error; } /* TODO print ACE */ if( libfwnt_access_control_entry_free( &access_control_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free discretionary access control entry (ACE): %d.", function, entry_index ); goto on_error; } } if( libfwnt_access_control_list_free( &access_control_list, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free discretionary access control list.", function ); goto on_error; } } result = libfwnt_security_descriptor_get_system_acl( security_descriptor, &access_control_list, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve system access control list (ACL).", function ); goto on_error; } else if( result != 0 ) { fprintf( info_handle->notify_stream, "\t\tSystem ACL:\n" ); if( libfwnt_access_control_list_get_number_of_entries( access_control_list, &number_of_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of system access control entries (ACE).", function ); goto on_error; } for( entry_index = 0; entry_index < number_of_entries; entry_index++ ) { if( libfwnt_access_control_list_get_entry_by_index( access_control_list, entry_index, &access_control_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve system access control entry (ACE): %d.", function, entry_index ); goto on_error; } if( libfwnt_access_control_entry_get_type( access_control_entry, &access_control_entry_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve system access control entry (ACE): %d type.", function, entry_index ); goto on_error; } if( libfwnt_access_control_entry_get_flags( access_control_entry, &access_control_entry_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve system access control entry (ACE): %d flags.", function, entry_index ); goto on_error; } result = libfwnt_access_control_entry_get_access_mask( access_control_entry, &access_mask, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve access mask.", function ); goto on_error; } /* TODO ignore ACE without access mask? */ result = libfwnt_access_control_entry_get_security_identifier( access_control_entry, &security_identifier, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security identifier.", function ); goto on_error; } else if( result != 0 ) { if( libfwnt_security_identifier_get_string_size( security_identifier, &value_string_size, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security identifier string size.", function ); goto on_error; } if( value_string_size > 0 ) { value_string = system_string_allocate( value_string_size ); if( value_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create security identifier string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfwnt_security_identifier_copy_to_utf16_string( security_identifier, (uint16_t *) value_string, value_string_size, 0, error ); #else result = libfwnt_security_identifier_copy_to_utf8_string( security_identifier, (uint8_t *) value_string, value_string_size, 0, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security identifier string.", function ); goto on_error; } if( libfwnt_security_identifier_free( &security_identifier, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free security identifier.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\t\t\t%s, flags: 0x%" PRIx8 ", access mask: 0x%04" PRIx32 ", SID: %" PRIs_SYSTEM "\n", info_handle_get_access_control_entry_type( access_control_entry_type ), access_control_entry_flags, access_mask, value_string ); memory_free( value_string ); value_string = NULL; } } if( libfwnt_access_control_entry_free( &access_control_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free system access control entry (ACE): %d.", function, entry_index ); goto on_error; } } if( libfwnt_access_control_list_free( &access_control_list, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free system access control list.", function ); goto on_error; } } if( libfwnt_security_descriptor_free( &security_descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free security descriptor.", function ); goto on_error; } return( 1 ); on_error: if( value_string != NULL ) { memory_free( value_string ); } if( access_control_entry != NULL ) { libfwnt_access_control_entry_free( &access_control_entry, NULL ); } if( access_control_list != NULL ) { libfwnt_access_control_list_free( &access_control_list, NULL ); } if( security_identifier != NULL ) { libfwnt_security_identifier_free( &security_identifier, NULL ); } if( security_descriptor != NULL ) { libfwnt_security_descriptor_free( &security_descriptor, NULL ); } return( -1 ); } /* Prints attribute information * Returns 1 if successful or -1 on error */ int info_handle_attribute_fprint( info_handle_t *info_handle, libfsntfs_file_entry_t *file_entry, libfsntfs_attribute_t *attribute, int attribute_index, libcerror_error_t **error ) { system_character_t *value_string = NULL; static char *function = "info_handle_attribute_fprint"; size_t value_string_size = 0; uint32_t attribute_type = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } fprintf( info_handle->notify_stream, "Attribute: %d\n", attribute_index + 1 ); if( libfsntfs_attribute_get_type( attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tAttribute type\t\t\t: %s (0x%08" PRIx32 ")\n", info_handle_get_attribute_type_description( attribute_type ), attribute_type ); switch( attribute_type ) { case LIBFSNTFS_ATTRIBUTE_TYPE_BITMAP: case LIBFSNTFS_ATTRIBUTE_TYPE_DATA: case LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME: case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME: break; default: #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_attribute_get_utf16_name_size( attribute, &value_string_size, error ); #else result = libfsntfs_attribute_get_utf8_name_size( attribute, &value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name string size.", function ); goto on_error; } if( value_string_size > 0 ) { value_string = system_string_allocate( value_string_size ); if( value_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create name string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_attribute_get_utf16_name( attribute, (uint16_t *) value_string, value_string_size, error ); #else result = libfsntfs_attribute_get_utf8_name( attribute, (uint8_t *) value_string, value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tAttribute name\t\t\t: " ); if( info_handle_name_value_fprint( info_handle, value_string, value_string_size - 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print attribute name string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\n" ); memory_free( value_string ); value_string = NULL; } break; } switch( attribute_type ) { case LIBFSNTFS_ATTRIBUTE_TYPE_ATTRIBUTE_LIST: if( info_handle_attribute_list_attribute_fprint( info_handle, attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print attribute list attribute: %d information.", function, attribute_index ); goto on_error; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_BITMAP: if( info_handle_bitmap_attribute_fprint( info_handle, attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print bitmap attribute: %d information.", function, attribute_index ); goto on_error; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_DATA: if( info_handle_data_attribute_fprint( info_handle, attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print data attribute: %d information.", function, attribute_index ); goto on_error; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME: if( info_handle_file_name_attribute_fprint( info_handle, attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print file name attribute: %d information.", function, attribute_index ); goto on_error; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ROOT: break; case LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ALLOCATION: break; case LIBFSNTFS_ATTRIBUTE_TYPE_LOGGED_UTILITY_STREAM: break; case LIBFSNTFS_ATTRIBUTE_TYPE_OBJECT_IDENTIFIER: if( info_handle_object_identifier_attribute_fprint( info_handle, attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print object identifier attribute: %d information.", function, attribute_index ); goto on_error; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT: if( info_handle_reparse_point_attribute_fprint( info_handle, attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print reparse point attribute: %d information.", function, attribute_index ); goto on_error; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_SECURITY_DESCRIPTOR: if( info_handle_security_descriptor_attribute_fprint( info_handle, attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print security descriptor attribute: %d information.", function, attribute_index ); goto on_error; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION: if( info_handle_standard_information_attribute_fprint( info_handle, attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print standard information attribute: %d information.", function, attribute_index ); goto on_error; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_INFORMATION: if( info_handle_volume_information_attribute_fprint( info_handle, attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print volume information attribute: %d information.", function, attribute_index ); goto on_error; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME: if( info_handle_volume_name_attribute_fprint( info_handle, attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print volume name attribute: %d information.", function, attribute_index ); goto on_error; } break; default: break; } if( ( info_handle->input_mft_metadata_file != NULL ) && ( attribute_type == LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ) ) { fprintf( info_handle->notify_stream, "\tPath hint\t\t: " ); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_file_entry_get_utf16_path_hint_size( file_entry, attribute_index, &value_string_size, error ); #else result = libfsntfs_file_entry_get_utf8_path_hint_size( file_entry, attribute_index, &value_string_size, error ); #endif if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve path hint string size.", function ); goto on_error; } if( ( result != 0 ) && ( value_string_size > 0 ) ) { value_string = system_string_allocate( value_string_size ); if( value_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create path hint string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_file_entry_get_utf16_path_hint( file_entry, attribute_index, (uint16_t *) value_string, value_string_size, error ); #else result = libfsntfs_file_entry_get_utf8_path_hint( file_entry, attribute_index, (uint8_t *) value_string, value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve path hint string.", function ); goto on_error; } if( info_handle_name_value_fprint( info_handle, value_string, value_string_size - 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print name string.", function ); goto on_error; } memory_free( value_string ); value_string = NULL; } fprintf( info_handle->notify_stream, "\n" ); } fprintf( info_handle->notify_stream, "\n" ); return( 1 ); on_error: if( value_string != NULL ) { memory_free( value_string ); } return( -1 ); } /* Prints $ATTRIBUTE_LIST attribute information * Returns 1 if successful or -1 on error */ int info_handle_attribute_list_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ) { libfsntfs_attribute_list_entry_t *attribute_list_entry = NULL; system_character_t *value_string = NULL; static char *function = "info_handle_attribute_list_attribute_fprint"; size64_t data_size = 0; size_t value_string_size = 0; uint64_t data_first_vcn = 0; uint64_t data_last_vcn = 0; uint64_t file_reference = 0; uint32_t attribute_type = 0; int entry_index = 0; int number_of_entries = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } result = libfsntfs_attribute_get_data_vcn_range( attribute, &data_first_vcn, &data_last_vcn, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data VCN range.", function ); return( -1 ); } else if( result != 0 ) { if( ( data_first_vcn == data_last_vcn ) || ( data_last_vcn == 0xffffffffffffffffUL ) ) { fprintf( info_handle->notify_stream, "\tData VCN\t\t\t: %" PRIu64 "\n", data_first_vcn ); } else { fprintf( info_handle->notify_stream, "\tData VCN range\t\t\t: %" PRIu64 " - %" PRIu64 "\n", data_first_vcn, data_last_vcn ); } } if( data_first_vcn == 0 ) { if( libfsntfs_attribute_get_data_size( attribute, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data size.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tData size\t\t\t: %" PRIu64 " bytes\n", data_size ); } if( libfsntfs_attribute_list_attribute_get_number_of_entries( attribute, &number_of_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of attribute list entries.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tNumber of entries\t\t: %d\n", number_of_entries ); for( entry_index = 0; entry_index < number_of_entries; entry_index++ ) { if( libfsntfs_attribute_list_attribute_get_entry_by_index( attribute, entry_index, &attribute_list_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute list entry: %d.", function, entry_index ); goto on_error; } if( libfsntfs_attribute_list_entry_get_attribute_type( attribute_list_entry, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); goto on_error; } if( libfsntfs_attribute_list_entry_get_file_reference( attribute_list_entry, &file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file reference.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_attribute_list_entry_get_utf16_name_size( attribute_list_entry, &value_string_size, error ); #else result = libfsntfs_attribute_list_entry_get_utf8_name_size( attribute_list_entry, &value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name string size.", function ); goto on_error; } if( value_string_size > 0 ) { value_string = system_string_allocate( value_string_size ); if( value_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create name string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_attribute_list_entry_get_utf16_name( attribute_list_entry, (uint16_t *) value_string, value_string_size, error ); #else result = libfsntfs_attribute_list_entry_get_utf8_name( attribute_list_entry, (uint8_t *) value_string, value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name string.", function ); goto on_error; } } fprintf( info_handle->notify_stream, "\tEntry: %d\t\t\t: %s (0x%08" PRIx32 ")", entry_index, info_handle_get_attribute_type_description( attribute_type ), attribute_type ); if( value_string != NULL ) { fprintf( info_handle->notify_stream, " " ); if( info_handle_name_value_fprint( info_handle, value_string, value_string_size - 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print name string.", function ); goto on_error; } memory_free( value_string ); value_string = NULL; } fprintf( info_handle->notify_stream, " in file reference: %" PRIu64 "-%" PRIu64 "\n", file_reference & 0xffffffffffffUL, file_reference >> 48 ); if( libfsntfs_attribute_list_entry_free( &attribute_list_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free attribute list entry: %d.", function, entry_index ); goto on_error; } } return( 1 ); on_error: if( value_string != NULL ) { memory_free( value_string ); } if( attribute_list_entry != NULL ) { libfsntfs_attribute_list_entry_free( &attribute_list_entry, NULL ); } return( -1 ); } /* Prints $BITMAP attribute information * Returns 1 if successful or -1 on error */ int info_handle_bitmap_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ) { system_character_t *value_string = NULL; static char *function = "info_handle_bitmap_attribute_fprint"; size64_t data_size = 0; size_t value_string_size = 0; uint64_t data_first_vcn = 0; uint64_t data_last_vcn = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } result = libfsntfs_attribute_get_data_vcn_range( attribute, &data_first_vcn, &data_last_vcn, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data VCN range.", function ); return( -1 ); } else if( result != 0 ) { if( ( data_first_vcn == data_last_vcn ) || ( data_last_vcn == 0xffffffffffffffffUL ) ) { fprintf( info_handle->notify_stream, "\tData VCN\t\t\t: %" PRIu64 "\n", data_first_vcn ); } else { fprintf( info_handle->notify_stream, "\tData VCN range\t\t\t: %" PRIu64 " - %" PRIu64 "\n", data_first_vcn, data_last_vcn ); } } if( data_first_vcn == 0 ) { if( libfsntfs_attribute_get_data_size( attribute, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data size.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tData size\t\t\t: %" PRIu64 " bytes\n", data_size ); } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_attribute_get_utf16_name_size( attribute, &value_string_size, error ); #else result = libfsntfs_attribute_get_utf8_name_size( attribute, &value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name string size.", function ); goto on_error; } if( value_string_size > 0 ) { value_string = system_string_allocate( value_string_size ); if( value_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create name string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_attribute_get_utf16_name( attribute, (uint16_t *) value_string, value_string_size, error ); #else result = libfsntfs_attribute_get_utf8_name( attribute, (uint8_t *) value_string, value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tAttribute name\t\t\t: " ); if( info_handle_name_value_fprint( info_handle, value_string, value_string_size - 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print name string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\n" ); memory_free( value_string ); value_string = NULL; } return( 1 ); on_error: if( value_string != NULL ) { memory_free( value_string ); } return( -1 ); } /* Prints $DATA attribute information * Returns 1 if successful or -1 on error */ int info_handle_data_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ) { system_character_t *value_string = NULL; static char *function = "info_handle_data_attribute_fprint"; size64_t data_size = 0; size_t value_string_size = 0; uint64_t data_first_vcn = 0; uint64_t data_last_vcn = 0; uint16_t data_flags = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } result = libfsntfs_attribute_get_data_vcn_range( attribute, &data_first_vcn, &data_last_vcn, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data VCN range.", function ); return( -1 ); } else if( result != 0 ) { if( ( data_first_vcn == data_last_vcn ) || ( data_last_vcn == 0xffffffffffffffffUL ) ) { fprintf( info_handle->notify_stream, "\tData VCN\t\t\t: %" PRIu64 "\n", data_first_vcn ); } else { fprintf( info_handle->notify_stream, "\tData VCN range\t\t\t: %" PRIu64 " - %" PRIu64 "\n", data_first_vcn, data_last_vcn ); } } if( data_first_vcn == 0 ) { if( libfsntfs_attribute_get_data_size( attribute, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data size.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tData size\t\t\t: %" PRIu64 " bytes\n", data_size ); } if( libfsntfs_attribute_get_data_flags( attribute, &data_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data flags.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tData flags\t\t\t: 0x%04" PRIx16 "\n", data_flags ); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_attribute_get_utf16_name_size( attribute, &value_string_size, error ); #else result = libfsntfs_attribute_get_utf8_name_size( attribute, &value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name string size.", function ); goto on_error; } if( value_string_size > 0 ) { value_string = system_string_allocate( value_string_size ); if( value_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create name string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_attribute_get_utf16_name( attribute, (uint16_t *) value_string, value_string_size, error ); #else result = libfsntfs_attribute_get_utf8_name( attribute, (uint8_t *) value_string, value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tName\t\t\t\t: " ); if( info_handle_name_value_fprint( info_handle, value_string, value_string_size - 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print name string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\n" ); memory_free( value_string ); value_string = NULL; } return( 1 ); on_error: if( value_string != NULL ) { memory_free( value_string ); } return( -1 ); } /* Prints $FILE_NAME attribute information * Returns 1 if successful or -1 on error */ int info_handle_file_name_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ) { system_character_t *value_string = NULL; static char *function = "info_handle_file_name_attribute_fprint"; size_t value_string_size = 0; uint64_t value_64bit = 0; uint32_t value_32bit = 0; uint8_t value_8bit = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( libfsntfs_file_name_attribute_get_parent_file_reference( attribute, &value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve parent file reference.", function ); goto on_error; } if( value_64bit == 0 ) { fprintf( info_handle->notify_stream, "\tParent file reference\t\t: %" PRIu64 "\n", value_64bit ); } else { fprintf( info_handle->notify_stream, "\tParent file reference\t\t: %" PRIu64 "-%" PRIu64 "\n", value_64bit & 0xffffffffffffUL, value_64bit >> 48 ); } if( libfsntfs_file_name_attribute_get_creation_time( attribute, &value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve creation time.", function ); goto on_error; } if( info_handle_filetime_value_fprint( info_handle, "\tCreation time\t\t\t", value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print FILETIME value.", function ); goto on_error; } if( libfsntfs_file_name_attribute_get_modification_time( attribute, &value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve modification time.", function ); goto on_error; } if( info_handle_filetime_value_fprint( info_handle, "\tModification time\t\t", value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print FILETIME value.", function ); goto on_error; } if( libfsntfs_file_name_attribute_get_access_time( attribute, &value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve access time.", function ); goto on_error; } if( info_handle_filetime_value_fprint( info_handle, "\tAccess time\t\t\t", value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print FILETIME value.", function ); goto on_error; } if( libfsntfs_file_name_attribute_get_entry_modification_time( attribute, &value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry modification time.", function ); goto on_error; } if( info_handle_filetime_value_fprint( info_handle, "\tEntry modification time\t\t", value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print FILETIME value.", function ); goto on_error; } if( libfsntfs_file_name_attribute_get_file_attribute_flags( attribute, &value_32bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file attribute flags.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tFile attribute flags\t\t: 0x%08" PRIx32 "\n", value_32bit ); info_handle_file_attribute_flags_fprint( value_32bit, info_handle->notify_stream ); if( libfsntfs_file_name_attribute_get_name_space( attribute, &value_8bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name space.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tName space\t\t\t: " ); switch( value_8bit ) { case 0: fprintf( info_handle->notify_stream, "POSIX (%" PRIu8 ")", value_8bit ); break; case 1: fprintf( info_handle->notify_stream, "Windows (%" PRIu8 ")", value_8bit ); break; case 2: fprintf( info_handle->notify_stream, "DOS (%" PRIu8 ")", value_8bit ); break; case 3: fprintf( info_handle->notify_stream, "DOS and Windows (%" PRIu8 ")", value_8bit ); break; default: fprintf( info_handle->notify_stream, "%" PRIu8 "", value_8bit ); break; } fprintf( info_handle->notify_stream, "\n" ); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_file_name_attribute_get_utf16_name_size( attribute, &value_string_size, error ); #else result = libfsntfs_file_name_attribute_get_utf8_name_size( attribute, &value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name string size.", function ); goto on_error; } if( value_string_size > 0 ) { value_string = system_string_allocate( value_string_size ); if( value_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create name string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_file_name_attribute_get_utf16_name( attribute, (uint16_t *) value_string, value_string_size, error ); #else result = libfsntfs_file_name_attribute_get_utf8_name( attribute, (uint8_t *) value_string, value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tName\t\t\t\t: " ); if( info_handle_name_value_fprint( info_handle, value_string, value_string_size - 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print name string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\n" ); memory_free( value_string ); value_string = NULL; } return( 1 ); on_error: if( value_string != NULL ) { memory_free( value_string ); } return( -1 ); } /* Prints $OBJECT_ID attribute information * Returns 1 if successful or -1 on error */ int info_handle_object_identifier_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ) { uint8_t guid_data[ 16 ]; system_character_t guid_string[ 48 ]; libfguid_identifier_t *guid = NULL; static char *function = "info_handle_object_identifier_attribute_fprint"; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( libfguid_identifier_initialize( &guid, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create GUID.", function ); goto on_error; } if( libfsntfs_object_identifier_attribute_get_droid_file_identifier( attribute, guid_data, 16, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve droid file identifier.", function ); goto on_error; } if( libfguid_identifier_copy_from_byte_stream( guid, guid_data, 16, LIBFGUID_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy byte stream to GUID.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfguid_identifier_copy_to_utf16_string( guid, (uint16_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #else result = libfguid_identifier_copy_to_utf8_string( guid, (uint8_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy GUID to string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tDroid file identifier\t\t: %" PRIs_SYSTEM "\n", guid_string ); result = libfsntfs_object_identifier_attribute_get_birth_droid_volume_identifier( attribute, guid_data, 16, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve birth droid volume identifier.", function ); goto on_error; } else if( result != 0 ) { if( libfguid_identifier_copy_from_byte_stream( guid, guid_data, 16, LIBFGUID_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy byte stream to GUID.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfguid_identifier_copy_to_utf16_string( guid, (uint16_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #else result = libfguid_identifier_copy_to_utf8_string( guid, (uint8_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy GUID to string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tBirth droid volume identifier\t: %" PRIs_SYSTEM "\n", guid_string ); } result = libfsntfs_object_identifier_attribute_get_birth_droid_file_identifier( attribute, guid_data, 16, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve birth droid file identifier.", function ); goto on_error; } else if( result != 0 ) { if( libfguid_identifier_copy_from_byte_stream( guid, guid_data, 16, LIBFGUID_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy byte stream to GUID.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfguid_identifier_copy_to_utf16_string( guid, (uint16_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #else result = libfguid_identifier_copy_to_utf8_string( guid, (uint8_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy GUID to string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tBirth droid file identifier\t: %" PRIs_SYSTEM "\n", guid_string ); } result = libfsntfs_object_identifier_attribute_get_birth_droid_domain_identifier( attribute, guid_data, 16, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve birth droid domain identifier.", function ); goto on_error; } else if( result != 0 ) { if( libfguid_identifier_copy_from_byte_stream( guid, guid_data, 16, LIBFGUID_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy byte stream to GUID.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfguid_identifier_copy_to_utf16_string( guid, (uint16_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #else result = libfguid_identifier_copy_to_utf8_string( guid, (uint8_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy GUID to string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tBirth droid domain identifier\t: %" PRIs_SYSTEM "\n", guid_string ); } if( libfguid_identifier_free( &guid, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free GUID.", function ); goto on_error; } return( 1 ); on_error: if( guid != NULL ) { libfguid_identifier_free( &guid, NULL ); } return( -1 ); } /* Prints $REPARSE_POINT attribute information * Returns 1 if successful or -1 on error */ int info_handle_reparse_point_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ) { system_character_t *value_string = NULL; static char *function = "info_handle_reparse_point_attribute_fprint"; size_t value_string_size = 0; uint32_t value_32bit = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( libfsntfs_reparse_point_attribute_get_tag( attribute, &value_32bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve tag.", function ); return( -1 ); } fprintf( info_handle->notify_stream, "\tTag\t\t\t\t: 0x%08" PRIx32 "\n", value_32bit ); result = libfsntfs_reparse_point_attribute_get_compression_method( attribute, &value_32bit, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve compression method.", function ); goto on_error; } else if( result != 0 ) { fprintf( info_handle->notify_stream, "\tCompression method\t\t: " ); switch( value_32bit ) { case 0: fprintf( info_handle->notify_stream, "XPRESS4K (%" PRIu32 ")", value_32bit ); break; case 1: fprintf( info_handle->notify_stream, "LZX (%" PRIu32 ")", value_32bit ); break; case 2: fprintf( info_handle->notify_stream, "XPRESS8K (%" PRIu32 ")", value_32bit ); break; case 3: fprintf( info_handle->notify_stream, "XPRESS16K (%" PRIu32 ")", value_32bit ); break; default: fprintf( info_handle->notify_stream, "%" PRIu32 "", value_32bit ); break; } fprintf( info_handle->notify_stream, "\n" ); } /* TODO sanitize substitute name ? */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_reparse_point_attribute_get_utf16_substitute_name_size( attribute, &value_string_size, error ); #else result = libfsntfs_reparse_point_attribute_get_utf8_substitute_name_size( attribute, &value_string_size, error ); #endif if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve substitute name string size.", function ); goto on_error; } if( ( result != 0 ) && ( value_string_size > 0 ) ) { value_string = system_string_allocate( value_string_size ); if( value_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create substitute name string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_reparse_point_attribute_get_utf16_substitute_name( attribute, (uint16_t *) value_string, value_string_size, error ); #else result = libfsntfs_reparse_point_attribute_get_utf8_substitute_name( attribute, (uint8_t *) value_string, value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve substitute name string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tSubstitute name\t\t\t: %" PRIs_SYSTEM "\n", value_string ); memory_free( value_string ); value_string = NULL; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_reparse_point_attribute_get_utf16_print_name_size( attribute, &value_string_size, error ); #else result = libfsntfs_reparse_point_attribute_get_utf8_print_name_size( attribute, &value_string_size, error ); #endif if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve print name string size.", function ); goto on_error; } if( ( result != 0 ) && ( value_string_size > 0 ) ) { value_string = system_string_allocate( value_string_size ); if( value_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create print name string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_reparse_point_attribute_get_utf16_print_name( attribute, (uint16_t *) value_string, value_string_size, error ); #else result = libfsntfs_reparse_point_attribute_get_utf8_print_name( attribute, (uint8_t *) value_string, value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve print name string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tPrint name\t\t\t: %" PRIs_SYSTEM "\n", value_string ); memory_free( value_string ); value_string = NULL; } return( 1 ); on_error: if( value_string != NULL ) { memory_free( value_string ); } return( -1 ); } /* Prints $SECURITY_DESCRIPTOR attribute information * Returns 1 if successful or -1 on error */ int info_handle_security_descriptor_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ) { static char *function = "info_handle_security_descriptor_attribute_fprint"; uint8_t *data = NULL; size_t data_size = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } result = libfsntfs_security_descriptor_attribute_get_security_descriptor_size( attribute, &data_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security descriptor size.", function ); goto on_error; } else if( result != 0 ) { data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * data_size ); if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create data.", function ); goto on_error; } if( libfsntfs_security_descriptor_attribute_get_security_descriptor( attribute, data, data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security descriptor.", function ); goto on_error; } if( info_handle_security_descriptor_fprint( info_handle, data, data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print security descriptor.", function ); goto on_error; } memory_free( data ); data = NULL; } return( 1 ); on_error: if( data != NULL ) { memory_free( data ); } return( -1 ); } /* Prints $STANDARD_INFORMATION attribute information * Returns 1 if successful or -1 on error */ int info_handle_standard_information_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ) { static char *function = "info_handle_standard_information_attribute_fprint"; uint64_t value_64bit = 0; uint32_t value_32bit = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( libfsntfs_standard_information_attribute_get_creation_time( attribute, &value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve creation time.", function ); return( -1 ); } if( info_handle_filetime_value_fprint( info_handle, "\tCreation time\t\t\t", value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print FILETIME value.", function ); return( -1 ); } if( libfsntfs_standard_information_attribute_get_modification_time( attribute, &value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve modification time.", function ); return( -1 ); } if( info_handle_filetime_value_fprint( info_handle, "\tModification time\t\t", value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print FILETIME value.", function ); return( -1 ); } if( libfsntfs_standard_information_attribute_get_access_time( attribute, &value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve access time.", function ); return( -1 ); } if( info_handle_filetime_value_fprint( info_handle, "\tAccess time\t\t\t", value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print FILETIME value.", function ); return( -1 ); } if( libfsntfs_standard_information_attribute_get_entry_modification_time( attribute, &value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry modification time.", function ); return( -1 ); } if( info_handle_filetime_value_fprint( info_handle, "\tEntry modification time\t\t", value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print FILETIME value.", function ); return( -1 ); } result = libfsntfs_standard_information_attribute_get_owner_identifier( attribute, &value_32bit, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve owner identifier.", function ); return( -1 ); } else if( result != 0 ) { fprintf( info_handle->notify_stream, "\tOwner identifier\t\t: %" PRIu32 "\n", value_32bit ); } result = libfsntfs_standard_information_attribute_get_security_descriptor_identifier( attribute, &value_32bit, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security descriptor identifier.", function ); return( -1 ); } else if( result != 0 ) { fprintf( info_handle->notify_stream, "\tSecurity descriptor identifier\t: %" PRIu32 "\n", value_32bit ); } result = libfsntfs_standard_information_attribute_get_update_sequence_number( attribute, &value_64bit, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve update sequence number.", function ); return( -1 ); } else if( result != 0 ) { fprintf( info_handle->notify_stream, "\tUpdate sequence number\t\t: %" PRIu64 "\n", value_64bit ); } if( libfsntfs_standard_information_attribute_get_file_attribute_flags( attribute, &value_32bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file attribute flags.", function ); return( -1 ); } fprintf( info_handle->notify_stream, "\tFile attribute flags\t\t: 0x%08" PRIx32 "\n", value_32bit ); info_handle_file_attribute_flags_fprint( value_32bit, info_handle->notify_stream ); return( 1 ); } /* Prints $VOLUME_INFORMATION attribute information * Returns 1 if successful or -1 on error */ int info_handle_volume_information_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ) { static char *function = "info_handle_volume_information_attribute_fprint"; uint16_t value_16bit = 0; uint8_t major_version = 0; uint8_t minor_version = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( libfsntfs_volume_information_attribute_get_version( attribute, &major_version, &minor_version, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve version.", function ); return( -1 ); } fprintf( info_handle->notify_stream, "\tVersion\t\t\t\t: %" PRIu8 ".%" PRIu8 "\n", major_version, minor_version ); if( libfsntfs_volume_information_attribute_get_flags( attribute, &value_16bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve flags.", function ); return( -1 ); } fprintf( info_handle->notify_stream, "\tFlags\t\t\t\t: 0x%04" PRIx16 "\n", value_16bit ); info_handle_volume_information_flags_fprint( value_16bit, info_handle->notify_stream ); return( 1 ); } /* Prints $VOLUME_NAME attribute information * Returns 1 if successful or -1 on error */ int info_handle_volume_name_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ) { system_character_t *value_string = NULL; static char *function = "info_handle_volume_name_attribute_fprint"; size_t value_string_size = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_volume_name_attribute_get_utf16_name_size( attribute, &value_string_size, error ); #else result = libfsntfs_volume_name_attribute_get_utf8_name_size( attribute, &value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name string size.", function ); goto on_error; } if( value_string_size > 0 ) { value_string = system_string_allocate( value_string_size ); if( value_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create name string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_volume_name_attribute_get_utf16_name( attribute, (uint16_t *) value_string, value_string_size, error ); #else result = libfsntfs_volume_name_attribute_get_utf8_name( attribute, (uint8_t *) value_string, value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tName\t\t\t\t: " ); if( info_handle_name_value_fprint( info_handle, value_string, value_string_size - 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print name string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\n" ); memory_free( value_string ); value_string = NULL; } return( 1 ); on_error: if( value_string != NULL ) { memory_free( value_string ); } return( -1 ); } /* Prints a file entry value * Returns 1 if successful, 0 if not or -1 on error */ int info_handle_file_entry_value_fprint( info_handle_t *info_handle, libfsntfs_file_entry_t *file_entry, libcerror_error_t **error ) { system_character_t *file_entry_name = NULL; uint8_t *security_descriptor_data = NULL; static char *function = "info_handle_file_entry_value_fprint"; size64_t size = 0; size_t file_entry_name_size = 0; uint64_t access_time = 0; uint64_t creation_time = 0; uint64_t entry_modification_time = 0; uint64_t file_reference = 0; uint64_t modification_time = 0; uint64_t parent_file_reference = 0; uint32_t file_attribute_flags = 0; int result = 0; #ifdef TODO size_t security_descriptor_data_size = 0; #endif if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( libfsntfs_file_entry_get_file_reference( file_entry, &file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file reference.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tFile reference\t\t\t: %" PRIu64 "-%" PRIu64 "\n", file_reference & 0xffffffffffffUL, file_reference >> 48 ); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_file_entry_get_utf16_name_size( file_entry, &file_entry_name_size, error ); #else result = libfsntfs_file_entry_get_utf8_name_size( file_entry, &file_entry_name_size, error ); #endif if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry name string size.", function ); goto on_error; } if( ( result == 1 ) && ( file_entry_name_size > 0 ) ) { file_entry_name = system_string_allocate( file_entry_name_size ); if( file_entry_name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create file entry name string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_file_entry_get_utf16_name( file_entry, (uint16_t *) file_entry_name, file_entry_name_size, error ); #else result = libfsntfs_file_entry_get_utf8_name( file_entry, (uint8_t *) file_entry_name, file_entry_name_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry name string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tName\t\t\t\t: " ); if( info_handle_name_value_fprint( info_handle, file_entry_name, file_entry_name_size - 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print file entry name string.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\n" ); } result = libfsntfs_file_entry_get_parent_file_reference( file_entry, &parent_file_reference, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve parent file reference.", function ); goto on_error; } else if( result != 0 ) { fprintf( info_handle->notify_stream, "\tParent file reference\t\t: " ); if( parent_file_reference == 0 ) { fprintf( info_handle->notify_stream, "Not set (0)" ); } else { fprintf( info_handle->notify_stream, "%" PRIu64 "-%" PRIu64 "", parent_file_reference & 0xffffffffffffUL, parent_file_reference >> 48 ); } fprintf( info_handle->notify_stream, "\n" ); } if( libfsntfs_file_entry_get_size( file_entry, &size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tSize\t\t\t\t: %" PRIu64 "\n", size ); result = libfsntfs_file_entry_get_creation_time( file_entry, &creation_time, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve creation time.", function ); goto on_error; } else if( result != 0 ) { if( info_handle_filetime_value_fprint( info_handle, "\tCreation time\t\t\t", creation_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print FILETIME value.", function ); goto on_error; } } result = libfsntfs_file_entry_get_modification_time( file_entry, &modification_time, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve modification time.", function ); goto on_error; } else if( result != 0 ) { if( info_handle_filetime_value_fprint( info_handle, "\tModification time\t\t", modification_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print FILETIME value.", function ); goto on_error; } } result = libfsntfs_file_entry_get_access_time( file_entry, &access_time, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve access time.", function ); goto on_error; } else if( result != 0 ) { if( info_handle_filetime_value_fprint( info_handle, "\tAccess time\t\t\t", access_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print FILETIME value.", function ); goto on_error; } } result = libfsntfs_file_entry_get_entry_modification_time( file_entry, &entry_modification_time, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry modification time.", function ); goto on_error; } else if( result != 0 ) { if( info_handle_filetime_value_fprint( info_handle, "\tEntry modification time\t\t", entry_modification_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print FILETIME value.", function ); goto on_error; } } result = libfsntfs_file_entry_get_file_attribute_flags( file_entry, &file_attribute_flags, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file attribute flags.", function ); goto on_error; } else if( result != 0 ) { fprintf( info_handle->notify_stream, "\tFile attribute flags\t\t: 0x%08" PRIx32 "\n", file_attribute_flags ); info_handle_file_attribute_flags_fprint( file_attribute_flags, info_handle->notify_stream ); } #ifdef TODO result = libfsntfs_file_entry_get_security_descriptor_size( file_entry, &security_descriptor_data_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security descriptor size.", function ); goto on_error; } else if( result != 0 ) { security_descriptor_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * security_descriptor_data_size ); if( security_descriptor_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create security descriptor data.", function ); goto on_error; } if( libfsntfs_file_entry_get_security_descriptor( file_entry, security_descriptor_data, security_descriptor_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security descriptor.", function ); goto on_error; } if( info_handle_security_descriptor_fprint( info_handle, security_descriptor_data, security_descriptor_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print security descriptor.", function ); goto on_error; } memory_free( security_descriptor_data ); security_descriptor_data = NULL; } #endif /* TODO print attributes + ADS ? */ if( file_entry_name != NULL ) { memory_free( file_entry_name ); file_entry_name = NULL; } return( 1 ); on_error: if( security_descriptor_data != NULL ) { memory_free( security_descriptor_data ); } if( file_entry_name != NULL ) { memory_free( file_entry_name ); } return( -1 ); } /* Prints a file entry or data stream name to a bodyfile * Returns 1 if successful or -1 on error */ int info_handle_bodyfile_name_value_fprint( info_handle_t *info_handle, const system_character_t *value_string, size_t value_string_length, libcerror_error_t **error ) { system_character_t *escaped_value_string = NULL; static char *function = "info_handle_bodyfile_name_value_fprint"; size_t escaped_value_string_size = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( bodyfile_path_string_copy_from_file_entry_path( &escaped_value_string, &escaped_value_string_size, value_string, value_string_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy path from file entry path.", function ); goto on_error; } if( escaped_value_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing escaped value string.", function ); goto on_error; } fprintf( info_handle->bodyfile_stream, "%" PRIs_SYSTEM "", escaped_value_string ); memory_free( escaped_value_string ); return( 1 ); on_error: if( escaped_value_string != NULL ) { memory_free( escaped_value_string ); } return( -1 ); } /* Prints a $FILE_NAME attribute to a bodyfile * Returns 1 if successful or -1 on error */ int info_handle_bodyfile_file_name_attribute_fprint( info_handle_t *info_handle, libfsntfs_file_entry_t *file_entry, libfsntfs_attribute_t *attribute, const system_character_t *path, size_t path_length, const system_character_t *file_entry_name, size_t file_entry_name_length, libcerror_error_t **error ) { char file_mode_string[ 11 ] = { '-', 'r', 'w', 'x', 'r', 'w', 'x', 'r', 'w', 'x', 0 }; static char *function = "info_handle_bodyfile_file_name_attribute_fprint"; size64_t size = 0; uint64_t access_time = 0; uint64_t creation_time = 0; uint64_t entry_modification_time = 0; uint64_t file_reference = 0; uint64_t modification_time = 0; int64_t posix_access_time = 0; int64_t posix_creation_time = 0; int64_t posix_inode_change_time = 0; int64_t posix_modification_time = 0; uint32_t file_attribute_flags = 0; uint32_t group_identifier = 0; uint32_t owner_identifier = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( libfsntfs_file_entry_get_file_reference( file_entry, &file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file reference.", function ); return( -1 ); } if( libfsntfs_file_name_attribute_get_creation_time( attribute, &creation_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve creation time.", function ); return( -1 ); } if( libfsntfs_file_name_attribute_get_modification_time( attribute, &modification_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve modification time.", function ); return( -1 ); } if( libfsntfs_file_name_attribute_get_access_time( attribute, &access_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve access time.", function ); return( -1 ); } if( libfsntfs_file_name_attribute_get_entry_modification_time( attribute, &entry_modification_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry modification time.", function ); return( -1 ); } if( libfsntfs_file_name_attribute_get_file_attribute_flags( attribute, &file_attribute_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file attribute flags.", function ); return( -1 ); } if( libfsntfs_attribute_get_data_size( attribute, &size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data size.", function ); return( -1 ); } result = libfsntfs_file_entry_is_symbolic_link( file_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if file entry is a symbolic link.", function ); return( -1 ); } else if( result != 0 ) { file_mode_string[ 0 ] = 'l'; } else { result = libfsntfs_file_entry_has_directory_entries_index( file_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if file entry has directory entries index.", function ); return( -1 ); } else if( result != 0 ) { file_mode_string[ 0 ] = 'd'; } } if( ( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_READ_ONLY ) != 0 ) || ( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_SYSTEM ) != 0 ) ) { file_mode_string[ 2 ] = '-'; file_mode_string[ 5 ] = '-'; file_mode_string[ 8 ] = '-'; } /* Colums in a Sleuthkit 3.x and later bodyfile * MD5|name|inode|mode_as_string|UID|GID|size|atime|mtime|ctime|crtime */ fprintf( info_handle->bodyfile_stream, "0|" ); if( path != NULL ) { if( info_handle_bodyfile_name_value_fprint( info_handle, path, path_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print path string.", function ); return( -1 ); } } if( file_entry_name != NULL ) { if( info_handle_bodyfile_name_value_fprint( info_handle, file_entry_name, file_entry_name_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print file entry name string.", function ); return( -1 ); } } posix_access_time = (int64_t) access_time - 116444736000000000L; posix_creation_time = (int64_t) creation_time - 116444736000000000L; posix_inode_change_time = (int64_t) entry_modification_time - 116444736000000000L; posix_modification_time = (int64_t) modification_time - 116444736000000000L; fprintf( info_handle->bodyfile_stream, " ($FILE_NAME)|%" PRIu64 "-%" PRIu64 "|%s|%" PRIu32 "|%" PRIu32 "|%" PRIu64 "|%" PRIi64 ".%07" PRIi64 "|%" PRIi64 ".%07" PRIi64 "|%" PRIi64 ".%07" PRIi64 "|%" PRIi64 ".%07" PRIi64 "\n", file_reference & 0xffffffffffffUL, file_reference >> 48, file_mode_string, owner_identifier, group_identifier, size, posix_access_time / 10000000, posix_access_time - ( ( posix_access_time / 10000000 ) * 10000000 ), posix_modification_time / 10000000, posix_modification_time - ( ( posix_modification_time / 10000000 ) * 10000000 ), posix_inode_change_time / 10000000, posix_inode_change_time - ( ( posix_inode_change_time / 10000000 ) * 10000000 ), posix_creation_time / 10000000, posix_creation_time - ( ( posix_creation_time / 10000000 ) * 10000000 ) ); return( 1 ); } /* Prints a $I30 entry to a bodyfile * Returns 1 if successful or -1 on error */ int info_handle_bodyfile_i30_entry_fprint( info_handle_t *info_handle, libfsntfs_file_entry_t *file_entry, const system_character_t *path, size_t path_length, const system_character_t *file_entry_name, size_t file_entry_name_length, libcerror_error_t **error ) { char file_mode_string[ 11 ] = { '-', 'r', 'w', 'x', 'r', 'w', 'x', 'r', 'w', 'x', 0 }; static char *function = "info_handle_bodyfile_i30_entry_fprint"; size64_t size = 0; uint64_t access_time = 0; uint64_t creation_time = 0; uint64_t entry_modification_time = 0; uint64_t file_reference = 0; uint64_t modification_time = 0; int64_t posix_access_time = 0; int64_t posix_creation_time = 0; int64_t posix_inode_change_time = 0; int64_t posix_modification_time = 0; uint32_t file_attribute_flags = 0; uint32_t group_identifier = 0; uint32_t owner_identifier = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } result = libfsntfs_file_entry_has_i30_entry( file_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if file entry has a $I30 entry.", function ); return( -1 ); } else if( result == 0 ) { return( 1 ); } if( libfsntfs_file_entry_get_i30_file_reference( file_entry, &file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file reference.", function ); return( -1 ); } if( libfsntfs_file_entry_get_i30_creation_time( file_entry, &creation_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve creation time.", function ); return( -1 ); } if( libfsntfs_file_entry_get_i30_modification_time( file_entry, &modification_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve modification time.", function ); return( -1 ); } if( libfsntfs_file_entry_get_i30_access_time( file_entry, &access_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve access time.", function ); return( -1 ); } if( libfsntfs_file_entry_get_i30_entry_modification_time( file_entry, &entry_modification_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry modification time.", function ); return( -1 ); } if( libfsntfs_file_entry_get_i30_file_attribute_flags( file_entry, &file_attribute_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file attribute flags.", function ); return( -1 ); } if( libfsntfs_file_entry_get_i30_size( file_entry, &size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size.", function ); return( -1 ); } result = libfsntfs_file_entry_is_symbolic_link( file_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if file entry is a symbolic link.", function ); return( -1 ); } else if( result != 0 ) { file_mode_string[ 0 ] = 'l'; } else { result = libfsntfs_file_entry_has_directory_entries_index( file_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if file entry has directory entries index.", function ); return( -1 ); } else if( result != 0 ) { file_mode_string[ 0 ] = 'd'; } } if( ( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_READ_ONLY ) != 0 ) || ( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_SYSTEM ) != 0 ) ) { file_mode_string[ 2 ] = '-'; file_mode_string[ 5 ] = '-'; file_mode_string[ 8 ] = '-'; } /* Colums in a Sleuthkit 3.x and later bodyfile * MD5|name|inode|mode_as_string|UID|GID|size|atime|mtime|ctime|crtime */ fprintf( info_handle->bodyfile_stream, "0|" ); if( path != NULL ) { if( info_handle_bodyfile_name_value_fprint( info_handle, path, path_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print path string.", function ); return( -1 ); } } if( file_entry_name != NULL ) { if( info_handle_bodyfile_name_value_fprint( info_handle, file_entry_name, file_entry_name_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print file entry name string.", function ); return( -1 ); } } posix_access_time = (int64_t) access_time - 116444736000000000L; posix_creation_time = (int64_t) creation_time - 116444736000000000L; posix_inode_change_time = (int64_t) entry_modification_time - 116444736000000000L; posix_modification_time = (int64_t) modification_time - 116444736000000000L; fprintf( info_handle->bodyfile_stream, " ($I30)|%" PRIu64 "-%" PRIu64 "|%s|%" PRIu32 "|%" PRIu32 "|%" PRIu64 "|%" PRIi64 ".%07" PRIi64 "|%" PRIi64 ".%07" PRIi64 "|%" PRIi64 ".%07" PRIi64 "|%" PRIi64 ".%07" PRIi64 "\n", file_reference & 0xffffffffffffUL, file_reference >> 48, file_mode_string, owner_identifier, group_identifier, size, posix_access_time / 10000000, posix_access_time - ( ( posix_access_time / 10000000 ) * 10000000 ), posix_modification_time / 10000000, posix_modification_time - ( ( posix_modification_time / 10000000 ) * 10000000 ), posix_inode_change_time / 10000000, posix_inode_change_time - ( ( posix_inode_change_time / 10000000 ) * 10000000 ), posix_creation_time / 10000000, posix_creation_time - ( ( posix_creation_time / 10000000 ) * 10000000 ) ); return( 1 ); } /* Prints a $INDEX_ROOT attribute to a bodyfile * Returns 1 if successful, 0 if not or -1 on error */ int info_handle_bodyfile_index_root_attribute_fprint( info_handle_t *info_handle, libfsntfs_file_entry_t *file_entry, libfsntfs_attribute_t *attribute, const system_character_t *path, size_t path_length, const system_character_t *file_entry_name, size_t file_entry_name_length, const system_character_t *attribute_name, size_t attribute_name_size, libcerror_error_t **error ) { char file_mode_string[ 11 ] = { '-', 'r', 'w', 'x', 'r', 'w', 'x', 'r', 'w', 'x', 0 }; system_character_t *symbolic_link_target = NULL; static char *function = "info_handle_bodyfile_index_root_attribute_fprint"; size64_t size = 0; size_t symbolic_link_target_length = 0; size_t symbolic_link_target_size = 0; uint64_t access_time = 0; uint64_t creation_time = 0; uint64_t entry_modification_time = 0; uint64_t file_reference = 0; uint64_t modification_time = 0; int64_t posix_access_time = 0; int64_t posix_creation_time = 0; int64_t posix_inode_change_time = 0; int64_t posix_modification_time = 0; uint32_t file_attribute_flags = 0; uint32_t group_identifier = 0; uint32_t owner_identifier = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( libfsntfs_file_entry_get_file_reference( file_entry, &file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file reference.", function ); goto on_error; } result = libfsntfs_file_entry_get_creation_time( file_entry, &creation_time, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve creation time.", function ); goto on_error; } result = libfsntfs_file_entry_get_modification_time( file_entry, &modification_time, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve modification time.", function ); goto on_error; } result = libfsntfs_file_entry_get_access_time( file_entry, &access_time, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve access time.", function ); goto on_error; } result = libfsntfs_file_entry_get_entry_modification_time( file_entry, &entry_modification_time, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry modification time.", function ); goto on_error; } result = libfsntfs_file_entry_get_file_attribute_flags( file_entry, &file_attribute_flags, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file attribute flags.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_file_entry_get_utf16_symbolic_link_target_size( file_entry, &symbolic_link_target_size, error ); #else result = libfsntfs_file_entry_get_utf8_symbolic_link_target_size( file_entry, &symbolic_link_target_size, error ); #endif if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve symbolic link target string size.", function ); goto on_error; } else if( result != 0 ) { symbolic_link_target = system_string_allocate( symbolic_link_target_size ); if( symbolic_link_target == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create symbolic link target string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_file_entry_get_utf16_symbolic_link_target( file_entry, (uint16_t *) symbolic_link_target, symbolic_link_target_size, error ); #else result = libfsntfs_file_entry_get_utf8_symbolic_link_target( file_entry, (uint8_t *) symbolic_link_target, symbolic_link_target_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve symbolic link target string.", function ); goto on_error; } symbolic_link_target_length = symbolic_link_target_size - 1; } if( libfsntfs_attribute_get_data_size( attribute, &size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data size.", function ); goto on_error; } result = libfsntfs_file_entry_is_symbolic_link( file_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if file entry is a symbolic link.", function ); goto on_error; } else if( result != 0 ) { file_mode_string[ 0 ] = 'l'; } else { result = libfsntfs_file_entry_has_directory_entries_index( file_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if file entry has directory entries index.", function ); goto on_error; } else if( result != 0 ) { file_mode_string[ 0 ] = 'd'; } } if( ( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_READ_ONLY ) != 0 ) || ( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_SYSTEM ) != 0 ) ) { file_mode_string[ 2 ] = '-'; file_mode_string[ 5 ] = '-'; file_mode_string[ 8 ] = '-'; } /* Colums in a Sleuthkit 3.x and later bodyfile * MD5|name|inode|mode_as_string|UID|GID|size|atime|mtime|ctime|crtime */ fprintf( info_handle->bodyfile_stream, "0|" ); if( path != NULL ) { if( info_handle_bodyfile_name_value_fprint( info_handle, path, path_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print path string.", function ); goto on_error; } } if( file_entry_name != NULL ) { if( info_handle_bodyfile_name_value_fprint( info_handle, file_entry_name, file_entry_name_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print file entry name string.", function ); goto on_error; } } if( ( attribute_name != NULL ) && ( ( attribute_name_size != 5 ) || ( narrow_string_compare( attribute_name, "$I30", 4 ) != 0 ) ) ) { fprintf( info_handle->bodyfile_stream, ":%" PRIs_SYSTEM "", attribute_name ); } if( symbolic_link_target != NULL ) { fprintf( info_handle->bodyfile_stream, " -> " ); if( info_handle_bodyfile_name_value_fprint( info_handle, symbolic_link_target, symbolic_link_target_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print file entry name string.", function ); goto on_error; } } posix_access_time = (int64_t) access_time - 116444736000000000L; posix_creation_time = (int64_t) creation_time - 116444736000000000L; posix_inode_change_time = (int64_t) entry_modification_time - 116444736000000000L; posix_modification_time = (int64_t) modification_time - 116444736000000000L; fprintf( info_handle->bodyfile_stream, "|%" PRIu64 "-%" PRIu64 "|%s|%" PRIu32 "|%" PRIu32 "|%" PRIu64 "|%" PRIi64 ".%07" PRIi64 "|%" PRIi64 ".%07" PRIi64 "|%" PRIi64 ".%07" PRIi64 "|%" PRIi64 ".%07" PRIi64 "\n", file_reference & 0xffffffffffffUL, file_reference >> 48, file_mode_string, owner_identifier, group_identifier, size, posix_access_time / 10000000, posix_access_time - ( ( posix_access_time / 10000000 ) * 10000000 ), posix_modification_time / 10000000, posix_modification_time - ( ( posix_modification_time / 10000000 ) * 10000000 ), posix_inode_change_time / 10000000, posix_inode_change_time - ( ( posix_inode_change_time / 10000000 ) * 10000000 ), posix_creation_time / 10000000, posix_creation_time - ( ( posix_creation_time / 10000000 ) * 10000000 ) ); if( symbolic_link_target != NULL ) { memory_free( symbolic_link_target ); symbolic_link_target = NULL; } return( 1 ); on_error: if( symbolic_link_target != NULL ) { memory_free( symbolic_link_target ); } return( -1 ); } /* Prints a file entry value to a bodyfile * Returns 1 if successful, 0 if not or -1 on error */ int info_handle_bodyfile_file_entry_value_fprint( info_handle_t *info_handle, libfsntfs_file_entry_t *file_entry, libfsntfs_data_stream_t *alternate_data_stream, const system_character_t *path, size_t path_length, const system_character_t *file_entry_name, size_t file_entry_name_length, const system_character_t *data_stream_name, libcerror_error_t **error ) { char md5_string[ DIGEST_HASH_STRING_SIZE_MD5 ] = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 0 }; char file_mode_string[ 11 ] = { '-', 'r', 'w', 'x', 'r', 'w', 'x', 'r', 'w', 'x', 0 }; system_character_t *symbolic_link_target = NULL; static char *function = "info_handle_bodyfile_file_entry_value_fprint"; size64_t size = 0; size_t symbolic_link_target_length = 0; size_t symbolic_link_target_size = 0; uint64_t access_time = 0; uint64_t creation_time = 0; uint64_t entry_modification_time = 0; uint64_t file_reference = 0; uint64_t mft_entry_index = 0; uint64_t modification_time = 0; int64_t posix_access_time = 0; int64_t posix_creation_time = 0; int64_t posix_inode_change_time = 0; int64_t posix_modification_time = 0; uint32_t file_attribute_flags = 0; uint32_t group_identifier = 0; uint32_t owner_identifier = 0; int has_default_data_stream = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( libfsntfs_file_entry_get_file_reference( file_entry, &file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file reference.", function ); goto on_error; } mft_entry_index = file_reference & 0xffffffffffffUL; result = libfsntfs_file_entry_get_creation_time( file_entry, &creation_time, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve creation time.", function ); goto on_error; } result = libfsntfs_file_entry_get_modification_time( file_entry, &modification_time, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve modification time.", function ); goto on_error; } result = libfsntfs_file_entry_get_access_time( file_entry, &access_time, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve access time.", function ); goto on_error; } result = libfsntfs_file_entry_get_entry_modification_time( file_entry, &entry_modification_time, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry modification time.", function ); goto on_error; } result = libfsntfs_file_entry_get_file_attribute_flags( file_entry, &file_attribute_flags, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file attribute flags.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_file_entry_get_utf16_symbolic_link_target_size( file_entry, &symbolic_link_target_size, error ); #else result = libfsntfs_file_entry_get_utf8_symbolic_link_target_size( file_entry, &symbolic_link_target_size, error ); #endif if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve symbolic link target string size.", function ); goto on_error; } else if( result != 0 ) { symbolic_link_target = system_string_allocate( symbolic_link_target_size ); if( symbolic_link_target == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create symbolic link target string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_file_entry_get_utf16_symbolic_link_target( file_entry, (uint16_t *) symbolic_link_target, symbolic_link_target_size, error ); #else result = libfsntfs_file_entry_get_utf8_symbolic_link_target( file_entry, (uint8_t *) symbolic_link_target, symbolic_link_target_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve symbolic link target string.", function ); goto on_error; } symbolic_link_target_length = symbolic_link_target_size - 1; } if( alternate_data_stream != NULL ) { if( libfsntfs_data_stream_get_size( alternate_data_stream, &size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size.", function ); goto on_error; } } else { if( libfsntfs_file_entry_get_size( file_entry, &size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size.", function ); goto on_error; } } result = libfsntfs_file_entry_has_default_data_stream( file_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if file entry has default data stream.", function ); goto on_error; } has_default_data_stream = result; result = libfsntfs_file_entry_is_symbolic_link( file_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if file entry is a symbolic link.", function ); goto on_error; } else if( result != 0 ) { file_mode_string[ 0 ] = 'l'; } else { result = libfsntfs_file_entry_has_directory_entries_index( file_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if file entry has directory entries index.", function ); goto on_error; } else if( result != 0 ) { file_mode_string[ 0 ] = 'd'; } } if( ( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_READ_ONLY ) != 0 ) || ( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_SYSTEM ) != 0 ) ) { file_mode_string[ 2 ] = '-'; file_mode_string[ 5 ] = '-'; file_mode_string[ 8 ] = '-'; } if( ( info_handle->calculate_md5 == 0 ) || ( has_default_data_stream == 0 ) ) { md5_string[ 1 ] = 0; } else if( result == 0 ) { if( info_handle_file_entry_calculate_md5( info_handle, file_entry, md5_string, DIGEST_HASH_STRING_SIZE_MD5, error ) != 1 ) { fprintf( info_handle->notify_stream, "Error calculating MD5 of MFT entry: %" PRIu64 "\n", mft_entry_index ); if( ( error != NULL ) && ( *error != NULL ) ) { libcnotify_print_error_backtrace( *error ); } libcerror_error_free( error ); fprintf( info_handle->notify_stream, "\n" ); } } /* Colums in a Sleuthkit 3.x and later bodyfile * MD5|name|inode|mode_as_string|UID|GID|size|atime|mtime|ctime|crtime */ fprintf( info_handle->bodyfile_stream, "%s|", md5_string ); if( path != NULL ) { if( info_handle_bodyfile_name_value_fprint( info_handle, path, path_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print path string.", function ); goto on_error; } } if( file_entry_name != NULL ) { if( info_handle_bodyfile_name_value_fprint( info_handle, file_entry_name, file_entry_name_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print file entry name string.", function ); goto on_error; } } if( data_stream_name != NULL ) { fprintf( info_handle->bodyfile_stream, ":%" PRIs_SYSTEM "", data_stream_name ); } if( symbolic_link_target != NULL ) { fprintf( info_handle->bodyfile_stream, " -> " ); if( info_handle_bodyfile_name_value_fprint( info_handle, symbolic_link_target, symbolic_link_target_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print file entry name string.", function ); goto on_error; } } posix_access_time = (int64_t) access_time - 116444736000000000L; posix_creation_time = (int64_t) creation_time - 116444736000000000L; posix_inode_change_time = (int64_t) entry_modification_time - 116444736000000000L; posix_modification_time = (int64_t) modification_time - 116444736000000000L; fprintf( info_handle->bodyfile_stream, "|%" PRIu64 "-%" PRIu64 "|%s|%" PRIu32 "|%" PRIu32 "|%" PRIu64 "|%" PRIi64 ".%07" PRIi64 "|%" PRIi64 ".%07" PRIi64 "|%" PRIi64 ".%07" PRIi64 "|%" PRIi64 ".%07" PRIi64 "\n", mft_entry_index, file_reference >> 48, file_mode_string, owner_identifier, group_identifier, size, posix_access_time / 10000000, posix_access_time - ( ( posix_access_time / 10000000 ) * 10000000 ), posix_modification_time / 10000000, posix_modification_time - ( ( posix_modification_time / 10000000 ) * 10000000 ), posix_inode_change_time / 10000000, posix_inode_change_time - ( ( posix_inode_change_time / 10000000 ) * 10000000 ), posix_creation_time / 10000000, posix_creation_time - ( ( posix_creation_time / 10000000 ) * 10000000 ) ); if( symbolic_link_target != NULL ) { memory_free( symbolic_link_target ); symbolic_link_target = NULL; } return( 1 ); on_error: if( symbolic_link_target != NULL ) { memory_free( symbolic_link_target ); } return( -1 ); } /* Prints the MFT entry to a bodyfile * Returns 1 if successful, 0 if not or -1 on error */ int info_handle_bodyfile_mft_entry_fprint( info_handle_t *info_handle, uint64_t mft_entry_index, libcerror_error_t **error ) { libfsntfs_attribute_t *attribute = NULL; libfsntfs_file_entry_t *file_entry = NULL; system_character_t *path_hint = NULL; static char *function = "info_handle_bodyfile_mft_entry_fprint"; size_t path_hint_size = 0; uint64_t base_record_file_reference = 0; uint32_t attribute_type = 0; int attribute_index = 0; int is_empty = 0; int number_of_attributes = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( info_handle->input_mft_metadata_file != NULL ) { result = libfsntfs_mft_metadata_file_get_file_entry_by_index( info_handle->input_mft_metadata_file, mft_entry_index, &file_entry, error ); } else if( info_handle->input_volume != NULL ) { result = libfsntfs_volume_get_file_entry_by_index( info_handle->input_volume, mft_entry_index, &file_entry, error ); } if( result != 1 ) { fprintf( info_handle->notify_stream, "Error reading MFT entry: %" PRIu64 "\n", mft_entry_index ); if( ( error != NULL ) && ( *error != NULL ) ) { libcnotify_print_error_backtrace( *error ); } libcerror_error_free( error ); fprintf( info_handle->notify_stream, "\n" ); return( 0 ); } is_empty = libfsntfs_file_entry_is_empty( file_entry, error ); if( is_empty == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if file entry is empty.", function ); goto on_error; } else if( is_empty == 0 ) { if( libfsntfs_file_entry_get_base_record_file_reference( file_entry, &base_record_file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve base record file reference.", function ); goto on_error; } if( base_record_file_reference == 0 ) { if( libfsntfs_file_entry_get_number_of_attributes( file_entry, &number_of_attributes, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of attributes.", function ); goto on_error; } for( attribute_index = 0; attribute_index < number_of_attributes; attribute_index++ ) { if( libfsntfs_file_entry_get_attribute_by_index( file_entry, attribute_index, &attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d.", function, attribute_index ); goto on_error; } if( libfsntfs_attribute_get_type( attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); goto on_error; } if( attribute_type == LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ) { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_file_entry_get_utf16_path_hint_size( file_entry, attribute_index, &path_hint_size, error ); #else result = libfsntfs_file_entry_get_utf8_path_hint_size( file_entry, attribute_index, &path_hint_size, error ); #endif if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve path hint string size.", function ); goto on_error; } if( ( result != 0 ) && ( path_hint_size > 0 ) ) { path_hint = system_string_allocate( path_hint_size ); if( path_hint == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create path hint string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_file_entry_get_utf16_path_hint( file_entry, attribute_index, (uint16_t *) path_hint, path_hint_size, error ); #else result = libfsntfs_file_entry_get_utf8_path_hint( file_entry, attribute_index, (uint8_t *) path_hint, path_hint_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve path hint string.", function ); goto on_error; } } if( info_handle_file_entry_fprint( info_handle, file_entry, attribute, path_hint, NULL, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print file entry.", function ); goto on_error; } if( path_hint != NULL ) { memory_free( path_hint ); path_hint = NULL; } } if( libfsntfs_attribute_free( &attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free attribute: %d.", function, attribute_index ); goto on_error; } } } } if( libfsntfs_file_entry_free( &file_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file entry.", function ); goto on_error; } return( 1 ); on_error: if( path_hint != NULL ) { memory_free( path_hint ); } if( attribute != NULL ) { libfsntfs_attribute_free( &attribute, NULL ); } if( file_entry != NULL ) { libfsntfs_file_entry_free( &file_entry, NULL ); } return( -1 ); } /* Prints file entry as part of the file system hierarchy or to a bodyfile * Returns 1 if successful or -1 on error */ int info_handle_file_entry_fprint( info_handle_t *info_handle, libfsntfs_file_entry_t *file_entry, libfsntfs_attribute_t *file_name_attribute, const system_character_t *path, const system_character_t *file_entry_name, libcerror_error_t **error ) { libfsntfs_attribute_t *attribute = NULL; libfsntfs_data_stream_t *alternate_data_stream = NULL; system_character_t *attribute_name = NULL; system_character_t *data_stream_name = NULL; static char *function = "info_handle_file_entry_fprint"; size_t attribute_name_size = 0; size_t data_stream_name_size = 0; size_t file_entry_name_length = 0; size_t path_length = 0; uint32_t attribute_type = 0; int alternate_data_stream_index = 0; int attribute_index = 0; int has_default_data_stream = 0; int has_index_root_attributes = 0; int number_of_alternate_data_streams = 0; int number_of_attributes = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); return( -1 ); } path_length = system_string_length( path ); if( file_entry_name != NULL ) { file_entry_name_length = system_string_length( file_entry_name ); } result = libfsntfs_file_entry_has_default_data_stream( file_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if file entry has default data stream.", function ); goto on_error; } has_default_data_stream = result; if( libfsntfs_file_entry_get_number_of_alternate_data_streams( file_entry, &number_of_alternate_data_streams, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of alternate data streams.", function ); goto on_error; } if( libfsntfs_file_entry_get_number_of_attributes( file_entry, &number_of_attributes, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of attributes.", function ); goto on_error; } for( attribute_index = 0; attribute_index < number_of_attributes; attribute_index++ ) { if( libfsntfs_file_entry_get_attribute_by_index( file_entry, attribute_index, &attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d.", function, attribute_index ); goto on_error; } if( libfsntfs_attribute_get_type( attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); goto on_error; } if( attribute_type == LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ROOT ) { /* Mimic Sleuthkit behavior printing indexes */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_attribute_get_utf16_name_size( attribute, &attribute_name_size, error ); #else result = libfsntfs_attribute_get_utf8_name_size( attribute, &attribute_name_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute name string size.", function ); goto on_error; } if( attribute_name_size > 0 ) { attribute_name = system_string_allocate( attribute_name_size ); if( attribute_name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create name string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_attribute_get_utf16_name( attribute, (uint16_t *) attribute_name, attribute_name_size, error ); #else result = libfsntfs_attribute_get_utf8_name( attribute, (uint8_t *) attribute_name, attribute_name_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute name string.", function ); goto on_error; } } if( info_handle->bodyfile_stream != NULL ) { if( info_handle_bodyfile_index_root_attribute_fprint( info_handle, file_entry, attribute, path, path_length, file_entry_name, file_entry_name_length, attribute_name, attribute_name_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print file entry.", function ); goto on_error; } } else { if( info_handle_name_value_fprint( info_handle, path, path_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print path string.", function ); goto on_error; } if( file_entry_name != NULL ) { if( info_handle_name_value_fprint( info_handle, file_entry_name, file_entry_name_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print file entry name string.", function ); goto on_error; } } if( ( attribute_name != NULL ) && ( ( attribute_name_size != 5 ) || ( narrow_string_compare( attribute_name, "$I30", 4 ) != 0 ) ) ) { fprintf( info_handle->notify_stream, ":%" PRIs_SYSTEM "", attribute_name ); } fprintf( info_handle->notify_stream, "\n" ); } if( attribute_name != NULL ) { memory_free( attribute_name ); attribute_name = NULL; } has_index_root_attributes = 1; } if( libfsntfs_attribute_free( &attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free attribute: %d.", function, attribute_index ); goto on_error; } } /* Do not print the name of file entries that have an ADS but no default data stream * and file entries that have $INDEX_ROOT attributes. */ if( ( has_index_root_attributes == 0 ) && ( ( has_default_data_stream != 0 ) || ( number_of_alternate_data_streams == 0 ) ) ) { if( info_handle->bodyfile_stream != NULL ) { if( info_handle_bodyfile_file_entry_value_fprint( info_handle, file_entry, NULL, path, path_length, file_entry_name, file_entry_name_length, NULL, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print file entry.", function ); goto on_error; } } else { if( info_handle_name_value_fprint( info_handle, path, path_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print path string.", function ); goto on_error; } if( file_entry_name != NULL ) { if( info_handle_name_value_fprint( info_handle, file_entry_name, file_entry_name_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print file entry name string.", function ); goto on_error; } } fprintf( info_handle->notify_stream, "\n" ); } } for( alternate_data_stream_index = 0; alternate_data_stream_index < number_of_alternate_data_streams; alternate_data_stream_index++ ) { if( libfsntfs_file_entry_get_alternate_data_stream_by_index( file_entry, alternate_data_stream_index, &alternate_data_stream, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve alternate data stream: %d.", function, alternate_data_stream_index ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_data_stream_get_utf16_name_size( alternate_data_stream, &data_stream_name_size, error ); #else result = libfsntfs_data_stream_get_utf8_name_size( alternate_data_stream, &data_stream_name_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve alternate data stream: %d name string size.", function, alternate_data_stream_index ); goto on_error; } if( data_stream_name_size > 0 ) { data_stream_name = system_string_allocate( data_stream_name_size ); if( data_stream_name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create alternate data stream: %d name string.", function, alternate_data_stream_index ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_data_stream_get_utf16_name( alternate_data_stream, (uint16_t *) data_stream_name, data_stream_name_size, error ); #else result = libfsntfs_data_stream_get_utf8_name( alternate_data_stream, (uint8_t *) data_stream_name, data_stream_name_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve alternate data stream: %d name string.", function, alternate_data_stream_index ); goto on_error; } if( info_handle->bodyfile_stream != NULL ) { if( info_handle_bodyfile_file_entry_value_fprint( info_handle, file_entry, alternate_data_stream, path, path_length, file_entry_name, file_entry_name_length, data_stream_name, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print file entry.", function ); goto on_error; } } else { if( info_handle_name_value_fprint( info_handle, path, path_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print path string.", function ); goto on_error; } if( file_entry_name != NULL ) { if( info_handle_name_value_fprint( info_handle, file_entry_name, file_entry_name_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print file entry name string.", function ); goto on_error; } fprintf( info_handle->notify_stream, ":" ); if( info_handle_name_value_fprint( info_handle, data_stream_name, data_stream_name_size - 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print data stream name string.", function ); goto on_error; } } fprintf( info_handle->notify_stream, "\n" ); } memory_free( data_stream_name ); data_stream_name = NULL; } if( libfsntfs_data_stream_free( &alternate_data_stream, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free alternate data stream: %d.", function, alternate_data_stream ); goto on_error; } } if( info_handle->bodyfile_stream != NULL ) { if( file_name_attribute != NULL ) { if( info_handle_bodyfile_file_name_attribute_fprint( info_handle, file_entry, file_name_attribute, path, path_length, file_entry_name, file_entry_name_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print $FILE_NAME attribute.", function ); goto on_error; } } if( info_handle_bodyfile_i30_entry_fprint( info_handle, file_entry, path, path_length, file_entry_name, file_entry_name_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print $I30 entry.", function ); goto on_error; } } return( 1 ); on_error: if( attribute != NULL ) { libfsntfs_attribute_free( &attribute, NULL ); } if( data_stream_name != NULL ) { memory_free( data_stream_name ); } if( alternate_data_stream != NULL ) { libfsntfs_data_stream_free( &alternate_data_stream, NULL ); } if( attribute_name != NULL ) { memory_free( attribute_name ); } return( -1 ); } /* Prints file entry information as part of the file system hierarchy * Returns 1 if successful or -1 on error */ int info_handle_file_system_hierarchy_fprint_file_entry( info_handle_t *info_handle, libfsntfs_file_entry_t *file_entry, const system_character_t *path, libcerror_error_t **error ) { libfsntfs_attribute_t *file_name_attribute = NULL; libfsntfs_file_entry_t *sub_file_entry = NULL; system_character_t *file_entry_name = NULL; system_character_t *sub_path = NULL; static char *function = "info_handle_file_system_hierarchy_fprint_file_entry"; size_t file_entry_name_size = 0; size_t path_length = 0; size_t sub_path_size = 0; int name_attribute_index = 0; int number_of_sub_file_entries = 0; int result = 0; int sub_file_entry_index = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); return( -1 ); } path_length = system_string_length( path ); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_file_entry_get_utf16_name_size( file_entry, &file_entry_name_size, error ); #else result = libfsntfs_file_entry_get_utf8_name_size( file_entry, &file_entry_name_size, error ); #endif if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry name string size.", function ); goto on_error; } if( ( result == 1 ) && ( file_entry_name_size > 0 ) ) { file_entry_name = system_string_allocate( file_entry_name_size ); if( file_entry_name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create file entry name string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_file_entry_get_utf16_name( file_entry, (uint16_t *) file_entry_name, file_entry_name_size, error ); #else result = libfsntfs_file_entry_get_utf8_name( file_entry, (uint8_t *) file_entry_name, file_entry_name_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry name string.", function ); goto on_error; } } if( info_handle->bodyfile_stream != NULL ) { result = libfsntfs_file_entry_get_name_attribute_index( file_entry, &name_attribute_index, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name attribute index.", function ); goto on_error; } else if( result != 0 ) { if( libfsntfs_file_entry_get_attribute_by_index( file_entry, name_attribute_index, &file_name_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve $FILE_NAME attribute: %d.", function, name_attribute_index ); goto on_error; } } } if( ( info_handle->bodyfile_stream != NULL ) || ( file_entry_name != NULL ) ) { if( info_handle_file_entry_fprint( info_handle, file_entry, file_name_attribute, path, file_entry_name, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print file entry.", function ); goto on_error; } } if( file_name_attribute != NULL ) { if( libfsntfs_attribute_free( &file_name_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free attribute: %d.", function, name_attribute_index ); goto on_error; } } if( libfsntfs_file_entry_get_number_of_sub_file_entries( file_entry, &number_of_sub_file_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of sub file entries.", function ); goto on_error; } if( number_of_sub_file_entries > 0 ) { sub_path_size = path_length + 1; if( file_entry_name != NULL ) { sub_path_size += file_entry_name_size; } sub_path = system_string_allocate( sub_path_size ); if( sub_path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create sub path.", function ); goto on_error; } if( system_string_copy( sub_path, path, path_length ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy path to sub path.", function ); goto on_error; } if( file_entry_name != NULL ) { if( system_string_copy( &( sub_path[ path_length ] ), file_entry_name, file_entry_name_size - 1 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy file entry name to sub path.", function ); goto on_error; } sub_path[ sub_path_size - 2 ] = (system_character_t) LIBFSNTFS_SEPARATOR; } sub_path[ sub_path_size - 1 ] = (system_character_t) 0; for( sub_file_entry_index = 0; sub_file_entry_index < number_of_sub_file_entries; sub_file_entry_index++ ) { if( libfsntfs_file_entry_get_sub_file_entry_by_index( file_entry, sub_file_entry_index, &sub_file_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve sub file entry: %d.", function, sub_file_entry_index ); goto on_error; } if( info_handle_file_system_hierarchy_fprint_file_entry( info_handle, sub_file_entry, sub_path, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print file entry: %d information.", function, sub_file_entry_index ); goto on_error; } if( libfsntfs_file_entry_free( &sub_file_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free sub file entry: %d.", function, sub_file_entry_index ); goto on_error; } } if( sub_path != NULL ) { memory_free( sub_path ); sub_path = NULL; } } if( file_entry_name != NULL ) { memory_free( file_entry_name ); file_entry_name = NULL; } return( 1 ); on_error: if( sub_file_entry != NULL ) { libfsntfs_file_entry_free( &sub_file_entry, NULL ); } if( sub_path != NULL ) { memory_free( sub_path ); } if( file_name_attribute != NULL ) { libfsntfs_attribute_free( &file_name_attribute, NULL ); } if( file_entry_name != NULL ) { memory_free( file_entry_name ); } return( -1 ); } /* Prints the MFT entry information * Returns 1 if successful, 0 if not or -1 on error */ int info_handle_mft_entry_fprint( info_handle_t *info_handle, uint64_t mft_entry_index, libcerror_error_t **error ) { libfsntfs_attribute_t *attribute = NULL; libfsntfs_file_entry_t *file_entry = NULL; static char *function = "info_handle_mft_entry_fprint"; uint64_t base_record_file_reference = 0; uint64_t value_64bit = 0; int attribute_index = 0; int is_allocated = 0; int is_corrupted = 0; int is_empty = 0; int number_of_attributes = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( info_handle->input_mft_metadata_file != NULL ) { result = libfsntfs_mft_metadata_file_get_file_entry_by_index( info_handle->input_mft_metadata_file, mft_entry_index, &file_entry, error ); } else if( info_handle->input_volume != NULL ) { result = libfsntfs_volume_get_file_entry_by_index( info_handle->input_volume, mft_entry_index, &file_entry, error ); } if( result != 1 ) { fprintf( info_handle->notify_stream, "Error reading MFT entry: %" PRIu64 "\n", mft_entry_index ); if( ( error != NULL ) && ( *error != NULL ) ) { libcnotify_print_error_backtrace( *error ); } libcerror_error_free( error ); fprintf( info_handle->notify_stream, "\n" ); return( 0 ); } fprintf( info_handle->notify_stream, "MFT entry: %" PRIu64 " information:\n", mft_entry_index ); is_empty = libfsntfs_file_entry_is_empty( file_entry, error ); if( is_empty == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if file entry is empty.", function ); goto on_error; } else if( is_empty != 0 ) { fprintf( info_handle->notify_stream, "\tIs empty\n" ); fprintf( info_handle->notify_stream, "\n" ); } else { is_allocated = libfsntfs_file_entry_is_allocated( file_entry, error ); if( is_allocated == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if file entry is allocated.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tIs allocated\t\t\t: " ); if( is_allocated == 0 ) { fprintf( info_handle->notify_stream, "false" ); } else { fprintf( info_handle->notify_stream, "true" ); } fprintf( info_handle->notify_stream, "\n" ); if( libfsntfs_file_entry_get_file_reference( file_entry, &value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file reference.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tFile reference\t\t\t: %" PRIu64 "-%" PRIu64 "\n", value_64bit & 0xffffffffffffUL, value_64bit >> 48 ); if( libfsntfs_file_entry_get_base_record_file_reference( file_entry, &base_record_file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve base record file reference.", function ); goto on_error; } if( base_record_file_reference == 0 ) { fprintf( info_handle->notify_stream, "\tBase record file reference\t: Not set (0)\n" ); } else { fprintf( info_handle->notify_stream, "\tBase record file reference\t: %" PRIu64 "-%" PRIu64 "\n", base_record_file_reference & 0xffffffffffffUL, base_record_file_reference >> 48 ); } if( libfsntfs_file_entry_get_journal_sequence_number( file_entry, &value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve journal sequence number.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tJournal sequence number\t\t: %" PRIu64 "\n", value_64bit ); if( libfsntfs_file_entry_get_number_of_attributes( file_entry, &number_of_attributes, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of attributes.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tNumber of attributes\t\t: %d\n", number_of_attributes ); is_corrupted = libfsntfs_file_entry_is_corrupted( file_entry, error ); if( is_corrupted == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if file entry is corrupted.", function ); goto on_error; } else if( is_corrupted != 0 ) { fprintf( info_handle->notify_stream, "\tIs corrupted\n" ); } fprintf( info_handle->notify_stream, "\n" ); for( attribute_index = 0; attribute_index < number_of_attributes; attribute_index++ ) { if( libfsntfs_file_entry_get_attribute_by_index( file_entry, attribute_index, &attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d.", function, attribute_index ); goto on_error; } if( info_handle_attribute_fprint( info_handle, file_entry, attribute, attribute_index, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print attribute: %d information.", function, attribute_index ); goto on_error; } if( libfsntfs_attribute_free( &attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free attribute: %d.", function, attribute_index ); goto on_error; } } } if( libfsntfs_file_entry_free( &file_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file entry.", function ); goto on_error; } return( 1 ); on_error: if( attribute != NULL ) { libfsntfs_attribute_free( &attribute, NULL ); } if( file_entry != NULL ) { libfsntfs_file_entry_free( &file_entry, NULL ); } return( -1 ); } /* Prints the MFT entries information * Returns 1 if successful or -1 on error */ int info_handle_mft_entries_fprint( info_handle_t *info_handle, libcerror_error_t **error ) { static char *function = "info_handle_mft_entries_fprint"; uint64_t file_entry_index = 0; uint64_t number_of_file_entries = 0; int result = 0; if( info_handle->input_mft_metadata_file != NULL ) { result = libfsntfs_mft_metadata_file_get_number_of_file_entries( info_handle->input_mft_metadata_file, &number_of_file_entries, error ); } else if( info_handle->input_volume != NULL ) { result = libfsntfs_volume_get_number_of_file_entries( info_handle->input_volume, &number_of_file_entries, error ); } if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of file entries.", function ); return( -1 ); } if( number_of_file_entries > (uint64_t) INT64_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid number of file entries value out of bounds.", function ); return( -1 ); } for( file_entry_index = 0; file_entry_index < number_of_file_entries; file_entry_index++ ) { if( info_handle->bodyfile_stream != NULL ) { result = info_handle_bodyfile_mft_entry_fprint( info_handle, file_entry_index, error ); } else { result = info_handle_mft_entry_fprint( info_handle, file_entry_index, error ); } if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print MFT entry: %" PRIu64 ".", function, file_entry_index ); return( -1 ); } else if( result == 0 ) { fprintf( info_handle->notify_stream, "Unable to print MFT entry: %" PRIu64 ".\n\n", file_entry_index ); } } return( 1 ); } /* Prints the file entry information for a specific path * Returns 1 if successful or -1 on error */ int info_handle_file_entry_fprint_by_path( info_handle_t *info_handle, const system_character_t *path, libcerror_error_t **error ) { libfsntfs_file_entry_t *file_entry = NULL; system_character_t *file_entry_path = NULL; static char *function = "info_handle_file_entry_fprint_by_path"; size_t data_stream_name_index = 0; size_t data_stream_name_length = 0; size_t file_entry_path_length = 0; size_t file_entry_path_size = 0; size_t path_index = 0; size_t path_length = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); return( -1 ); } path_length = system_string_length( path ); for( path_index = path_length - 1; path_index > 0; path_index-- ) { if( path[ path_index ] == (system_character_t) ':' ) { data_stream_name_index = path_index + 1; break; } else if( path[ path_index ] == (system_character_t) LIBFSNTFS_SEPARATOR ) { break; } data_stream_name_length++; } if( data_stream_name_index > 0 ) { path_length -= data_stream_name_length + 1; } if( path_string_copy_to_file_entry_path( path, path_length, LIBFSNTFS_SEPARATOR, &file_entry_path, &file_entry_path_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy path to file entry path.", function ); goto on_error; } if( file_entry_path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing file entry path.", function ); goto on_error; } /* Need to determine length here since size is based on the worst case */ file_entry_path_length = system_string_length( file_entry_path ); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_volume_get_file_entry_by_utf16_path( info_handle->input_volume, (uint16_t *) file_entry_path, file_entry_path_length, &file_entry, error ); #else result = libfsntfs_volume_get_file_entry_by_utf8_path( info_handle->input_volume, (uint8_t *) file_entry_path, file_entry_path_length, &file_entry, error ); #endif if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry.", function ); goto on_error; } else if( result == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: file entry not found.", function ); goto on_error; } memory_free( file_entry_path ); file_entry_path = NULL; if( info_handle->bodyfile_stream == NULL ) { fprintf( info_handle->notify_stream, "New Technology File System information:\n\n" ); fprintf( info_handle->notify_stream, "File entry:\n" ); /* TODO remove data stream name */ fprintf( info_handle->notify_stream, "\tPath\t\t\t\t: %" PRIs_SYSTEM "\n", path ); } if( info_handle_file_entry_value_fprint( info_handle, file_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print file entry.", function ); goto on_error; } if( libfsntfs_file_entry_free( &file_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file entry.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\n" ); return( 1 ); on_error: if( file_entry != NULL ) { libfsntfs_file_entry_free( &file_entry, NULL ); } if( file_entry_path != NULL ) { memory_free( file_entry_path ); } return( -1 ); } /* Prints the file system hierarchy information * Returns 1 if successful or -1 on error */ int info_handle_file_system_hierarchy_fprint( info_handle_t *info_handle, libcerror_error_t **error ) { libfsntfs_file_entry_t *file_entry = NULL; static char *function = "info_handle_file_system_hierarchy_fprint"; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } if( info_handle->bodyfile_stream == NULL ) { fprintf( info_handle->notify_stream, "New Technology File System information:\n\n" ); fprintf( info_handle->notify_stream, "File system hierarchy:\n" ); } if( libfsntfs_volume_get_root_directory( info_handle->input_volume, &file_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve root directory file entry.", function ); goto on_error; } if( info_handle_file_system_hierarchy_fprint_file_entry( info_handle, file_entry, _SYSTEM_STRING( "\\" ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print root directory file entry information.", function ); goto on_error; } if( libfsntfs_file_entry_free( &file_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file entry.", function ); goto on_error; } if( info_handle->bodyfile_stream == NULL ) { fprintf( info_handle->notify_stream, "\n" ); } return( 1 ); on_error: if( file_entry != NULL ) { libfsntfs_file_entry_free( &file_entry, NULL ); } return( -1 ); } /* Prints the USN change journal ($UsnJrnl) record update reason to the notify stream */ void info_handle_usn_record_update_reason_flags_fprint( uint32_t update_reason_flags, FILE *notify_stream ) { /* TODO add description */ if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_DATA_OVERWRITE ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_DATA_OVERWRITE)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_DATA_EXTEND ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_DATA_EXTEND)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_DATA_TRUNCATION ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_DATA_TRUNCATION)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_NAMED_DATA_OVERWRITE ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_NAMED_DATA_OVERWRITE)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_NAMED_DATA_EXTEND ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_NAMED_DATA_EXTEND)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_NAMED_DATA_TRUNCATION ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_NAMED_DATA_TRUNCATION)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_FILE_CREATE ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_FILE_CREATE)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_FILE_DELETE ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_FILE_DELETE)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_EXTENDED_ATTRIBUTE_CHANGE ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_EA_CHANGE)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_SECURITY_CHANGE ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_SECURITY_CHANGE)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_RENAME_OLD_NAME ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_RENAME_OLD_NAME)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_RENAME_NEW_NAME ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_RENAME_NEW_NAME)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_INDEXABLE_CHANGE ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_INDEXABLE_CHANGE)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_BASIC_INFO_CHANGE ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_BASIC_INFO_CHANGE)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_HARD_LINK_CHANGE ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_HARD_LINK_CHANGE)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_COMPRESSION_CHANGE ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_COMPRESSION_CHANGE)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_ENCRYPTION_CHANGE ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_ENCRYPTION_CHANGE)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_OBJECT_IDENTIFIER_CHANGE ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_OBJECT_IDENTIFIER_CHANGE)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_REPARSE_POINT_CHANGE ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_REPARSE_POINT_CHANGE)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_STREAM_CHANGE ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_STREAM_CHANGE)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_TRANSACTED_CHANGE ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_TRANSACTED_CHANGE)\n" ); } if( ( update_reason_flags & LIBFUSN_UPDATE_REASON_FLAG_CLOSE ) != 0 ) { fprintf( notify_stream, "\t\t(USN_REASON_CLOSE)\n" ); } } /* Prints the USN change journal ($UsnJrnl) record update source flags to the notify stream */ void info_handle_usn_record_update_source_flags_fprint( uint32_t update_source_flags, FILE *notify_stream ) { /* TODO add description */ if( ( update_source_flags & LIBFUSN_UPDATE_SOURCE_FLAG_DATA_MANAGEMENT ) != 0 ) { fprintf( notify_stream, "\t\t(USN_SOURCE_DATA_MANAGEMENT)\n" ); } if( ( update_source_flags & LIBFUSN_UPDATE_SOURCE_FLAG_AUXILIARY_DATA ) != 0 ) { fprintf( notify_stream, "\t\t(USN_SOURCE_AUXILIARY_DATA)\n" ); } if( ( update_source_flags & LIBFUSN_UPDATE_SOURCE_FLAG_REPLICATION_MANAGEMENT ) != 0 ) { fprintf( notify_stream, "\t\t(USN_SOURCE_REPLICATION_MANAGEMENT)\n" ); } } /* Prints the USN change journal ($UsnJrnl) record information * Returns 1 if successful or -1 on error */ int info_handle_usn_record_fprint( info_handle_t *info_handle, libfusn_record_t *usn_record, libcerror_error_t **error ) { system_character_t *value_string = NULL; static char *function = "info_handle_usn_record_fprint"; size_t value_string_size = 0; uint64_t value_64bit = 0; uint32_t value_32bit = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } fprintf( info_handle->notify_stream, "USN record:\n" ); if( libfusn_record_get_update_time( usn_record, &value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve update time.", function ); goto on_error; } if( info_handle_filetime_value_fprint( info_handle, "\tUpdate time\t\t\t", value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print FILETIME value.", function ); goto on_error; } if( libfusn_record_get_update_sequence_number( usn_record, &value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve update sequence number.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tUpdate sequence number\t\t: %" PRIu64 "\n", value_64bit ); if( libfusn_record_get_update_reason_flags( usn_record, &value_32bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve update reason flags.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tUpdate reason flags\t\t: 0x%08" PRIx32 "\n", value_32bit ); info_handle_usn_record_update_reason_flags_fprint( value_32bit, info_handle->notify_stream ); fprintf( info_handle->notify_stream, "\n" ); if( libfusn_record_get_update_source_flags( usn_record, &value_32bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve update source flags.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tUpdate source flags\t\t: 0x%08" PRIx32 "\n", value_32bit ); info_handle_usn_record_update_source_flags_fprint( value_32bit, info_handle->notify_stream ); fprintf( info_handle->notify_stream, "\n" ); fprintf( info_handle->notify_stream, "\tName\t\t\t\t: " ); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfusn_record_get_utf16_name_size( usn_record, &value_string_size, error ); #else result = libfusn_record_get_utf8_name_size( usn_record, &value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name string size.", function ); goto on_error; } if( value_string_size > 0 ) { value_string = system_string_allocate( value_string_size ); if( value_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create name string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfusn_record_get_utf16_name( usn_record, (uint16_t *) value_string, value_string_size, error ); #else result = libfusn_record_get_utf8_name( usn_record, (uint8_t *) value_string, value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name string.", function ); goto on_error; } if( info_handle_name_value_fprint( info_handle, value_string, value_string_size - 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print name string.", function ); goto on_error; } memory_free( value_string ); value_string = NULL; } fprintf( info_handle->notify_stream, "\n" ); if( libfusn_record_get_file_reference( usn_record, &value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file reference.", function ); goto on_error; } if( value_64bit == 0 ) { fprintf( info_handle->notify_stream, "\tFile reference\t\t\t: %" PRIu64 "\n", value_64bit ); } else { fprintf( info_handle->notify_stream, "\tFile reference\t\t\t: %" PRIu64 "-%" PRIu64 "\n", value_64bit & 0xffffffffffffUL, value_64bit >> 48 ); } if( libfusn_record_get_parent_file_reference( usn_record, &value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve parent file reference.", function ); goto on_error; } if( value_64bit == 0 ) { fprintf( info_handle->notify_stream, "\tParent file reference\t\t: %" PRIu64 "\n", value_64bit ); } else { fprintf( info_handle->notify_stream, "\tParent file reference\t\t: %" PRIu64 "-%" PRIu64 "\n", value_64bit & 0xffffffffffffUL, value_64bit >> 48 ); } if( libfusn_record_get_file_attribute_flags( usn_record, &value_32bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file attribute flags.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\tFile attribute flags\t\t: 0x%08" PRIx32 "\n", value_32bit ); info_handle_file_attribute_flags_fprint( value_32bit, info_handle->notify_stream ); fprintf( info_handle->notify_stream, "\n" ); return( 1 ); on_error: if( value_string != NULL ) { memory_free( value_string ); } return( -1 ); } /* Prints the USN change journal ($UsnJrnl) entry information * Returns 1 if successful or -1 on error */ int info_handle_usn_change_journal_fprint( info_handle_t *info_handle, libcerror_error_t **error ) { libfsntfs_usn_change_journal_t *usn_change_journal = NULL; libfusn_record_t *usn_record = NULL; uint8_t *buffer = NULL; static char *function = "info_handle_usn_change_journal_fprint"; size_t journal_block_size = 0; ssize_t read_count = 0; uint32_t usn_record_size = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } fprintf( info_handle->notify_stream, "New Technology File System information:\n\n" ); result = libfsntfs_volume_get_usn_change_journal( info_handle->input_volume, &usn_change_journal, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve USN change journal.", function ); goto on_error; } else if( result == 0 ) { fprintf( info_handle->notify_stream, "USN change journal: N/A\n\n" ); return( 1 ); } /* TODO get journal block size from USN change journal */ journal_block_size = 0x1000; if( ( journal_block_size == 0 ) || ( journal_block_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid journal block size value out of bounds.", function ); goto on_error; } fprintf( info_handle->notify_stream, "USN change journal: \\$Extend\\$UsnJrnl\n\n" ); buffer = (uint8_t *) memory_allocate( sizeof( uint8_t ) * journal_block_size ); if( buffer == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create buffer.", function ); goto on_error; } do { read_count = libfsntfs_usn_change_journal_read_usn_record( usn_change_journal, buffer, journal_block_size, error ); if( read_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read USN record data.", function ); goto on_error; } else if( read_count > 0 ) { if( libfusn_record_initialize( &usn_record, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize USN record.", function ); goto on_error; } if( libfusn_record_copy_from_byte_stream( usn_record, buffer, read_count, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to copy USN record from byte stream.", function ); goto on_error; } if( libfusn_record_get_size( usn_record, &usn_record_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve USN record size.", function ); goto on_error; } if( info_handle_usn_record_fprint( info_handle, usn_record, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print USN record information.", function ); goto on_error; } if( libfusn_record_free( &usn_record, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free USN record.", function ); goto on_error; } } } while( read_count > 0 ); memory_free( buffer ); buffer = NULL; if( libfsntfs_usn_change_journal_free( &usn_change_journal, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free USN change journal.", function ); goto on_error; } fprintf( info_handle->notify_stream, "\n" ); return( 1 ); on_error: if( usn_record != NULL ) { libfusn_record_free( &usn_record, NULL ); } if( buffer != NULL ) { memory_free( buffer ); } if( usn_change_journal != NULL ) { libfsntfs_usn_change_journal_free( &usn_change_journal, NULL ); } return( -1 ); } /* Prints the volume information * Returns 1 if successful or -1 on error */ int info_handle_volume_fprint( info_handle_t *info_handle, libcerror_error_t **error ) { system_character_t *volume_name = NULL; static char *function = "info_handle_volume_fprint"; size32_t cluster_block_size = 0; size32_t index_entry_size = 0; size32_t mft_entry_size = 0; size_t volume_name_size = 0; uint64_t serial_number = 0; uint16_t bytes_per_sector = 0; uint16_t flags = 0; uint8_t major_version = 0; uint8_t minor_version = 0; int result = 0; if( info_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid info handle.", function ); return( -1 ); } fprintf( info_handle->notify_stream, "New Technology File System information:\n\n" ); fprintf( info_handle->notify_stream, "Volume information:\n" ); fprintf( info_handle->notify_stream, "\tName\t\t\t\t:" ); if( info_handle->input_mft_metadata_file != NULL ) { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_mft_metadata_file_get_utf16_volume_name_size( info_handle->input_mft_metadata_file, &volume_name_size, error ); #else result = libfsntfs_mft_metadata_file_get_utf8_volume_name_size( info_handle->input_mft_metadata_file, &volume_name_size, error ); #endif } else if( info_handle->input_volume != NULL ) { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_volume_get_utf16_name_size( info_handle->input_volume, &volume_name_size, error ); #else result = libfsntfs_volume_get_utf8_name_size( info_handle->input_volume, &volume_name_size, error ); #endif } if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve volume name string size.", function ); goto on_error; } else if( ( result != 0 ) && ( volume_name_size > 0 ) ) { volume_name = system_string_allocate( volume_name_size ); if( volume_name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create volume name string.", function ); goto on_error; } if( info_handle->input_mft_metadata_file != NULL ) { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_mft_metadata_file_get_utf16_volume_name( info_handle->input_mft_metadata_file, (uint16_t *) volume_name, volume_name_size, error ); #else result = libfsntfs_mft_metadata_file_get_utf8_volume_name( info_handle->input_mft_metadata_file, (uint8_t *) volume_name, volume_name_size, error ); #endif } else if( info_handle->input_volume != NULL ) { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_volume_get_utf16_name( info_handle->input_volume, (uint16_t *) volume_name, volume_name_size, error ); #else result = libfsntfs_volume_get_utf8_name( info_handle->input_volume, (uint8_t *) volume_name, volume_name_size, error ); #endif } if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve volume name string.", function ); goto on_error; } fprintf( info_handle->notify_stream, " %" PRIs_SYSTEM "", volume_name ); memory_free( volume_name ); volume_name = NULL; } fprintf( info_handle->notify_stream, "\n" ); fprintf( info_handle->notify_stream, "\tVersion\t\t\t\t:" ); if( info_handle->input_mft_metadata_file != NULL ) { result = libfsntfs_mft_metadata_file_get_volume_version( info_handle->input_mft_metadata_file, &major_version, &minor_version, error ); } else if( info_handle->input_volume != NULL ) { result = libfsntfs_volume_get_version( info_handle->input_volume, &major_version, &minor_version, error ); } if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve version.", function ); return( -1 ); } else if( result != 0 ) { fprintf( info_handle->notify_stream, " %" PRIu8 ".%" PRIu8 "", major_version, minor_version ); } fprintf( info_handle->notify_stream, "\n" ); if( info_handle->input_volume != NULL ) { if( libfsntfs_volume_get_serial_number( info_handle->input_volume, &serial_number, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve serial number.", function ); return( -1 ); } fprintf( info_handle->notify_stream, "\tSerial number\t\t\t: %08" PRIx64 "\n", serial_number ); if( libfsntfs_volume_get_bytes_per_sector( info_handle->input_volume, &bytes_per_sector, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve bytes per sector.", function ); return( -1 ); } fprintf( info_handle->notify_stream, "\tBytes per sector\t\t: %" PRIu16 "\n", bytes_per_sector ); if( libfsntfs_volume_get_cluster_block_size( info_handle->input_volume, &cluster_block_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve cluster block size.", function ); return( -1 ); } fprintf( info_handle->notify_stream, "\tCluster block size\t\t: %" PRIu32 "\n", cluster_block_size ); } if( info_handle->input_mft_metadata_file != NULL ) { /* TODO */ } else if( info_handle->input_volume != NULL ) { result = libfsntfs_volume_get_mft_entry_size( info_handle->input_volume, &mft_entry_size, error ); } if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry size.", function ); return( -1 ); } fprintf( info_handle->notify_stream, "\tMFT entry size\t\t\t: %" PRIu32 "\n", mft_entry_size ); if( info_handle->input_volume != NULL ) { if( libfsntfs_volume_get_index_entry_size( info_handle->input_volume, &index_entry_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve index entry size.", function ); return( -1 ); } fprintf( info_handle->notify_stream, "\tIndex entry size\t\t: %" PRIu32 "\n", index_entry_size ); } fprintf( info_handle->notify_stream, "\tFlags\t\t\t\t:" ); if( info_handle->input_mft_metadata_file != NULL ) { result = libfsntfs_mft_metadata_file_get_volume_flags( info_handle->input_mft_metadata_file, &flags, error ); } else if( info_handle->input_volume != NULL ) { result = libfsntfs_volume_get_flags( info_handle->input_volume, &flags, error ); } if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve flags.", function ); return( -1 ); } else if( result != 0 ) { fprintf( info_handle->notify_stream, " 0x%04" PRIx16 "", flags ); } fprintf( info_handle->notify_stream, "\n" ); if( ( flags & 0x0001 ) != 0 ) { fprintf( info_handle->notify_stream, "\t\tIs dirty\n" ); } if( ( flags & 0x0002 ) != 0 ) { fprintf( info_handle->notify_stream, "\t\tRe-size journal\n" ); } if( ( flags & 0x0004 ) != 0 ) { fprintf( info_handle->notify_stream, "\t\tUpgrade on next mount\n" ); } if( ( flags & 0x0008 ) != 0 ) { fprintf( info_handle->notify_stream, "\t\tMounted on Windows NT 4\n" ); } if( ( flags & 0x0010 ) != 0 ) { fprintf( info_handle->notify_stream, "\t\tDelete USN underway\n" ); } if( ( flags & 0x0020 ) != 0 ) { fprintf( info_handle->notify_stream, "\t\tRepair object identifiers\n" ); } if( ( flags & 0x8000 ) != 0 ) { fprintf( info_handle->notify_stream, "\t\tModified by chkdsk\n" ); } /* TODO print more info */ fprintf( info_handle->notify_stream, "\n" ); return( 1 ); on_error: if( volume_name != NULL ) { memory_free( volume_name ); } return( -1 ); } ================================================ FILE: fsntfstools/info_handle.h ================================================ /* * Info handle * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _INFO_HANDLE_H ) #define _INFO_HANDLE_H #include #include #include #include "fsntfstools_libbfio.h" #include "fsntfstools_libcerror.h" #include "fsntfstools_libfsntfs.h" #include "fsntfstools_libfusn.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct info_handle info_handle_t; struct info_handle { /* The MFT entry index */ uint64_t entry_index; /* The volume offset */ off64_t volume_offset; /* The libbfio input file IO handle */ libbfio_handle_t *input_file_io_handle; /* The libfsntfs input volume */ libfsntfs_volume_t *input_volume; /* The libfsntfs input MFT metadata file */ libfsntfs_mft_metadata_file_t *input_mft_metadata_file; /* Value to indicate if the MD5 hash should be calculated */ uint8_t calculate_md5; /* The bodyfile output stream */ FILE *bodyfile_stream; /* The notification output stream */ FILE *notify_stream; /* Value to indicate if abort was signalled */ int abort; }; int fsntfstools_system_string_copy_decimal_to_integer_64_bit( const system_character_t *string, size_t string_size, uint64_t *value_64bit, libcerror_error_t **error ); void info_handle_file_attribute_flags_fprint( uint32_t file_attribute_flags, FILE *notify_stream ); void info_handle_volume_information_flags_fprint( uint16_t volume_information_flags, FILE *notify_stream ); const char *info_handle_get_access_control_entry_type( uint8_t entry_type ); const char *info_handle_get_attribute_type_description( uint32_t attribute_type ); int info_handle_initialize( info_handle_t **info_handle, uint8_t calculate_md5, libcerror_error_t **error ); int info_handle_free( info_handle_t **info_handle, libcerror_error_t **error ); int info_handle_signal_abort( info_handle_t *info_handle, libcerror_error_t **error ); int info_handle_set_bodyfile( info_handle_t *info_handle, const system_character_t *filename, libcerror_error_t **error ); int info_handle_set_volume_offset( info_handle_t *info_handle, const system_character_t *string, libcerror_error_t **error ); int info_handle_open_input( info_handle_t *info_handle, const system_character_t *filename, libcerror_error_t **error ); int info_handle_close_input( info_handle_t *info_handle, libcerror_error_t **error ); int info_handle_file_entry_calculate_md5( info_handle_t *info_handle, libfsntfs_file_entry_t *file_entry, char *md5_string, size_t md5_string_size, libcerror_error_t **error ); int info_handle_name_value_fprint( info_handle_t *info_handle, const system_character_t *value_string, size_t value_string_length, libcerror_error_t **error ); int info_handle_filetime_value_fprint( info_handle_t *info_handle, const char *value_name, uint64_t value_64bit, libcerror_error_t **error ); int info_handle_security_descriptor_fprint( info_handle_t *info_handle, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int info_handle_attribute_fprint( info_handle_t *info_handle, libfsntfs_file_entry_t *file_entry, libfsntfs_attribute_t *attribute, int attribute_index, libcerror_error_t **error ); int info_handle_attribute_list_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ); int info_handle_bitmap_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ); int info_handle_data_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ); int info_handle_file_name_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ); int info_handle_object_identifier_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ); int info_handle_reparse_point_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ); int info_handle_security_descriptor_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ); int info_handle_standard_information_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ); int info_handle_volume_information_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ); int info_handle_volume_name_attribute_fprint( info_handle_t *info_handle, libfsntfs_attribute_t *attribute, libcerror_error_t **error ); int info_handle_file_entry_value_fprint( info_handle_t *info_handle, libfsntfs_file_entry_t *file_entry, libcerror_error_t **error ); int info_handle_bodyfile_name_value_fprint( info_handle_t *info_handle, const system_character_t *value_string, size_t value_string_length, libcerror_error_t **error ); int info_handle_bodyfile_file_name_attribute_fprint( info_handle_t *info_handle, libfsntfs_file_entry_t *file_entry, libfsntfs_attribute_t *attribute, const system_character_t *path, size_t path_length, const system_character_t *file_entry_name, size_t file_entry_name_length, libcerror_error_t **error ); int info_handle_bodyfile_i30_entry_fprint( info_handle_t *info_handle, libfsntfs_file_entry_t *file_entry, const system_character_t *path, size_t path_length, const system_character_t *file_entry_name, size_t file_entry_name_length, libcerror_error_t **error ); int info_handle_bodyfile_index_root_attribute_fprint( info_handle_t *info_handle, libfsntfs_file_entry_t *file_entry, libfsntfs_attribute_t *attribute, const system_character_t *path, size_t path_length, const system_character_t *file_entry_name, size_t file_entry_name_length, const system_character_t *attribute_name, size_t attribute_name_size, libcerror_error_t **error ); int info_handle_bodyfile_file_entry_value_fprint( info_handle_t *info_handle, libfsntfs_file_entry_t *file_entry, libfsntfs_data_stream_t *alternate_data_stream, const system_character_t *path, size_t path_length, const system_character_t *file_entry_name, size_t file_entry_name_length, const system_character_t *data_stream_name, libcerror_error_t **error ); int info_handle_bodyfile_mft_entry_fprint( info_handle_t *info_handle, uint64_t mft_entry_index, libcerror_error_t **error ); int info_handle_file_entry_fprint( info_handle_t *info_handle, libfsntfs_file_entry_t *file_entry, libfsntfs_attribute_t *file_name_attribute, const system_character_t *path, const system_character_t *file_entry_name, libcerror_error_t **error ); int info_handle_file_system_hierarchy_fprint_file_entry( info_handle_t *info_handle, libfsntfs_file_entry_t *file_entry, const system_character_t *path, libcerror_error_t **error ); int info_handle_mft_entry_fprint( info_handle_t *info_handle, uint64_t mft_entry_index, libcerror_error_t **error ); int info_handle_mft_entries_fprint( info_handle_t *info_handle, libcerror_error_t **error ); int info_handle_file_entry_fprint_by_path( info_handle_t *info_handle, const system_character_t *path, libcerror_error_t **error ); int info_handle_file_system_hierarchy_fprint( info_handle_t *info_handle, libcerror_error_t **error ); void info_handle_usn_record_update_reason_flags_fprint( uint32_t update_reason_flags, FILE *notify_stream ); void info_handle_usn_record_update_source_flags_fprint( uint32_t update_source_flags, FILE *notify_stream ); int info_handle_usn_record_fprint( info_handle_t *info_handle, libfusn_record_t *usn_record, libcerror_error_t **error ); int info_handle_usn_change_journal_fprint( info_handle_t *info_handle, libcerror_error_t **error ); int info_handle_volume_fprint( info_handle_t *info_handle, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _INFO_HANDLE_H ) */ ================================================ FILE: fsntfstools/mount_dokan.c ================================================ /* * Mount tool dokan functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "fsntfstools_libcerror.h" #include "fsntfstools_libcnotify.h" #include "fsntfstools_libfsntfs.h" #include "fsntfstools_unused.h" #include "mount_dokan.h" #include "mount_file_entry.h" #include "mount_handle.h" extern mount_handle_t *fsntfsmount_mount_handle; #if defined( HAVE_LIBDOKAN ) #if ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) #define MOUNT_DOKAN_ERROR_BAD_ARGUMENTS -ERROR_BAD_ARGUMENTS #define MOUNT_DOKAN_ERROR_FILE_NOT_FOUND -ERROR_FILE_NOT_FOUND #define MOUNT_DOKAN_ERROR_GENERIC_FAILURE -ERROR_GEN_FAILURE #define MOUNT_DOKAN_ERROR_READ_FAULT -ERROR_READ_FAULT #else #define MOUNT_DOKAN_ERROR_BAD_ARGUMENTS STATUS_UNSUCCESSFUL #define MOUNT_DOKAN_ERROR_FILE_NOT_FOUND STATUS_OBJECT_NAME_NOT_FOUND #define MOUNT_DOKAN_ERROR_GENERIC_FAILURE STATUS_UNSUCCESSFUL #define MOUNT_DOKAN_ERROR_READ_FAULT STATUS_UNEXPECTED_IO_ERROR #endif /* ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) */ #if defined( HAVE_DOKAN_LONG_PATHS ) #define DOKAN_MAX_PATH 32768 #else #define DOKAN_MAX_PATH MAX_PATH #endif /* Sets the values in a file information structure * The time values contain an unsigned 64-bit FILETIME timestamp * Returns 1 if successful or -1 on error */ int mount_dokan_set_file_information( BY_HANDLE_FILE_INFORMATION *file_information, size64_t size, uint16_t file_mode, uint64_t creation_time, uint64_t access_time, uint64_t modification_time, libcerror_error_t **error ) { static char *function = "mount_dokan_set_file_information"; if( file_information == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file information.", function ); return( -1 ); } if( size > 0 ) { file_information->nFileSizeHigh = (DWORD) ( size >> 32 ); file_information->nFileSizeLow = (DWORD) ( size & 0xffffffffUL ); } if( ( file_mode & 0x4000 ) != 0 ) { file_information->dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; } else { file_information->dwFileAttributes = FILE_ATTRIBUTE_NORMAL; } file_information->ftCreationTime.dwLowDateTime = (uint32_t) ( creation_time & 0x00000000ffffffffULL ); file_information->ftCreationTime.dwHighDateTime = creation_time >> 32; file_information->ftLastAccessTime.dwLowDateTime = (uint32_t) ( access_time & 0x00000000ffffffffULL ); file_information->ftLastAccessTime.dwHighDateTime = access_time >> 32; file_information->ftLastWriteTime.dwLowDateTime = (uint32_t) ( modification_time & 0x00000000ffffffffULL ); file_information->ftLastWriteTime.dwHighDateTime = modification_time >> 32; return( 1 ); } /* Sets the values in a find data structure * The time values contain an unsigned 64-bit FILETIME timestamp * Returns 1 if successful or -1 on error */ int mount_dokan_set_find_data( WIN32_FIND_DATAW *find_data, size64_t size, uint16_t file_mode, uint64_t creation_time, uint64_t access_time, uint64_t modification_time, libcerror_error_t **error ) { static char *function = "mount_dokan_set_find_data"; if( find_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid find data.", function ); return( -1 ); } if( size > 0 ) { find_data->nFileSizeHigh = (DWORD) ( size >> 32 ); find_data->nFileSizeLow = (DWORD) ( size & 0xffffffffUL ); } if( ( file_mode & 0x4000 ) != 0 ) { find_data->dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; } else { find_data->dwFileAttributes = FILE_ATTRIBUTE_NORMAL; } find_data->ftCreationTime.dwLowDateTime = (uint32_t) ( creation_time & 0x00000000ffffffffULL ); find_data->ftCreationTime.dwHighDateTime = creation_time >> 32; find_data->ftLastAccessTime.dwLowDateTime = (uint32_t) ( access_time & 0x00000000ffffffffULL ); find_data->ftLastAccessTime.dwHighDateTime = access_time >> 32; find_data->ftLastWriteTime.dwLowDateTime = (uint32_t) ( modification_time & 0x00000000ffffffffULL ); find_data->ftLastWriteTime.dwHighDateTime = modification_time >> 32; return( 1 ); } /* Fills a directory entry * Returns 1 if successful or -1 on error */ int mount_dokan_filldir( PFillFindData fill_find_data, DOKAN_FILE_INFO *file_info, wchar_t *name, size_t name_size, WIN32_FIND_DATAW *find_data, mount_file_entry_t *file_entry, libcerror_error_t **error ) { static char *function = "mount_dokan_filldir"; size64_t file_size = 0; uint64_t access_time = 0; uint64_t creation_time = 0; uint64_t modification_time = 0; uint16_t file_mode = 0; if( fill_find_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid fill find data.", function ); return( -1 ); } if( name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid name.", function ); return( -1 ); } if( name_size > (size_t) DOKAN_MAX_PATH ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid name size value out of bounds.", function ); return( -1 ); } if( file_entry != NULL ) { if( mount_file_entry_get_size( file_entry, &file_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry size.", function ); return( -1 ); } if( mount_file_entry_get_file_mode( file_entry, &file_mode, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file mode.", function ); return( -1 ); } if( mount_file_entry_get_creation_time( file_entry, &creation_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve creation time.", function ); return( -1 ); } if( mount_file_entry_get_access_time( file_entry, &access_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve access time.", function ); return( -1 ); } if( mount_file_entry_get_modification_time( file_entry, &modification_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve modification time.", function ); return( -1 ); } } if( memory_set( find_data, 0, sizeof( WIN32_FIND_DATAW ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear find data.", function ); return( -1 ); } if( wide_string_copy( find_data->cFileName, name, name_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy filename.", function ); return( -1 ); } if( name_size <= (size_t) 14 ) { if( wide_string_copy( find_data->cAlternateFileName, name, name_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy alternate filename.", function ); return( -1 ); } } if( mount_dokan_set_find_data( find_data, file_size, file_mode, creation_time, access_time, modification_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set find data.", function ); return( -1 ); } if( fill_find_data( find_data, file_info ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set directory entry.", function ); return( -1 ); } return( 1 ); } #if ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) /* Opens a file or directory * Returns 0 if successful or an error code otherwise */ int __stdcall mount_dokan_CreateFile( const wchar_t *path, DWORD desired_access, DWORD share_mode FSNTFSTOOLS_ATTRIBUTE_UNUSED, DWORD creation_disposition, DWORD attribute_flags FSNTFSTOOLS_ATTRIBUTE_UNUSED, DOKAN_FILE_INFO *file_info ) { libcerror_error_t *error = NULL; static char *function = "mount_dokan_CreateFile"; int result = 0; FSNTFSTOOLS_UNREFERENCED_PARAMETER( share_mode ) FSNTFSTOOLS_UNREFERENCED_PARAMETER( attribute_flags ) #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: %ls\n", function, path ); } #endif if( path == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); result = -ERROR_BAD_ARGUMENTS; goto on_error; } if( ( desired_access & GENERIC_WRITE ) != 0 ) { return( -ERROR_WRITE_PROTECT ); } /* Ignore the share_mode */ if( creation_disposition == CREATE_NEW ) { return( -ERROR_FILE_EXISTS ); } else if( creation_disposition == CREATE_ALWAYS ) { return( -ERROR_ALREADY_EXISTS ); } else if( creation_disposition == OPEN_ALWAYS ) { return( -ERROR_FILE_NOT_FOUND ); } else if( creation_disposition == TRUNCATE_EXISTING ) { return( -ERROR_FILE_NOT_FOUND ); } else if( creation_disposition != OPEN_EXISTING ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid creation disposition.", function ); result = -ERROR_BAD_ARGUMENTS; goto on_error; } if( file_info == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file information.", function ); result = -ERROR_BAD_ARGUMENTS; goto on_error; } if( file_info->Context != (ULONG64) NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file information - context already set.", function ); result = -ERROR_BAD_ARGUMENTS; goto on_error; } if( mount_handle_get_file_entry_by_path( fsntfsmount_mount_handle, path, (mount_file_entry_t **) &( file_info->Context ), &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry for path: %ls.", function, path ); result = -ERROR_FILE_NOT_FOUND; goto on_error; } return( 0 ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } return( result ); } #else /* Opens a file or directory * Returns 0 if successful or an error code otherwise */ NTSTATUS __stdcall mount_dokan_ZwCreateFile( const wchar_t *path, DOKAN_IO_SECURITY_CONTEXT *security_context FSNTFSTOOLS_ATTRIBUTE_UNUSED, ACCESS_MASK desired_access, ULONG file_attributes FSNTFSTOOLS_ATTRIBUTE_UNUSED, ULONG share_access FSNTFSTOOLS_ATTRIBUTE_UNUSED, ULONG creation_disposition, ULONG creation_options FSNTFSTOOLS_ATTRIBUTE_UNUSED, DOKAN_FILE_INFO *file_info ) { libcerror_error_t *error = NULL; static char *function = "mount_dokan_ZwCreateFile"; int result = 0; FSNTFSTOOLS_UNREFERENCED_PARAMETER( security_context ) FSNTFSTOOLS_UNREFERENCED_PARAMETER( file_attributes ) FSNTFSTOOLS_UNREFERENCED_PARAMETER( share_access ) FSNTFSTOOLS_UNREFERENCED_PARAMETER( creation_options ) if( path == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); result = STATUS_UNSUCCESSFUL; goto on_error; } if( ( desired_access & GENERIC_WRITE ) != 0 ) { return( STATUS_MEDIA_WRITE_PROTECTED ); } /* Ignore the share_mode */ if( creation_disposition == FILE_CREATE ) { return( STATUS_OBJECT_NAME_COLLISION ); } else if( ( creation_disposition != FILE_OPEN ) && ( creation_disposition != FILE_OPEN_IF ) ) { return( STATUS_ACCESS_DENIED ); } if( file_info == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file information.", function ); result = STATUS_UNSUCCESSFUL; goto on_error; } if( file_info->Context != (ULONG64) NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file information - context already set.", function ); result = STATUS_UNSUCCESSFUL; goto on_error; } if( mount_handle_get_file_entry_by_path( fsntfsmount_mount_handle, path, (mount_file_entry_t **) &( file_info->Context ), &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry for path: %ls.", function, path ); result = STATUS_OBJECT_NAME_NOT_FOUND; goto on_error; } return( STATUS_SUCCESS ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } return( result ); } #endif /* ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) */ #if ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) /* Opens a directory * Returns 0 if successful or an error code otherwise */ int __stdcall mount_dokan_OpenDirectory( const wchar_t *path, DOKAN_FILE_INFO *file_info ) { libcerror_error_t *error = NULL; static char *function = "mount_dokan_OpenDirectory"; int result = 0; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: %ls\n", function, path ); } #endif if( path == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); result = MOUNT_DOKAN_ERROR_BAD_ARGUMENTS; goto on_error; } if( file_info == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file information.", function ); result = MOUNT_DOKAN_ERROR_BAD_ARGUMENTS; goto on_error; } if( file_info->Context != (ULONG64) NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file information - context already set.", function ); result = MOUNT_DOKAN_ERROR_BAD_ARGUMENTS; goto on_error; } if( mount_handle_get_file_entry_by_path( fsntfsmount_mount_handle, path, (mount_file_entry_t **) &( file_info->Context ), &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry for path: %ls.", function, path ); result = MOUNT_DOKAN_ERROR_FILE_NOT_FOUND; goto on_error; } return( 0 ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } return( result ); } #endif /* ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) */ /* Closes a file or directory * Returns 0 if successful or an error code otherwise */ #if ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) int __stdcall mount_dokan_CloseFile( const wchar_t *path, DOKAN_FILE_INFO *file_info ) #else NTSTATUS __stdcall mount_dokan_CloseFile( const wchar_t *path, DOKAN_FILE_INFO *file_info ) #endif { libcerror_error_t *error = NULL; static char *function = "mount_dokan_CloseFile"; int result = 0; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: %ls\n", function, path ); } #endif if( path == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); result = MOUNT_DOKAN_ERROR_BAD_ARGUMENTS; goto on_error; } if( file_info == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file information.", function ); result = MOUNT_DOKAN_ERROR_BAD_ARGUMENTS; goto on_error; } if( file_info->Context != (ULONG64) NULL ) { if( mount_file_entry_free( (mount_file_entry_t **) &( file_info->Context ), &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file entry.", function ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } } return( 0 ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } return( result ); } /* Reads a buffer of data at the specified offset * Returns 0 if successful or an error code otherwise */ #if ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) int __stdcall mount_dokan_ReadFile( const wchar_t *path, void *buffer, DWORD number_of_bytes_to_read, DWORD *number_of_bytes_read, LONGLONG offset, DOKAN_FILE_INFO *file_info ) #else NTSTATUS __stdcall mount_dokan_ReadFile( const wchar_t *path, void *buffer, DWORD number_of_bytes_to_read, DWORD *number_of_bytes_read, LONGLONG offset, DOKAN_FILE_INFO *file_info ) #endif { libcerror_error_t *error = NULL; static char *function = "mount_dokan_ReadFile"; ssize_t read_count = 0; int result = 0; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: %ls\n", function, path ); } #endif if( path == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); result = MOUNT_DOKAN_ERROR_BAD_ARGUMENTS; goto on_error; } if( number_of_bytes_to_read > (DWORD) INT32_MAX ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid number of bytes to read value exceeds maximum.", function ); result = MOUNT_DOKAN_ERROR_BAD_ARGUMENTS; goto on_error; } if( number_of_bytes_read == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid number of bytes read.", function ); result = MOUNT_DOKAN_ERROR_BAD_ARGUMENTS; goto on_error; } if( file_info == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file information.", function ); result = MOUNT_DOKAN_ERROR_BAD_ARGUMENTS; goto on_error; } if( file_info->Context == (ULONG64) NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid file information - missing context.", function ); result = MOUNT_DOKAN_ERROR_BAD_ARGUMENTS; goto on_error; } read_count = mount_file_entry_read_buffer_at_offset( (mount_file_entry_t *) file_info->Context, buffer, (size_t) number_of_bytes_to_read, (off64_t) offset, &error ); if( read_count < 0 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read from file entry.", function ); result = MOUNT_DOKAN_ERROR_READ_FAULT; goto on_error; } if( read_count > (size_t) INT32_MAX ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid read count value exceeds maximum.", function ); result = MOUNT_DOKAN_ERROR_READ_FAULT; goto on_error; } /* Dokan does not require the read function to return ERROR_HANDLE_EOF */ *number_of_bytes_read = (DWORD) read_count; return( 0 ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } return( result ); } /* Reads a directory * Returns 0 if successful or an error code otherwise */ #if ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) int __stdcall mount_dokan_FindFiles( const wchar_t *path, PFillFindData fill_find_data, DOKAN_FILE_INFO *file_info ) #else NTSTATUS __stdcall mount_dokan_FindFiles( const wchar_t *path, PFillFindData fill_find_data, DOKAN_FILE_INFO *file_info ) #endif { WIN32_FIND_DATAW find_data; libcerror_error_t *error = NULL; mount_file_entry_t *file_entry = NULL; mount_file_entry_t *parent_file_entry = NULL; mount_file_entry_t *sub_file_entry = NULL; wchar_t *name = NULL; static char *function = "mount_dokan_FindFiles"; size_t name_size = 0; int number_of_sub_file_entries = 0; int result = 0; int sub_file_entry_index = 0; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: %ls\n", function, path ); } #endif if( path == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); result = MOUNT_DOKAN_ERROR_BAD_ARGUMENTS; goto on_error; } if( mount_handle_get_file_entry_by_path( fsntfsmount_mount_handle, path, &file_entry, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry for path: %ls.", function, path ); result = MOUNT_DOKAN_ERROR_FILE_NOT_FOUND; goto on_error; } if( mount_dokan_filldir( fill_find_data, file_info, L".", 2, &find_data, file_entry, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set self find data.", function ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } result = mount_file_entry_get_parent_file_entry( file_entry, &parent_file_entry, &error ); if( result == -1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve parent file entry.", function ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } if( mount_dokan_filldir( fill_find_data, file_info, L"..", 3, &find_data, parent_file_entry, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set parent find data.", function ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } if( mount_file_entry_free( &parent_file_entry, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free parent file entry.", function ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } if( mount_file_entry_get_number_of_sub_file_entries( file_entry, &number_of_sub_file_entries, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of sub file entries.", function ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } for( sub_file_entry_index = 0; sub_file_entry_index < number_of_sub_file_entries; sub_file_entry_index++ ) { if( mount_file_entry_get_sub_file_entry_by_index( file_entry, sub_file_entry_index, &sub_file_entry, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve sub file entry: %d.", function, sub_file_entry_index ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } if( mount_file_entry_get_name_size( sub_file_entry, &name_size, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve sub file entry: %d name size.", function, sub_file_entry_index ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } name = wide_string_allocate( name_size ); if( name == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create sub file entry: %d name.", function ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } if( mount_file_entry_get_name( sub_file_entry, name, name_size, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve sub file entry: %d name.", function, sub_file_entry_index ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } if( mount_dokan_filldir( fill_find_data, file_info, name, name_size, &find_data, sub_file_entry, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set sub file entry: %d find data.", function, sub_file_entry_index ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } memory_free( name ); name = NULL; if( mount_file_entry_free( &sub_file_entry, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free sub file entry: %d.", function, sub_file_entry_index ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } } if( mount_file_entry_free( &file_entry, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file entry.", function ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } return( 0 ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } if( name != NULL ) { memory_free( name ); } if( sub_file_entry != NULL ) { mount_file_entry_free( &sub_file_entry, NULL ); } if( parent_file_entry != NULL ) { mount_file_entry_free( &parent_file_entry, NULL ); } if( file_entry != NULL ) { mount_file_entry_free( &file_entry, NULL ); } return( result ); } /* Retrieves the file information * Returns 0 if successful or an error code otherwise */ #if ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) int __stdcall mount_dokan_GetFileInformation( const wchar_t *path, BY_HANDLE_FILE_INFORMATION *file_information, DOKAN_FILE_INFO *file_info FSNTFSTOOLS_ATTRIBUTE_UNUSED ) #else NTSTATUS __stdcall mount_dokan_GetFileInformation( const wchar_t *path, BY_HANDLE_FILE_INFORMATION *file_information, DOKAN_FILE_INFO *file_info FSNTFSTOOLS_ATTRIBUTE_UNUSED ) #endif { libcerror_error_t *error = NULL; mount_file_entry_t *file_entry = NULL; static char *function = "mount_dokan_GetFileInformation"; size64_t file_size = 0; uint64_t access_time = 0; uint64_t creation_time = 0; uint64_t modification_time = 0; uint16_t file_mode = 0; int result = 0; FSNTFSTOOLS_UNREFERENCED_PARAMETER( file_info ) #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: %ls\n", function, path ); } #endif if( path == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); result = MOUNT_DOKAN_ERROR_BAD_ARGUMENTS; goto on_error; } if( mount_handle_get_file_entry_by_path( fsntfsmount_mount_handle, path, &file_entry, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry for path: %ls.", function, path ); result = MOUNT_DOKAN_ERROR_FILE_NOT_FOUND; goto on_error; } if( file_entry != NULL ) { if( mount_file_entry_get_size( file_entry, &file_size, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry size.", function ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } if( mount_file_entry_get_file_mode( file_entry, &file_mode, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file mode.", function ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } if( mount_file_entry_get_creation_time( file_entry, &creation_time, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve creation time.", function ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } if( mount_file_entry_get_access_time( file_entry, &access_time, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve access time.", function ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } if( mount_file_entry_get_modification_time( file_entry, &modification_time, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve modification time.", function ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } } if( mount_dokan_set_file_information( file_information, file_size, file_mode, creation_time, access_time, modification_time, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set file information.", function ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } if( mount_file_entry_free( &file_entry, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file entry.", function ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } return( 0 ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } if( file_entry != NULL ) { mount_file_entry_free( &file_entry, NULL ); } return( result ); } /* Retrieves the volume information * Returns 0 if successful or an error code otherwise */ #if ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) int __stdcall mount_dokan_GetVolumeInformation( wchar_t *volume_name, DWORD volume_name_size, DWORD *volume_serial_number, DWORD *maximum_filename_length, DWORD *file_system_flags, wchar_t *file_system_name, DWORD file_system_name_size, DOKAN_FILE_INFO *file_info FSNTFSTOOLS_ATTRIBUTE_UNUSED ) #else NTSTATUS __stdcall mount_dokan_GetVolumeInformation( wchar_t *volume_name, DWORD volume_name_size, DWORD *volume_serial_number, DWORD *maximum_filename_length, DWORD *file_system_flags, wchar_t *file_system_name, DWORD file_system_name_size, DOKAN_FILE_INFO *file_info FSNTFSTOOLS_ATTRIBUTE_UNUSED ) #endif { libcerror_error_t *error = NULL; const wchar_t *name = NULL; static char *function = "mount_dokan_GetVolumeInformation"; size_t name_size = 0; int result = 0; FSNTFSTOOLS_UNREFERENCED_PARAMETER( file_info ) #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: %ls\n", function, volume_name ); } #endif name = L"FSNTFS"; name_size = 1 + wide_string_length( name ); if( ( volume_name != NULL ) && ( volume_name_size > (DWORD) name_size ) ) { /* Using wcsncpy seems to cause strange behavior here */ if( memory_copy( volume_name, name, name_size * sizeof( wchar_t ) ) == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy volume name.", function ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } } if( volume_serial_number != NULL ) { /* If this value contains 0 it can crash the system is this an issue in Dokan? */ *volume_serial_number = 0x19831116; } if( maximum_filename_length != NULL ) { *maximum_filename_length = 256; } if( file_system_flags != NULL ) { *file_system_flags = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK | FILE_READ_ONLY_VOLUME; } name = L"Dokan"; name_size = 1 + wide_string_length( name ); if( ( file_system_name != NULL ) && ( file_system_name_size > (DWORD) name_size ) ) { /* Using wcsncpy seems to cause strange behavior here */ if( memory_copy( file_system_name, name, name_size * sizeof( wchar_t ) ) == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy file system name.", function ); result = MOUNT_DOKAN_ERROR_GENERIC_FAILURE; goto on_error; } } return( 0 ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } return( result ); } #if ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) /* Unmounts the volume * Returns 0 if successful or an error code otherwise */ int __stdcall mount_dokan_Unmount( DOKAN_FILE_INFO *file_info FSNTFSTOOLS_ATTRIBUTE_UNUSED ) { static char *function = "mount_dokan_Unmount"; FSNTFSTOOLS_UNREFERENCED_PARAMETER( file_info ) #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s\n", function ); } #endif return( 0 ); } #endif /* ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) */ #endif /* defined( HAVE_LIBDOKAN ) */ ================================================ FILE: fsntfstools/mount_dokan.h ================================================ /* * Mount tool dokan functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _MOUNT_DOKAN_H ) #define _MOUNT_DOKAN_H #include #include #if defined( HAVE_LIBDOKAN ) #include #endif #include "fsntfstools_libcerror.h" #include "fsntfstools_libfsntfs.h" #include "mount_file_entry.h" #if defined( __cplusplus ) extern "C" { #endif #if defined( HAVE_LIBDOKAN ) int mount_dokan_set_file_information( BY_HANDLE_FILE_INFORMATION *file_information, size64_t size, uint16_t file_mode, uint64_t creation_time, uint64_t access_time, uint64_t modification_time, libcerror_error_t **error ); int mount_dokan_set_find_data( WIN32_FIND_DATAW *find_data, size64_t size, uint16_t file_mode, uint64_t creation_time, uint64_t access_time, uint64_t modification_time, libcerror_error_t **error ); int mount_dokan_filldir( PFillFindData fill_find_data, DOKAN_FILE_INFO *file_info, wchar_t *name, size_t name_size, WIN32_FIND_DATAW *find_data, mount_file_entry_t *file_entry, libcerror_error_t **error ); #if ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) int __stdcall mount_dokan_CreateFile( const wchar_t *path, DWORD desired_access, DWORD share_mode, DWORD creation_disposition, DWORD attribute_flags, DOKAN_FILE_INFO *file_info ); #else NTSTATUS __stdcall mount_dokan_ZwCreateFile( const wchar_t *path, DOKAN_IO_SECURITY_CONTEXT *security_context, ACCESS_MASK desired_access, ULONG file_attributes, ULONG share_access, ULONG creation_disposition, ULONG creation_options, DOKAN_FILE_INFO *file_info ); #endif #if ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) int __stdcall mount_dokan_OpenDirectory( const wchar_t *path, DOKAN_FILE_INFO *file_info ); #endif #if ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) int __stdcall mount_dokan_CloseFile( const wchar_t *path, DOKAN_FILE_INFO *file_info ); #else NTSTATUS __stdcall mount_dokan_CloseFile( const wchar_t *path, DOKAN_FILE_INFO *file_info ); #endif #if ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) int __stdcall mount_dokan_ReadFile( const wchar_t *path, void *buffer, DWORD number_of_bytes_to_read, DWORD *number_of_bytes_read, LONGLONG offset, DOKAN_FILE_INFO *file_info ); #else NTSTATUS __stdcall mount_dokan_ReadFile( const wchar_t *path, void *buffer, DWORD number_of_bytes_to_read, DWORD *number_of_bytes_read, LONGLONG offset, DOKAN_FILE_INFO *file_info ); #endif #if ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) int __stdcall mount_dokan_FindFiles( const wchar_t *path, PFillFindData fill_find_data, DOKAN_FILE_INFO *file_info ); #else NTSTATUS __stdcall mount_dokan_FindFiles( const wchar_t *path, PFillFindData fill_find_data, DOKAN_FILE_INFO *file_info ); #endif #if ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) int __stdcall mount_dokan_GetFileInformation( const wchar_t *path, BY_HANDLE_FILE_INFORMATION *file_information, DOKAN_FILE_INFO *file_info ); #else NTSTATUS __stdcall mount_dokan_GetFileInformation( const wchar_t *path, BY_HANDLE_FILE_INFORMATION *file_information, DOKAN_FILE_INFO *file_info ); #endif #if ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) int __stdcall mount_dokan_GetVolumeInformation( wchar_t *volume_name, DWORD volume_name_size, DWORD *volume_serial_number, DWORD *maximum_filename_length, DWORD *file_system_flags, wchar_t *file_system_name, DWORD file_system_name_size, DOKAN_FILE_INFO *file_info ); #else NTSTATUS __stdcall mount_dokan_GetVolumeInformation( wchar_t *volume_name, DWORD volume_name_size, DWORD *volume_serial_number, DWORD *maximum_filename_length, DWORD *file_system_flags, wchar_t *file_system_name, DWORD file_system_name_size, DOKAN_FILE_INFO *file_info ); #endif #if ( DOKAN_VERSION >= 600 ) && ( DOKAN_VERSION < 800 ) int __stdcall mount_dokan_Unmount( DOKAN_FILE_INFO *file_info ); #endif #endif /* defined( HAVE_LIBDOKAN ) */ #if defined( __cplusplus ) } #endif #endif /* !defined( _MOUNT_DOKAN_H ) */ ================================================ FILE: fsntfstools/mount_file_entry.c ================================================ /* * Mount file entry * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #if defined( HAVE_SYS_STAT_H ) #include #endif #include "fsntfstools_libcerror.h" #include "fsntfstools_libfsntfs.h" #include "mount_file_entry.h" #include "mount_file_system.h" #if !defined( S_IFDIR ) #define S_IFDIR 0x4000 #endif #if !defined( S_IFREG ) #define S_IFREG 0x8000 #endif #if !defined( S_IFLNK ) #define S_IFLNK 0xa000 #endif /* Creates a file entry * Make sure the value file_entry is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int mount_file_entry_initialize( mount_file_entry_t **file_entry, mount_file_system_t *file_system, const system_character_t *name, size_t name_length, libfsntfs_file_entry_t *fsntfs_file_entry, libcerror_error_t **error ) { static char *function = "mount_file_entry_initialize"; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( *file_entry != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file entry value already set.", function ); return( -1 ); } if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } if( name_length > (size_t) ( SSIZE_MAX - 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid name length value exceeds maximum.", function ); return( -1 ); } *file_entry = memory_allocate_structure( mount_file_entry_t ); if( *file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create file entry.", function ); goto on_error; } if( memory_set( *file_entry, 0, sizeof( mount_file_entry_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear file entry.", function ); memory_free( *file_entry ); *file_entry = NULL; return( -1 ); } ( *file_entry )->file_system = file_system; if( name != NULL ) { ( *file_entry )->name = system_string_allocate( name_length + 1 ); if( ( *file_entry )->name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create name string.", function ); goto on_error; } if( name_length > 0 ) { if( system_string_copy( ( *file_entry )->name, name, name_length ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy name.", function ); goto on_error; } } ( *file_entry )->name[ name_length ] = 0; ( *file_entry )->name_size = name_length + 1; } ( *file_entry )->fsntfs_file_entry = fsntfs_file_entry; return( 1 ); on_error: if( *file_entry != NULL ) { if( ( *file_entry )->name != NULL ) { memory_free( ( *file_entry )->name ); } memory_free( *file_entry ); *file_entry = NULL; } return( -1 ); } /* Frees a file entry * Returns 1 if successful or -1 on error */ int mount_file_entry_free( mount_file_entry_t **file_entry, libcerror_error_t **error ) { static char *function = "mount_file_entry_free"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( *file_entry != NULL ) { if( ( *file_entry )->name != NULL ) { memory_free( ( *file_entry )->name ); } if( libfsntfs_file_entry_free( &( ( *file_entry )->fsntfs_file_entry ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file entry.", function ); result = -1; } memory_free( *file_entry ); *file_entry = NULL; } return( result ); } /* Retrieves the parent file entry * Returns 1 if successful, 0 if no such file entry or -1 on error */ int mount_file_entry_get_parent_file_entry( mount_file_entry_t *file_entry, mount_file_entry_t **parent_file_entry, libcerror_error_t **error ) { static char *function = "mount_file_entry_get_parent_file_entry"; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( parent_file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid parent file entry.", function ); return( -1 ); } if( *parent_file_entry != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid parent file entry value already set.", function ); return( -1 ); } /* TODO implement libfsntfs_item_get_parent function */ return( 1 ); } /* Retrieves the creation date and time * On Windows the timestamp is an unsigned 64-bit FILETIME timestamp * otherwise the timestamp is a signed 64-bit POSIX date and time value in number of nanoseconds * Returns 1 if successful or -1 on error */ int mount_file_entry_get_creation_time( mount_file_entry_t *file_entry, uint64_t *creation_time, libcerror_error_t **error ) { static char *function = "mount_file_entry_get_creation_time"; uint64_t filetime = 0; #if !defined( WINAPI ) int64_t posix_time = 0; #endif if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( creation_time == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid creation time.", function ); return( -1 ); } if( libfsntfs_file_entry_get_creation_time( file_entry->fsntfs_file_entry, &filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve creation time from file entry.", function ); return( -1 ); } #if defined( WINAPI ) *creation_time = filetime; #else if( filetime != 0 ) { /* Convert the FILETIME timestamp into a POSIX nanoseconds timestamp */ posix_time = ( (int64_t) filetime - 116444736000000000L ) * 100; } *creation_time = (uint64_t) posix_time; #endif return( 1 ); } /* Retrieves the access date and time * On Windows the timestamp is an unsigned 64-bit FILETIME timestamp * otherwise the timestamp is a signed 64-bit POSIX date and time value in number of nanoseconds * Returns 1 if successful or -1 on error */ int mount_file_entry_get_access_time( mount_file_entry_t *file_entry, uint64_t *access_time, libcerror_error_t **error ) { static char *function = "mount_file_entry_get_access_time"; uint64_t filetime = 0; #if !defined( WINAPI ) int64_t posix_time = 0; #endif if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( access_time == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid access time.", function ); return( -1 ); } if( libfsntfs_file_entry_get_access_time( file_entry->fsntfs_file_entry, &filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve access time from file entry.", function ); return( -1 ); } #if defined( WINAPI ) *access_time = filetime; #else if( filetime != 0 ) { /* Convert the FILETIME timestamp into a POSIX nanoseconds timestamp */ posix_time = ( (int64_t) filetime - 116444736000000000L ) * 100; } *access_time = (uint64_t) posix_time; #endif return( 1 ); } /* Retrieves the modification date and time * On Windows the timestamp is an unsigned 64-bit FILETIME timestamp * otherwise the timestamp is a signed 64-bit POSIX date and time value in number of nanoseconds * Returns 1 if successful or -1 on error */ int mount_file_entry_get_modification_time( mount_file_entry_t *file_entry, uint64_t *modification_time, libcerror_error_t **error ) { static char *function = "mount_file_entry_get_modification_time"; uint64_t filetime = 0; #if !defined( WINAPI ) int64_t posix_time = 0; #endif if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( modification_time == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid modification time.", function ); return( -1 ); } if( libfsntfs_file_entry_get_modification_time( file_entry->fsntfs_file_entry, &filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve modification time from file entry.", function ); return( -1 ); } #if defined( WINAPI ) *modification_time = filetime; #else if( filetime != 0 ) { /* Convert the FILETIME timestamp into a POSIX nanoseconds timestamp */ posix_time = ( (int64_t) filetime - 116444736000000000L ) * 100; } *modification_time = (uint64_t) posix_time; #endif return( 1 ); } /* Retrieves the inode change date and time * On Windows the timestamp is an unsigned 64-bit FILETIME timestamp * otherwise the timestamp is a signed 64-bit POSIX date and time value in number of nanoseconds * Returns 1 if successful or -1 on error */ int mount_file_entry_get_inode_change_time( mount_file_entry_t *file_entry, uint64_t *inode_change_time, libcerror_error_t **error ) { static char *function = "mount_file_entry_get_inode_change_time"; uint64_t filetime = 0; #if !defined( WINAPI ) int64_t posix_time = 0; #endif if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( inode_change_time == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid inode change time.", function ); return( -1 ); } if( libfsntfs_file_entry_get_entry_modification_time( file_entry->fsntfs_file_entry, &filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry modification time from file entry.", function ); return( -1 ); } #if defined( WINAPI ) *inode_change_time = filetime; #else if( filetime != 0 ) { /* Convert the FILETIME timestamp into a POSIX nanoseconds timestamp */ posix_time = ( (int64_t) filetime - 116444736000000000L ) * 100; } *inode_change_time = (uint64_t) posix_time; #endif return( 1 ); } /* Retrieves the file mode * Returns 1 if successful or -1 on error */ int mount_file_entry_get_file_mode( mount_file_entry_t *file_entry, uint16_t *file_mode, libcerror_error_t **error ) { static char *function = "mount_file_entry_get_file_mode"; uint32_t file_attribute_flags = 0; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( file_mode == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file mode.", function ); return( -1 ); } if( libfsntfs_file_entry_get_file_attribute_flags( file_entry->fsntfs_file_entry, &file_attribute_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file attribute flags.", function ); return( -1 ); } result = libfsntfs_file_entry_has_directory_entries_index( file_entry->fsntfs_file_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if file entry has directory entries index.", function ); return( -1 ); } else if( result != 0 ) { *file_mode = S_IFDIR | 0555; } else { result = libfsntfs_file_entry_is_symbolic_link( file_entry->fsntfs_file_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if file entry is a symbolic link.", function ); return( -1 ); } else if( result != 0 ) { *file_mode = S_IFLNK | 0555; } else { *file_mode = S_IFREG | 0444; } } return( 1 ); } /* Retrieves the size of the name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int mount_file_entry_get_name_size( mount_file_entry_t *file_entry, size_t *string_size, libcerror_error_t **error ) { static char *function = "mount_file_entry_get_name_size"; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( string_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid string size.", function ); return( -1 ); } *string_size = file_entry->name_size; return( 1 ); } /* Retrieves the name * The size should include the end of string character * Returns 1 if successful or -1 on error */ int mount_file_entry_get_name( mount_file_entry_t *file_entry, system_character_t *string, size_t string_size, libcerror_error_t **error ) { static char *function = "mount_file_entry_get_name"; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( file_entry->name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid file entry - missing name.", function ); return( -1 ); } if( string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid string.", function ); return( -1 ); } if( string_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid string size value exceeds maximum.", function ); return( -1 ); } if( string_size < file_entry->name_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: invalid string size value too small.", function ); return( -1 ); } if( system_string_copy( string, file_entry->name, file_entry->name_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy name.", function ); return( -1 ); } string[ file_entry->name_size - 1 ] = 0; return( 1 ); } /* Retrieves the symbolic link target * The size should include the end of string character * Returns 1 if successful or -1 on error */ int mount_file_entry_get_symbolic_link_target( mount_file_entry_t *file_entry, system_character_t *string, size_t string_size, libcerror_error_t **error ) { static char *function = "mount_file_entry_get_symbolic_link_target"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_file_entry_get_utf16_symbolic_link_target( file_entry->fsntfs_file_entry, (uint16_t *) string, string_size, error ); #else result = libfsntfs_file_entry_get_utf8_symbolic_link_target( file_entry->fsntfs_file_entry, (uint8_t *) string, string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve symbolic link target string.", function ); return( -1 ); } /* TODO rewrite symbolic link target */ return( 1 ); } /* Retrieves the number of sub file entries * Returns 1 if successful or -1 on error */ int mount_file_entry_get_number_of_sub_file_entries( mount_file_entry_t *file_entry, int *number_of_sub_file_entries, libcerror_error_t **error ) { static char *function = "mount_file_entry_get_number_of_sub_file_entries"; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( libfsntfs_file_entry_get_number_of_sub_file_entries( file_entry->fsntfs_file_entry, number_of_sub_file_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of sub file entries.", function ); return( -1 ); } return( 1 ); } /* Retrieves the sub file entry for the specific index * Returns 1 if successful or -1 on error */ int mount_file_entry_get_sub_file_entry_by_index( mount_file_entry_t *file_entry, int sub_file_entry_index, mount_file_entry_t **sub_file_entry, libcerror_error_t **error ) { libfsntfs_file_entry_t *sub_fsntfs_file_entry = NULL; system_character_t *filename = NULL; static char *function = "mount_file_entry_get_sub_file_entry_by_index"; size_t filename_size = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( sub_file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid sub file entry.", function ); return( -1 ); } if( *sub_file_entry != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid sub file entry value already set.", function ); return( -1 ); } if( libfsntfs_file_entry_get_sub_file_entry_by_index( file_entry->fsntfs_file_entry, sub_file_entry_index, &sub_fsntfs_file_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve sub file entry: %d.", function, sub_file_entry_index ); goto on_error; } if( mount_file_system_get_filename_from_file_entry( file_entry->file_system, sub_fsntfs_file_entry, &filename, &filename_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve filename of sub file entry: %d.", function, sub_file_entry_index ); goto on_error; } if( mount_file_entry_initialize( sub_file_entry, file_entry->file_system, filename, filename_size - 1, sub_fsntfs_file_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize sub file entry: %d.", function, sub_file_entry_index ); goto on_error; } if( filename != NULL ) { memory_free( filename ); } return( 1 ); on_error: if( filename != NULL ) { memory_free( filename ); } if( sub_fsntfs_file_entry != NULL ) { libfsntfs_file_entry_free( &sub_fsntfs_file_entry, NULL ); } return( -1 ); } /* Reads data at a specific offset * Returns the number of bytes read or -1 on error */ ssize_t mount_file_entry_read_buffer_at_offset( mount_file_entry_t *file_entry, void *buffer, size_t buffer_size, off64_t offset, libcerror_error_t **error ) { static char *function = "mount_file_entry_read_buffer_at_offset"; size64_t file_size = 0; ssize_t read_count = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } /* TODO certain files have no default data stream such as $ObjId * for now work-around this */ if( libfsntfs_file_entry_get_size( file_entry->fsntfs_file_entry, &file_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size from file entry.", function ); return( -1 ); } if( file_size == 0 ) { return( 0 ); } read_count = libfsntfs_file_entry_read_buffer_at_offset( file_entry->fsntfs_file_entry, buffer, buffer_size, offset, error ); if( read_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read buffer at offset: %" PRIi64 " (0x%08" PRIx64 ") from file entry.", function, offset, offset ); return( -1 ); } return( read_count ); } /* Retrieves the size * Returns 1 if successful or -1 on error */ int mount_file_entry_get_size( mount_file_entry_t *file_entry, size64_t *size, libcerror_error_t **error ) { static char *function = "mount_file_entry_get_size"; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( libfsntfs_file_entry_get_size( file_entry->fsntfs_file_entry, size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size from file entry.", function ); return( -1 ); } return( 1 ); } ================================================ FILE: fsntfstools/mount_file_entry.h ================================================ /* * Mount file entry * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _MOUNT_FILE_ENTRY_H ) #define _MOUNT_FILE_ENTRY_H #include #include #include "fsntfstools_libcerror.h" #include "fsntfstools_libfsntfs.h" #include "mount_file_system.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct mount_file_entry mount_file_entry_t; struct mount_file_entry { /* The file system */ mount_file_system_t *file_system; /* The name */ system_character_t *name; /* The name size */ size_t name_size; /* The file entry */ libfsntfs_file_entry_t *fsntfs_file_entry; }; int mount_file_entry_initialize( mount_file_entry_t **file_entry, mount_file_system_t *file_system, const system_character_t *name, size_t name_length, libfsntfs_file_entry_t *fsntfs_file_entry, libcerror_error_t **error ); int mount_file_entry_free( mount_file_entry_t **file_entry, libcerror_error_t **error ); int mount_file_entry_get_parent_file_entry( mount_file_entry_t *file_entry, mount_file_entry_t **parent_file_entry, libcerror_error_t **error ); int mount_file_entry_get_creation_time( mount_file_entry_t *file_entry, uint64_t *creation_time, libcerror_error_t **error ); int mount_file_entry_get_access_time( mount_file_entry_t *file_entry, uint64_t *access_time, libcerror_error_t **error ); int mount_file_entry_get_modification_time( mount_file_entry_t *file_entry, uint64_t *modification_time, libcerror_error_t **error ); int mount_file_entry_get_inode_change_time( mount_file_entry_t *file_entry, uint64_t *inode_change_time, libcerror_error_t **error ); int mount_file_entry_get_file_mode( mount_file_entry_t *file_entry, uint16_t *file_mode, libcerror_error_t **error ); int mount_file_entry_get_name_size( mount_file_entry_t *file_entry, size_t *string_size, libcerror_error_t **error ); int mount_file_entry_get_name( mount_file_entry_t *file_entry, system_character_t *string, size_t string_size, libcerror_error_t **error ); int mount_file_entry_get_symbolic_link_target( mount_file_entry_t *file_entry, system_character_t *string, size_t string_size, libcerror_error_t **error ); int mount_file_entry_get_number_of_sub_file_entries( mount_file_entry_t *file_entry, int *number_of_sub_entries, libcerror_error_t **error ); int mount_file_entry_get_sub_file_entry_by_index( mount_file_entry_t *file_entry, int sub_file_entry_index, mount_file_entry_t **sub_file_entry, libcerror_error_t **error ); ssize_t mount_file_entry_read_buffer_at_offset( mount_file_entry_t *file_entry, void *buffer, size_t buffer_size, off64_t offset, libcerror_error_t **error ); int mount_file_entry_get_size( mount_file_entry_t *file_entry, size64_t *size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _MOUNT_FILE_ENTRY_H ) */ ================================================ FILE: fsntfstools/mount_file_system.c ================================================ /* * Mount file system * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #if defined( HAVE_SYS_STAT_H ) #include #endif #if defined( HAVE_SYS_TIME_H ) #include #endif #include #include "fsntfstools_libcerror.h" #include "fsntfstools_libfsntfs.h" #include "mount_file_system.h" #include "mount_path_string.h" /* Creates a file system * Make sure the value file_system is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int mount_file_system_initialize( mount_file_system_t **file_system, libcerror_error_t **error ) { #if defined( WINAPI ) FILETIME filetime; SYSTEMTIME systemtime; #elif defined( HAVE_CLOCK_GETTIME ) struct timespec time_structure; #endif static char *function = "mount_file_system_initialize"; #if defined( WINAPI ) DWORD error_code = 0; #else int64_t timestamp = 0; #endif if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } if( *file_system != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file system value already set.", function ); return( -1 ); } *file_system = memory_allocate_structure( mount_file_system_t ); if( *file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create file system.", function ); goto on_error; } if( memory_set( *file_system, 0, sizeof( mount_file_system_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear file system.", function ); memory_free( *file_system ); *file_system = NULL; return( -1 ); } #if defined( WINAPI ) if( memory_set( &systemtime, 0, sizeof( SYSTEMTIME ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear systemtime.", function ); goto on_error; } GetSystemTime( &systemtime ); if( SystemTimeToFileTime( &systemtime, &filetime ) == 0 ) { error_code = GetLastError(); libcerror_system_set_error( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, error_code, "%s: unable to retrieve FILETIME of current time.", function ); goto on_error; } ( *file_system )->mounted_timestamp = ( (uint64_t) filetime.dwHighDateTime << 32 ) | filetime.dwLowDateTime; #elif defined( HAVE_CLOCK_GETTIME ) if( clock_gettime( CLOCK_REALTIME, &time_structure ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve current time structure.", function ); goto on_error; } timestamp = ( (int64_t) time_structure.tv_sec * 1000000000 ) + time_structure.tv_nsec; ( *file_system )->mounted_timestamp = (uint64_t) timestamp; #else timestamp = (int64_t) time( NULL ); if( timestamp == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve current time.", function ); goto on_error; } timestamp *= 1000000000; ( *file_system )->mounted_timestamp = (uint64_t) timestamp; #endif /* defined( HAVE_CLOCK_GETTIME ) */ return( 1 ); on_error: if( *file_system != NULL ) { memory_free( *file_system ); *file_system = NULL; } return( -1 ); } /* Frees a file system * Returns 1 if successful or -1 on error */ int mount_file_system_free( mount_file_system_t **file_system, libcerror_error_t **error ) { static char *function = "mount_file_system_free"; int result = 1; if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } if( *file_system != NULL ) { memory_free( *file_system ); *file_system = NULL; } return( result ); } /* Signals the mount volume system to abort * Returns 1 if successful or -1 on error */ int mount_file_system_signal_abort( mount_file_system_t *file_system, libcerror_error_t **error ) { static char *function = "mount_file_system_signal_abort"; if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } if( file_system->fsntfs_volume != NULL ) { if( libfsntfs_volume_signal_abort( file_system->fsntfs_volume, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to signal volume to abort.", function ); return( -1 ); } } return( 1 ); } /* Sets the volume * Returns 1 if successful or -1 on error */ int mount_file_system_set_volume( mount_file_system_t *file_system, libfsntfs_volume_t *fsntfs_volume, libcerror_error_t **error ) { static char *function = "mount_file_system_set_volume"; if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } file_system->fsntfs_volume = fsntfs_volume; return( 1 ); } /* Retrieves the volume * Returns 1 if successful or -1 on error */ int mount_file_system_get_volume( mount_file_system_t *file_system, libfsntfs_volume_t **fsntfs_volume, libcerror_error_t **error ) { static char *function = "mount_file_system_get_volume"; if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } if( fsntfs_volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } *fsntfs_volume = file_system->fsntfs_volume; return( 1 ); } /* Retrieves the mounted timestamp * On Windows the timestamp is an unsigned 64-bit FILETIME timestamp * otherwise the timestamp is a signed 64-bit POSIX date and time value in number of nanoseconds * Returns 1 if successful or -1 on error */ int mount_file_system_get_mounted_timestamp( mount_file_system_t *file_system, uint64_t *mounted_timestamp, libcerror_error_t **error ) { static char *function = "mount_file_system_get_mounted_timestamp"; if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } if( mounted_timestamp == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid mounted timestamp.", function ); return( -1 ); } *mounted_timestamp = file_system->mounted_timestamp; return( 1 ); } /* Retrieves the file entry of a specific path * Returns 1 if successful, 0 if no such file entry or -1 on error */ int mount_file_system_get_file_entry_by_path( mount_file_system_t *file_system, const system_character_t *path, size_t path_length, libfsntfs_file_entry_t **fsntfs_file_entry, libcerror_error_t **error ) { system_character_t *file_entry_path = NULL; static char *function = "mount_file_system_get_file_entry_by_path"; size_t file_entry_path_length = 0; size_t file_entry_path_size = 0; int result = 0; if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } if( mount_path_string_copy_to_file_entry_path( path, path_length, &file_entry_path, &file_entry_path_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy path to file entry path.", function ); goto on_error; } if( file_entry_path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing file entry path.", function ); goto on_error; } /* Need to determine length here since size is based on the worst case */ file_entry_path_length = system_string_length( file_entry_path ); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_volume_get_file_entry_by_utf16_path( file_system->fsntfs_volume, (uint16_t *) file_entry_path, file_entry_path_length, fsntfs_file_entry, error ); #else result = libfsntfs_volume_get_file_entry_by_utf8_path( file_system->fsntfs_volume, (uint8_t *) file_entry_path, file_entry_path_length, fsntfs_file_entry, error ); #endif if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry ", function ); goto on_error; } memory_free( file_entry_path ); return( result ); on_error: if( file_entry_path != NULL ) { memory_free( file_entry_path ); } return( -1 ); } /* Retrieves the filename from an file entry * Returns 1 if successful or -1 on error */ int mount_file_system_get_filename_from_file_entry( mount_file_system_t *file_system, libfsntfs_file_entry_t *fsntfs_file_entry, system_character_t **filename, size_t *filename_size, libcerror_error_t **error ) { system_character_t *file_entry_name = NULL; static char *function = "mount_file_system_get_filename_from_file_entry"; size_t file_entry_name_size = 0; int result = 0; if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_file_entry_get_utf16_name_size( fsntfs_file_entry, &file_entry_name_size, error ); #else result = libfsntfs_file_entry_get_utf8_name_size( fsntfs_file_entry, &file_entry_name_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry name size.", function ); goto on_error; } if( ( file_entry_name_size == 0 ) || ( file_entry_name_size > SSIZE_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid file entry name size value out of bounds.", function ); goto on_error; } file_entry_name = system_string_allocate( file_entry_name_size ); if( file_entry_name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create file entry name string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_file_entry_get_utf16_name( fsntfs_file_entry, (uint16_t *) file_entry_name, file_entry_name_size, error ); #else result = libfsntfs_file_entry_get_utf8_name( fsntfs_file_entry, (uint8_t *) file_entry_name, file_entry_name_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry name.", function ); goto on_error; } if( mount_path_string_copy_from_file_entry_path( filename, filename_size, file_entry_name, file_entry_name_size - 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy filename from the file entry name.", function ); goto on_error; } memory_free( file_entry_name ); return( 1 ); on_error: if( file_entry_name != NULL ) { memory_free( file_entry_name ); } return( -1 ); } ================================================ FILE: fsntfstools/mount_file_system.h ================================================ /* * Mount file system * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _MOUNT_FILE_SYSTEM_H ) #define _MOUNT_FILE_SYSTEM_H #include #include #include "fsntfstools_libcerror.h" #include "fsntfstools_libfsntfs.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct mount_file_system mount_file_system_t; struct mount_file_system { /* The mounted timestamp */ uint64_t mounted_timestamp; /* The volume */ libfsntfs_volume_t *fsntfs_volume; }; int mount_file_system_initialize( mount_file_system_t **file_system, libcerror_error_t **error ); int mount_file_system_free( mount_file_system_t **file_system, libcerror_error_t **error ); int mount_file_system_signal_abort( mount_file_system_t *file_system, libcerror_error_t **error ); int mount_file_system_set_volume( mount_file_system_t *file_system, libfsntfs_volume_t *fsntfs_volume, libcerror_error_t **error ); int mount_file_system_get_volume( mount_file_system_t *file_system, libfsntfs_volume_t **fsntfs_volume, libcerror_error_t **error ); int mount_file_system_get_mounted_timestamp( mount_file_system_t *file_system, uint64_t *mounted_timestamp, libcerror_error_t **error ); int mount_file_system_get_file_entry_by_path( mount_file_system_t *file_system, const system_character_t *path, size_t path_length, libfsntfs_file_entry_t **fsntfs_file_entry, libcerror_error_t **error ); int mount_file_system_get_filename_from_file_entry( mount_file_system_t *file_system, libfsntfs_file_entry_t *fsntfs_file_entry, system_character_t **filename, size_t *filename_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _MOUNT_FILE_SYSTEM_H ) */ ================================================ FILE: fsntfstools/mount_fuse.c ================================================ /* * Mount tool fuse functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_ERRNO_H ) || defined( WINAPI ) #include #endif #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #if defined( HAVE_UNISTD_H ) #include #endif #include "fsntfstools_libcerror.h" #include "fsntfstools_libcnotify.h" #include "fsntfstools_libfsntfs.h" #include "fsntfstools_unused.h" #include "mount_fuse.h" #include "mount_handle.h" extern mount_handle_t *fsntfsmount_mount_handle; #if defined( HAVE_LIBFUSE ) || defined( HAVE_LIBFUSE3 ) || defined( HAVE_LIBOSXFUSE ) #if ( SIZEOF_OFF_T != 8 ) && ( SIZEOF_OFF_T != 4 ) #error Size of off_t not supported #endif /* Sets the values in a stat info structure * The time values are a signed 64-bit POSIX date and time value in number of nanoseconds * Returns 1 if successful or -1 on error */ int mount_fuse_set_stat_info( struct stat *stat_info, size64_t size, uint16_t file_mode, int64_t access_time, int64_t inode_change_time, int64_t modification_time, libcerror_error_t **error ) { static char *function = "mount_fuse_set_stat_info"; if( stat_info == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid stat info.", function ); return( -1 ); } #if SIZEOF_OFF_T <= 4 if( size > (size64_t) UINT32_MAX ) #else if( size > (size64_t) INT64_MAX ) #endif { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid size value out of bounds.", function ); return( -1 ); } stat_info->st_size = (off_t) size; stat_info->st_mode = file_mode; if( ( file_mode & 0x4000 ) != 0 ) { stat_info->st_nlink = 2; } else { stat_info->st_nlink = 1; } #if defined( HAVE_GETEUID ) stat_info->st_uid = geteuid(); #endif #if defined( HAVE_GETEGID ) stat_info->st_gid = getegid(); #endif stat_info->st_atime = access_time / 1000000000; stat_info->st_ctime = inode_change_time / 1000000000; stat_info->st_mtime = modification_time / 1000000000; #if defined( STAT_HAVE_NSEC ) stat_info->st_atime_nsec = access_time % 1000000000; stat_info->st_ctime_nsec = inode_change_time % 1000000000; stat_info->st_mtime_nsec = modification_time % 1000000000; #endif return( 1 ); } /* Fills a directory entry * Returns 1 if successful or -1 on error */ int mount_fuse_filldir( void *buffer, fuse_fill_dir_t filler, const char *name, struct stat *stat_info, mount_file_entry_t *file_entry, libcerror_error_t **error ) { static char *function = "mount_fuse_filldir"; size64_t file_size = 0; uint64_t access_time = 0; uint64_t inode_change_time = 0; uint64_t modification_time = 0; uint16_t file_mode = 0; if( filler == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid filler.", function ); return( -1 ); } if( file_entry != NULL ) { if( mount_file_entry_get_size( file_entry, &file_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry size.", function ); return( -1 ); } if( mount_file_entry_get_file_mode( file_entry, &file_mode, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file mode.", function ); return( -1 ); } if( mount_file_entry_get_access_time( file_entry, &access_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve access time.", function ); return( -1 ); } if( mount_file_entry_get_modification_time( file_entry, &modification_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve modification time.", function ); return( -1 ); } if( mount_file_entry_get_inode_change_time( file_entry, &inode_change_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve inode change time.", function ); return( -1 ); } } if( memory_set( stat_info, 0, sizeof( struct stat ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear stat info.", function ); return( -1 ); } if( mount_fuse_set_stat_info( stat_info, file_size, file_mode, (int64_t) access_time, (int64_t) inode_change_time, (int64_t) modification_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set stat info.", function ); return( -1 ); } #if defined( HAVE_LIBFUSE3 ) if( filler( buffer, name, stat_info, 0, 0 ) == 1 ) #else if( filler( buffer, name, stat_info, 0 ) == 1 ) #endif { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set directory entry.", function ); return( -1 ); } return( 1 ); } /* Opens a file or directory * Returns 0 if successful or a negative errno value otherwise */ int mount_fuse_open( const char *path, struct fuse_file_info *file_info ) { libcerror_error_t *error = NULL; static char *function = "mount_fuse_open"; int result = 0; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: %s\n", function, path ); } #endif if( path == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); result = -EINVAL; goto on_error; } if( file_info == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file information.", function ); result = -EINVAL; goto on_error; } if( file_info->fh != (uint64_t) NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file information - file handle already set.", function ); result = -EINVAL; goto on_error; } if( ( file_info->flags & 0x03 ) != O_RDONLY ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: write access currently not supported.", function ); result = -EACCES; goto on_error; } if( mount_handle_get_file_entry_by_path( fsntfsmount_mount_handle, path, (mount_file_entry_t **) &( file_info->fh ), &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry for path: %s.", function, path ); result = -ENOENT; goto on_error; } return( 0 ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } return( result ); } /* Reads a buffer of data at the specified offset * Returns number of bytes read if successful or a negative errno value otherwise */ int mount_fuse_read( const char *path, char *buffer, size_t size, off_t offset, struct fuse_file_info *file_info ) { libcerror_error_t *error = NULL; static char *function = "mount_fuse_read"; ssize_t read_count = 0; int result = 0; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: %s\n", function, path ); } #endif if( path == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); result = -EINVAL; goto on_error; } if( size > (size_t) INT_MAX ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid size value exceeds maximum.", function ); result = -EINVAL; goto on_error; } if( file_info == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file information.", function ); result = -EINVAL; goto on_error; } if( file_info->fh == (uint64_t) NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid file information - missing file handle.", function ); result = -EINVAL; goto on_error; } read_count = mount_file_entry_read_buffer_at_offset( (mount_file_entry_t *) file_info->fh, (void *) buffer, size, (off64_t) offset, &error ); if( read_count < 0 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read from file entry.", function ); result = -EIO; goto on_error; } return( (int) read_count ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } return( result ); } /* Releases a file entry * Returns 0 if successful or a negative errno value otherwise */ int mount_fuse_release( const char *path, struct fuse_file_info *file_info ) { libcerror_error_t *error = NULL; static char *function = "mount_fuse_release"; int result = 0; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: %s\n", function, path ); } #endif if( path == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); result = -EINVAL; goto on_error; } if( file_info == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file information.", function ); result = -EINVAL; goto on_error; } if( file_info->fh != (uint64_t) NULL ) { if( mount_file_entry_free( (mount_file_entry_t **) &( file_info->fh ), &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file entry.", function ); result = -ENOENT; goto on_error; } } return( 0 ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } return( result ); } /* Opens a directory * Returns 0 if successful or a negative errno value otherwise */ int mount_fuse_opendir( const char *path, struct fuse_file_info *file_info ) { libcerror_error_t *error = NULL; static char *function = "mount_fuse_opendir"; int result = 0; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: %s\n", function, path ); } #endif if( path == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); result = -EINVAL; goto on_error; } if( file_info == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file information.", function ); result = -EINVAL; goto on_error; } if( file_info->fh != (uint64_t) NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file information - file handle already set.", function ); result = -EINVAL; goto on_error; } if( mount_handle_get_file_entry_by_path( fsntfsmount_mount_handle, path, (mount_file_entry_t **) &( file_info->fh ), &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry for path: %s.", function, path ); result = -ENOENT; goto on_error; } return( 0 ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } return( result ); } /* Reads a directory * Returns 0 if successful or a negative errno value otherwise */ #if defined( HAVE_LIBFUSE3 ) int mount_fuse_readdir( const char *path, void *buffer, fuse_fill_dir_t filler, off_t offset FSNTFSTOOLS_ATTRIBUTE_UNUSED, struct fuse_file_info *file_info FSNTFSTOOLS_ATTRIBUTE_UNUSED, enum fuse_readdir_flags flags FSNTFSTOOLS_ATTRIBUTE_UNUSED ) #else int mount_fuse_readdir( const char *path, void *buffer, fuse_fill_dir_t filler, off_t offset FSNTFSTOOLS_ATTRIBUTE_UNUSED, struct fuse_file_info *file_info FSNTFSTOOLS_ATTRIBUTE_UNUSED ) #endif { struct stat *stat_info = NULL; libcerror_error_t *error = NULL; mount_file_entry_t *parent_file_entry = NULL; mount_file_entry_t *sub_file_entry = NULL; static char *function = "mount_fuse_readdir"; char *name = NULL; size_t name_size = 0; int number_of_sub_file_entries = 0; int result = 0; int sub_file_entry_index = 0; FSNTFSTOOLS_UNREFERENCED_PARAMETER( offset ) #if defined( HAVE_LIBFUSE3 ) FSNTFSTOOLS_UNREFERENCED_PARAMETER( flags ) #endif #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: %s\n", function, path ); } #endif if( path == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); result = -EINVAL; goto on_error; } if( file_info == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file information.", function ); result = -EINVAL; goto on_error; } if( file_info->fh == (uint64_t) NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid file information - missing file handle.", function ); result = -EINVAL; goto on_error; } stat_info = memory_allocate_structure( struct stat ); if( stat_info == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create stat info.", function ); result = errno; goto on_error; } if( mount_fuse_filldir( buffer, filler, ".", stat_info, (mount_file_entry_t *) file_info->fh, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set self directory entry.", function ); result = -EIO; goto on_error; } result = mount_file_entry_get_parent_file_entry( (mount_file_entry_t *) file_info->fh, &parent_file_entry, &error ); if( result == -1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve parent file entry.", function ); result = -EIO; goto on_error; } if( mount_fuse_filldir( buffer, filler, "..", stat_info, parent_file_entry, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set parent directory entry.", function ); result = -EIO; goto on_error; } if( mount_file_entry_free( &parent_file_entry, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free parent file entry.", function ); result = -EIO; goto on_error; } if( mount_file_entry_get_number_of_sub_file_entries( (mount_file_entry_t *) file_info->fh, &number_of_sub_file_entries, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of sub file entries.", function ); result = -EIO; goto on_error; } for( sub_file_entry_index = 0; sub_file_entry_index < number_of_sub_file_entries; sub_file_entry_index++ ) { if( mount_file_entry_get_sub_file_entry_by_index( (mount_file_entry_t *) file_info->fh, sub_file_entry_index, &sub_file_entry, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve sub file entry: %d.", function, sub_file_entry_index ); result = -EIO; goto on_error; } if( mount_file_entry_get_name_size( sub_file_entry, &name_size, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve sub file entry: %d name size.", function, sub_file_entry_index ); result = -EIO; goto on_error; } name = narrow_string_allocate( name_size ); if( name == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create sub file entry: %d name.", function ); result = -EIO; goto on_error; } if( mount_file_entry_get_name( sub_file_entry, name, name_size, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve sub file entry: %d name.", function, sub_file_entry_index ); result = -EIO; goto on_error; } if( mount_fuse_filldir( buffer, filler, name, stat_info, sub_file_entry, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set directory entry.", function ); result = -EIO; goto on_error; } memory_free( name ); name = NULL; if( mount_file_entry_free( &sub_file_entry, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free sub file entry: %d.", function, sub_file_entry_index ); result = -EIO; goto on_error; } } memory_free( stat_info ); return( 0 ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } if( name != NULL ) { memory_free( name ); } if( sub_file_entry != NULL ) { mount_file_entry_free( &sub_file_entry, NULL ); } if( parent_file_entry != NULL ) { mount_file_entry_free( &parent_file_entry, NULL ); } if( stat_info != NULL ) { memory_free( stat_info ); } return( result ); } /* Releases a directory entry * Returns 0 if successful or a negative errno value otherwise */ int mount_fuse_releasedir( const char *path, struct fuse_file_info *file_info ) { libcerror_error_t *error = NULL; static char *function = "mount_fuse_releasedir"; int result = 0; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: %s\n", function, path ); } #endif if( path == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); result = -EINVAL; goto on_error; } if( file_info == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file information.", function ); result = -EINVAL; goto on_error; } if( file_info->fh != (uint64_t) NULL ) { file_info->fh = (uint64_t) NULL; } return( 0 ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } return( result ); } /* Retrieves the file stat info * Returns 0 if successful or a negative errno value otherwise */ #if defined( HAVE_LIBFUSE3 ) int mount_fuse_getattr( const char *path, struct stat *stat_info, struct fuse_file_info *file_info FSNTFSTOOLS_ATTRIBUTE_UNUSED ) #else int mount_fuse_getattr( const char *path, struct stat *stat_info ) #endif { libcerror_error_t *error = NULL; mount_file_entry_t *file_entry = NULL; static char *function = "mount_fuse_getattr"; size64_t file_size = 0; uint64_t access_time = 0; uint64_t inode_change_time = 0; uint64_t modification_time = 0; uint16_t file_mode = 0; int result = 0; #if defined( HAVE_LIBFUSE3 ) FSNTFSTOOLS_UNREFERENCED_PARAMETER( file_info ) #endif #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: %s\n", function, path ); } #endif if( path == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); result = -EINVAL; goto on_error; } if( stat_info == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid stat info.", function ); result = -EINVAL; goto on_error; } if( memory_set( stat_info, 0, sizeof( struct stat ) ) == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear stat info.", function ); result = errno; goto on_error; } result = mount_handle_get_file_entry_by_path( fsntfsmount_mount_handle, path, &file_entry, &error ); if( result == -1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve value for: %s.", function, path ); result = -ENOENT; goto on_error; } else if( result == 0 ) { return( -ENOENT ); } if( mount_file_entry_get_size( file_entry, &file_size, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry size.", function ); result = -EIO; goto on_error; } if( mount_file_entry_get_file_mode( file_entry, &file_mode, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file mode.", function ); result = -EIO; goto on_error; } if( mount_file_entry_get_access_time( file_entry, &access_time, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve access time.", function ); result = -EIO; goto on_error; } if( mount_file_entry_get_modification_time( file_entry, &modification_time, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve modification time.", function ); result = -EIO; goto on_error; } if( mount_file_entry_get_inode_change_time( file_entry, &inode_change_time, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve inode change time.", function ); result = -EIO; goto on_error; } if( mount_fuse_set_stat_info( stat_info, file_size, file_mode, (int64_t) access_time, (int64_t) inode_change_time, (int64_t) modification_time, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set stat info.", function ); result = -EIO; goto on_error; } if( mount_file_entry_free( &file_entry, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file entry.", function ); result = -EIO; goto on_error; } return( 0 ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } if( file_entry != NULL ) { mount_file_entry_free( &file_entry, NULL ); } return( result ); } /* Reads the target of a symbolic link * Returns 0 if successful or a negative errno value otherwise */ int mount_fuse_readlink( const char *path, char *buffer, size_t size ) { libcerror_error_t *error = NULL; mount_file_entry_t *file_entry = NULL; static char *function = "mount_fuse_readlink"; int result = 0; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: %s\n", function, path ); } #endif if( path == NULL ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); result = -EINVAL; goto on_error; } result = mount_handle_get_file_entry_by_path( fsntfsmount_mount_handle, path, &file_entry, &error ); if( result == -1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve value for: %s.", function, path ); result = -ENOENT; goto on_error; } else if( result == 0 ) { return( -ENOENT ); } if( mount_file_entry_get_symbolic_link_target( file_entry, buffer, size, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve symbolic link target string.", function ); result = -EIO; goto on_error; } if( mount_file_entry_free( &file_entry, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file entry.", function ); result = -EIO; goto on_error; } return( 0 ); on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } if( file_entry != NULL ) { mount_file_entry_free( &file_entry, NULL ); } return( result ); } /* Cleans up when fuse is done */ void mount_fuse_destroy( void *private_data FSNTFSTOOLS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; static char *function = "mount_fuse_destroy"; FSNTFSTOOLS_UNREFERENCED_PARAMETER( private_data ) #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s\n", function ); } #endif if( fsntfsmount_mount_handle != NULL ) { if( mount_handle_free( &fsntfsmount_mount_handle, &error ) != 1 ) { libcerror_error_set( &error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free mount handle.", function ); goto on_error; } } return; on_error: if( error != NULL ) { libcnotify_print_error_backtrace( error ); libcerror_error_free( &error ); } return; } #endif /* defined( HAVE_LIBFUSE ) || defined( HAVE_LIBFUSE3 ) || defined( HAVE_LIBOSXFUSE ) */ ================================================ FILE: fsntfstools/mount_fuse.h ================================================ /* * Mount tool fuse functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _MOUNT_FUSE_H ) #define _MOUNT_FUSE_H #include #include #if defined( HAVE_LIBFUSE ) || defined( HAVE_LIBFUSE3 ) || defined( HAVE_LIBOSXFUSE ) #if !defined( FUSE_USE_VERSION ) && !defined( CYGFUSE ) /* Ensure FUSE_USE_VERSION is defined before including fuse.h */ #if defined( HAVE_LIBFUSE3 ) #define FUSE_USE_VERSION 30 #else #define FUSE_USE_VERSION 26 #endif #endif /* !defined( FUSE_USE_VERSION ) && !defined( CYGFUSE ) */ #if defined( HAVE_LIBFUSE ) #include #elif defined( HAVE_LIBFUSE3 ) #include #elif defined( HAVE_LIBOSXFUSE ) #include #endif #endif /* defined( HAVE_LIBFUSE ) || defined( HAVE_LIBFUSE3 ) || defined( HAVE_LIBOSXFUSE ) */ #include "fsntfstools_libcerror.h" #include "fsntfstools_libfsntfs.h" #include "mount_file_entry.h" #include "mount_handle.h" #if defined( __cplusplus ) extern "C" { #endif #if defined( HAVE_LIBFUSE ) || defined( HAVE_LIBFUSE3 ) || defined( HAVE_LIBOSXFUSE ) int mount_fuse_set_stat_info( struct stat *stat_info, size64_t size, uint16_t file_mode, int64_t access_time, int64_t inode_change_time, int64_t modification_time, libcerror_error_t **error ); int mount_fuse_filldir( void *buffer, fuse_fill_dir_t filler, const char *name, struct stat *stat_info, mount_file_entry_t *file_entry, libcerror_error_t **error ); int mount_fuse_open( const char *path, struct fuse_file_info *file_info ); int mount_fuse_read( const char *path, char *buffer, size_t size, off_t offset, struct fuse_file_info *file_info ); int mount_fuse_release( const char *path, struct fuse_file_info *file_info ); int mount_fuse_opendir( const char *path, struct fuse_file_info *file_info ); #if defined( HAVE_LIBFUSE3 ) int mount_fuse_readdir( const char *path, void *buffer, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *file_info, enum fuse_readdir_flags flags ); #else int mount_fuse_readdir( const char *path, void *buffer, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *file_info ); #endif int mount_fuse_releasedir( const char *path, struct fuse_file_info *file_info ); #if defined( HAVE_LIBFUSE3 ) int mount_fuse_getattr( const char *path, struct stat *stat_info, struct fuse_file_info *file_info ); #else int mount_fuse_getattr( const char *path, struct stat *stat_info ); #endif int mount_fuse_readlink( const char *path, char *buffer, size_t size ); void mount_fuse_destroy( void *private_data ); #endif /* defined( HAVE_LIBFUSE ) || defined( HAVE_LIBFUSE3 ) || defined( HAVE_LIBOSXFUSE ) */ #if defined( __cplusplus ) } #endif #endif /* !defined( _MOUNT_FUSE_H ) */ ================================================ FILE: fsntfstools/mount_handle.c ================================================ /* * Mount handle * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include "fsntfstools_libbfio.h" #include "fsntfstools_libcerror.h" #include "fsntfstools_libcpath.h" #include "fsntfstools_libfsntfs.h" #include "mount_file_entry.h" #include "mount_file_system.h" #include "mount_handle.h" #if !defined( LIBFSNTFS_HAVE_BFIO ) extern \ int libfsntfs_volume_open_file_io_handle( libfsntfs_volume_t *volume, libbfio_handle_t *file_io_handle, int access_flags, libfsntfs_error_t **error ); #endif /* !defined( LIBFSNTFS_HAVE_BFIO ) */ /* Copies a string of a decimal value to a 64-bit value * Returns 1 if successful or -1 on error */ int mount_handle_system_string_copy_from_64_bit_in_decimal( const system_character_t *string, size_t string_size, uint64_t *value_64bit, libcerror_error_t **error ) { static char *function = "mount_handle_system_string_copy_from_64_bit_in_decimal"; system_character_t character_value = 0; size_t string_index = 0; uint8_t maximum_string_index = 20; int8_t sign = 1; if( string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid string.", function ); return( -1 ); } if( string_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid string size value exceeds maximum.", function ); return( -1 ); } if( value_64bit == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid value 64-bit.", function ); return( -1 ); } *value_64bit = 0; if( string[ string_index ] == (system_character_t) '-' ) { string_index++; maximum_string_index++; sign = -1; } else if( string[ string_index ] == (system_character_t) '+' ) { string_index++; maximum_string_index++; } while( string_index < string_size ) { if( string[ string_index ] == 0 ) { break; } if( string_index > (size_t) maximum_string_index ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_LARGE, "%s: string too large.", function ); return( -1 ); } *value_64bit *= 10; if( ( string[ string_index ] >= (system_character_t) '0' ) && ( string[ string_index ] <= (system_character_t) '9' ) ) { character_value = (system_character_t) ( string[ string_index ] - (system_character_t) '0' ); } else { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported character value: %" PRIc_SYSTEM " at index: %d.", function, string[ string_index ], string_index ); return( -1 ); } *value_64bit += character_value; string_index++; } if( sign == -1 ) { *value_64bit *= (uint64_t) -1; } return( 1 ); } /* Creates a mount handle * Make sure the value mount_handle is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int mount_handle_initialize( mount_handle_t **mount_handle, libcerror_error_t **error ) { static char *function = "mount_handle_initialize"; if( mount_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid mount handle.", function ); return( -1 ); } if( *mount_handle != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid mount handle value already set.", function ); return( -1 ); } *mount_handle = memory_allocate_structure( mount_handle_t ); if( *mount_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create mount handle.", function ); goto on_error; } if( memory_set( *mount_handle, 0, sizeof( mount_handle_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear mount handle.", function ); goto on_error; } if( mount_file_system_initialize( &( ( *mount_handle )->file_system ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize file system.", function ); goto on_error; } return( 1 ); on_error: if( *mount_handle != NULL ) { memory_free( *mount_handle ); *mount_handle = NULL; } return( -1 ); } /* Frees a mount handle * Returns 1 if successful or -1 on error */ int mount_handle_free( mount_handle_t **mount_handle, libcerror_error_t **error ) { static char *function = "mount_handle_free"; int result = 1; if( mount_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid mount handle.", function ); return( -1 ); } if( *mount_handle != NULL ) { if( mount_file_system_free( &( ( *mount_handle )->file_system ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file system.", function ); result = -1; } memory_free( *mount_handle ); *mount_handle = NULL; } return( result ); } /* Signals the mount handle to abort * Returns 1 if successful or -1 on error */ int mount_handle_signal_abort( mount_handle_t *mount_handle, libcerror_error_t **error ) { static char *function = "mount_handle_signal_abort"; if( mount_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid mount handle.", function ); return( -1 ); } if( mount_file_system_signal_abort( mount_handle->file_system, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to signal file system to abort.", function ); return( -1 ); } return( 1 ); } /* Sets the volume offset * Returns 1 if successful or -1 on error */ int mount_handle_set_offset( mount_handle_t *mount_handle, const system_character_t *string, libcerror_error_t **error ) { static char *function = "mount_handle_set_offset"; size_t string_length = 0; uint64_t value_64bit = 0; if( mount_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid mount handle.", function ); return( -1 ); } string_length = system_string_length( string ); if( mount_handle_system_string_copy_from_64_bit_in_decimal( string, string_length + 1, &value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy string to 64-bit decimal.", function ); return( -1 ); } mount_handle->volume_offset = (off64_t) value_64bit; return( 1 ); } /* Opens the mount handle * Returns 1 if successful, 0 if not or -1 on error */ int mount_handle_open( mount_handle_t *mount_handle, const system_character_t *filename, libcerror_error_t **error ) { libbfio_handle_t *file_io_handle = NULL; libfsntfs_volume_t *fsntfs_volume = NULL; static char *function = "mount_handle_open"; size_t filename_length = 0; int result = 0; if( mount_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid mount handle.", function ); return( -1 ); } if( filename == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid filename.", function ); return( -1 ); } filename_length = system_string_length( filename ); if( libbfio_file_range_initialize( &file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize file IO handle.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) if( libbfio_file_range_set_name_wide( file_io_handle, filename, filename_length, error ) != 1 ) #else if( libbfio_file_range_set_name( file_io_handle, filename, filename_length, error ) != 1 ) #endif { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to set file range name.", function ); goto on_error; } if( libbfio_file_range_set( file_io_handle, mount_handle->volume_offset, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to set file range offset.", function ); goto on_error; } if( libfsntfs_volume_initialize( &fsntfs_volume, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize volume.", function ); goto on_error; } result = libfsntfs_volume_open_file_io_handle( fsntfs_volume, file_io_handle, LIBFSNTFS_OPEN_READ, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open volume.", function ); goto on_error; } if( mount_file_system_set_volume( mount_handle->file_system, fsntfs_volume, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set volume in file system.", function ); goto on_error; } mount_handle->file_io_handle = file_io_handle; return( 1 ); on_error: if( fsntfs_volume != NULL ) { libfsntfs_volume_free( &fsntfs_volume, NULL ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } return( -1 ); } /* Closes the mount handle * Returns the 0 if succesful or -1 on error */ int mount_handle_close( mount_handle_t *mount_handle, libcerror_error_t **error ) { libfsntfs_volume_t *fsntfs_volume = NULL; static char *function = "mount_handle_close"; if( mount_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid mount handle.", function ); return( -1 ); } if( mount_file_system_get_volume( mount_handle->file_system, &fsntfs_volume, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve volume from file system.", function ); goto on_error; } if( mount_file_system_set_volume( mount_handle->file_system, NULL, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set volume in file system.", function ); fsntfs_volume = NULL; goto on_error; } if( libfsntfs_volume_close( fsntfs_volume, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close volume.", function ); goto on_error; } if( libfsntfs_volume_free( &fsntfs_volume, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free volume.", function ); goto on_error; } if( libbfio_handle_close( mount_handle->file_io_handle, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to close file IO handle.", function ); goto on_error; } if( libbfio_handle_free( &( mount_handle->file_io_handle ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file IO handle.", function ); goto on_error; } return( 0 ); on_error: if( fsntfs_volume != NULL ) { libfsntfs_volume_free( &fsntfs_volume, NULL ); } return( -1 ); } /* Retrieves a file entry for a specific path * Returns 1 if successful, 0 if no such file entry or -1 on error */ int mount_handle_get_file_entry_by_path( mount_handle_t *mount_handle, const system_character_t *path, mount_file_entry_t **file_entry, libcerror_error_t **error ) { libfsntfs_file_entry_t *fsntfs_file_entry = NULL; const system_character_t *filename = NULL; static char *function = "mount_handle_get_file_entry_by_path"; size_t filename_length = 0; size_t path_index = 0; size_t path_length = 0; int result = 0; if( mount_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid mount handle.", function ); return( -1 ); } if( path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); return( -1 ); } path_length = system_string_length( path ); if( path_length == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid path length value out of bounds.", function ); goto on_error; } if( ( path_length >= 2 ) && ( path[ path_length - 1 ] == LIBCPATH_SEPARATOR ) ) { path_length--; } path_index = path_length; while( path_index > 0 ) { if( path[ path_index ] == LIBCPATH_SEPARATOR ) { break; } path_index--; } /* Ignore the name of the root item */ if( path_length == 0 ) { filename = _SYSTEM_STRING( "" ); filename_length = 0; } else { filename = &( path[ path_index + 1 ] ); filename_length = path_length - ( path_index + 1 ); } result = mount_file_system_get_file_entry_by_path( mount_handle->file_system, path, path_length, &fsntfs_file_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file entry.", function ); goto on_error; } else if( result != 0 ) { if( mount_file_entry_initialize( file_entry, mount_handle->file_system, filename, filename_length, fsntfs_file_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize file entry.", function ); goto on_error; } } return( result ); on_error: if( fsntfs_file_entry != NULL ) { libfsntfs_file_entry_free( &fsntfs_file_entry, NULL ); } return( -1 ); } ================================================ FILE: fsntfstools/mount_handle.h ================================================ /* * Mount handle * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _MOUNT_HANDLE_H ) #define _MOUNT_HANDLE_H #include #include #include #include "fsntfstools_libbfio.h" #include "fsntfstools_libcerror.h" #include "fsntfstools_libfsntfs.h" #include "mount_file_entry.h" #include "mount_file_system.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct mount_handle mount_handle_t; struct mount_handle { /* The file system */ mount_file_system_t *file_system; /* The volume offset */ off64_t volume_offset; /* The libbfio file IO handle */ libbfio_handle_t *file_io_handle; /* The notification output stream */ FILE *notify_stream; }; int mount_handle_system_string_copy_from_64_bit_in_decimal( const system_character_t *string, size_t string_size, uint64_t *value_64bit, libcerror_error_t **error ); int mount_handle_initialize( mount_handle_t **mount_handle, libcerror_error_t **error ); int mount_handle_free( mount_handle_t **mount_handle, libcerror_error_t **error ); int mount_handle_signal_abort( mount_handle_t *mount_handle, libcerror_error_t **error ); int mount_handle_set_offset( mount_handle_t *mount_handle, const system_character_t *string, libcerror_error_t **error ); int mount_handle_open( mount_handle_t *mount_handle, const system_character_t *filename, libcerror_error_t **error ); int mount_handle_close( mount_handle_t *mount_handle, libcerror_error_t **error ); int mount_handle_get_file_entry_by_path( mount_handle_t *mount_handle, const system_character_t *path, mount_file_entry_t **file_entry, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _MOUNT_HANDLE_H ) */ ================================================ FILE: fsntfstools/mount_path_string.c ================================================ /* * Mount path string functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include "fsntfstools_libcerror.h" #include "fsntfstools_libcpath.h" #include "fsntfstools_libfsntfs.h" #include "fsntfstools_libuna.h" #include "mount_path_string.h" #if defined( WINAPI ) #define ESCAPE_CHARACTER (system_character_t) '^' #else #define ESCAPE_CHARACTER (system_character_t) '\\' #endif /* Copies a string of a hexadecimal value to a 32-bit value * Returns 1 if successful or -1 on error */ int mount_path_string_copy_hexadecimal_to_integer_32_bit( const system_character_t *string, size_t string_size, uint32_t *value_32bit, libcerror_error_t **error ) { static char *function = "mount_path_string_copy_hexadecimal_to_integer_32_bit"; system_character_t character_value = 0; size_t string_index = 0; uint32_t safe_value_32bit = 0; if( string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid string.", function ); return( -1 ); } if( ( string_size == 0 ) || ( string_size > (size_t) SSIZE_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid string size value out of bounds.", function ); return( -1 ); } if( value_32bit == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid value 32-bit.", function ); return( -1 ); } for( string_index = 0; string_index < string_size; string_index++ ) { safe_value_32bit <<= 4; character_value = string[ string_index ]; if( ( character_value >= (system_character_t) '0' ) && ( character_value <= (system_character_t) '9' ) ) { safe_value_32bit |= (uint8_t) ( character_value - (system_character_t) '0' ); } #if defined( WINAPI ) else if( ( character_value >= (system_character_t) 'A' ) && ( character_value <= (system_character_t) 'F' ) ) { safe_value_32bit |= (uint8_t) ( character_value - (system_character_t) 'A' + 10 ); } #endif else if( ( character_value >= (system_character_t) 'a' ) && ( character_value <= (system_character_t) 'f' ) ) { safe_value_32bit |= (uint8_t) ( character_value - (system_character_t) 'a' + 10 ); } else { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported character value: %" PRIc_SYSTEM " at index: %d.", function, character_value, string_index ); return( -1 ); } } *value_32bit = safe_value_32bit; return( 1 ); } /* Copies the path from a comparable file entry path * Returns 1 if successful or -1 on error */ int mount_path_string_copy_from_file_entry_path( system_character_t **path, size_t *path_size, const system_character_t *file_entry_path, size_t file_entry_path_length, libcerror_error_t **error ) { system_character_t *safe_path = NULL; static char *function = "mount_path_string_copy_from_file_entry_path"; libuna_unicode_character_t unicode_character = 0; size_t file_entry_path_index = 0; size_t path_index = 0; size_t safe_path_size = 0; ssize_t print_count = 0; int result = 0; if( path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); return( -1 ); } if( path_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path size.", function ); return( -1 ); } if( file_entry_path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry path.", function ); return( -1 ); } if( ( file_entry_path_length == 0 ) || ( file_entry_path_length > (size_t) ( SSIZE_MAX - 1 ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid file entry path length value out of bounds.", function ); return( -1 ); } /* Note that there is a worst-case of a 1 to 10 ratio for each escaped character. */ if( file_entry_path_length > (size_t) ( ( SSIZE_MAX - 1 ) / ( sizeof( system_character_t ) * 10 ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid value string length value exceeds maximum.", function ); return( -1 ); } safe_path_size = ( file_entry_path_length * 10 ) + 1; safe_path = system_string_allocate( safe_path_size ); if( safe_path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create path.", function ); goto on_error; } while( file_entry_path_index < file_entry_path_length ) { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libuna_unicode_character_copy_from_utf16( &unicode_character, (libuna_utf16_character_t *) file_entry_path, file_entry_path_length, &file_entry_path_index, error ); #else result = libuna_unicode_character_copy_from_utf8( &unicode_character, (libuna_utf8_character_t *) file_entry_path, file_entry_path_length, &file_entry_path_index, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_INPUT_FAILED, "%s: unable to copy Unicode character from file entry path.", function ); goto on_error; } if( unicode_character == 0 ) { break; } /* Replace: * control characters ([U+1-U+1f, U+7f-U+9f]) by \x## (or ^x## on Windows) * * On Windows replace: * \ by ^x5c * <, >, :, ", /, |, ?, * by ^x## * * On other platforms replace: * / by \x2f */ if( ( unicode_character <= 0x1f ) || ( unicode_character == (libuna_unicode_character_t) LIBCPATH_SEPARATOR ) #if defined( WINAPI ) || ( unicode_character == (libuna_unicode_character_t) '<' ) || ( unicode_character == (libuna_unicode_character_t) '>' ) || ( unicode_character == (libuna_unicode_character_t) ':' ) || ( unicode_character == (libuna_unicode_character_t) '"' ) || ( unicode_character == (libuna_unicode_character_t) '/' ) || ( unicode_character == (libuna_unicode_character_t) '|' ) || ( unicode_character == (libuna_unicode_character_t) '?' ) || ( unicode_character == (libuna_unicode_character_t) '*' ) #endif || ( ( unicode_character >= 0x7f ) && ( unicode_character <= 0x9f ) ) ) { print_count = system_string_sprintf( &( safe_path[ path_index ] ), safe_path_size - path_index, _SYSTEM_STRING( "%" PRIc_SYSTEM "x%02" PRIx32 "" ), ESCAPE_CHARACTER, unicode_character ); if( print_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_INPUT_FAILED, "%s: unable to copy escaped Unicode character to path.", function ); goto on_error; } path_index += print_count; } /* Replace by \U######## (or ^U######## on Windows): * Unicode surrogate characters ([U+d800-U+dfff]) * Undefined Unicode characters ([ * U+fdd0-U+fddf, U+fffe-U+ffff, U+1fffe-U+1ffff, U+2fffe-U+2ffff, * U+3fffe-U+3ffff, U+4fffe-U+4ffff, U+5fffe-U+5ffff, U+6fffe-U+6ffff, * U+7fffe-U+7ffff, U+8fffe-U+8ffff, U+9fffe-U+9ffff, U+afffe-U+affff, * U+bfffe-U+bffff, U+cfffe-U+cffff, U+dfffe-U+dffff, U+efffe-U+effff, * U+ffffe-U+fffff, U+10fffe-U+ffffffff]) * Observed unprintable characters ([ * U+2028, U+2029, U+e000, U+f8ff, U+f0000, U+ffffd, U+100000, U+10fffd]) */ else if( ( ( unicode_character >= 0x00002028UL ) && ( unicode_character <= 0x00002029UL ) ) || ( ( unicode_character >= 0x0000d800UL ) && ( unicode_character <= 0x0000dfffUL ) ) || ( unicode_character == 0x0000e000UL ) || ( unicode_character == 0x0000f8ffUL ) || ( ( unicode_character >= 0x0000fdd0UL ) && ( unicode_character <= 0x0000fddfUL ) ) || ( ( ( unicode_character & 0x0000ffffUL ) >= 0x0000fffeUL ) && ( ( unicode_character & 0x0000ffffUL ) <= 0x0000ffffUL ) ) || ( unicode_character == 0x000f0000UL ) || ( unicode_character == 0x000ffffdUL ) || ( unicode_character == 0x00100000UL ) || ( unicode_character >= 0x0010fffdUL ) ) { print_count = system_string_sprintf( &( safe_path[ path_index ] ), safe_path_size - path_index, _SYSTEM_STRING( "%" PRIc_SYSTEM "U%08" PRIx32 "" ), ESCAPE_CHARACTER, unicode_character ); if( print_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_INPUT_FAILED, "%s: unable to copy escaped Unicode character to path.", function ); goto on_error; } path_index += print_count; } /* Replace: * Escape character (\) by \\ (or ^ by ^^ on Windows) */ else if( unicode_character == (libuna_unicode_character_t) ESCAPE_CHARACTER ) { if( ( path_index + 2 ) > safe_path_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid path index value out of bounds.", function ); goto on_error; } safe_path[ path_index++ ] = ESCAPE_CHARACTER; safe_path[ path_index++ ] = (system_character_t) unicode_character; } else { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libuna_unicode_character_copy_to_utf16( unicode_character, (libuna_utf16_character_t *) safe_path, safe_path_size, &path_index, error ); #else result = libuna_unicode_character_copy_to_utf8( unicode_character, (libuna_utf8_character_t *) safe_path, safe_path_size, &path_index, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_INPUT_FAILED, "%s: unable to copy Unicode character to path.", function ); goto on_error; } } } if( path_index >= safe_path_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid path index value out of bounds.", function ); goto on_error; } safe_path[ path_index ] = 0; *path = safe_path; *path_size = safe_path_size; return( 1 ); on_error: if( safe_path != NULL ) { memory_free( safe_path ); } return( -1 ); } /* Copies the path to a comparable file entry path * Returns 1 if successful or -1 on error */ int mount_path_string_copy_to_file_entry_path( const system_character_t *path, size_t path_length, system_character_t **file_entry_path, size_t *file_entry_path_size, libcerror_error_t **error ) { system_character_t *safe_file_entry_path = NULL; static char *function = "mount_path_string_copy_to_file_entry_path"; libuna_unicode_character_t unicode_character = 0; system_character_t character = 0; size_t file_entry_path_index = 0; size_t path_index = 0; size_t safe_file_entry_path_size = 0; uint32_t escaped_value = 0; int result = 0; if( path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); return( -1 ); } if( ( path_length == 0 ) || ( path_length > (size_t) ( SSIZE_MAX - 1 ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid string size value out of bounds.", function ); return( -1 ); } if( file_entry_path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry path.", function ); return( -1 ); } if( file_entry_path_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry path size.", function ); return( -1 ); } if( path[ 0 ] != (system_character_t) LIBCPATH_SEPARATOR ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported path - path is not absolute.", function ); return( -1 ); } safe_file_entry_path_size = path_length + 1; if( safe_file_entry_path_size > (size_t) ( SSIZE_MAX / sizeof( system_character_t ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid file entry path size value exceeds maximum.", function ); goto on_error; } safe_file_entry_path = system_string_allocate( safe_file_entry_path_size ); if( safe_file_entry_path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create file entry path.", function ); goto on_error; } while( path_index < path_length ) { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libuna_unicode_character_copy_from_utf16( &unicode_character, (libuna_utf16_character_t *) path, path_length, &path_index, error ); #else result = libuna_unicode_character_copy_from_utf8( &unicode_character, (libuna_utf8_character_t *) path, path_length, &path_index, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_INPUT_FAILED, "%s: unable to copy Unicode character from path.", function ); goto on_error; } if( unicode_character == (libuna_unicode_character_t) LIBCPATH_SEPARATOR ) { unicode_character = (libuna_unicode_character_t) LIBFSNTFS_SEPARATOR; } else if( unicode_character == (libuna_unicode_character_t) ESCAPE_CHARACTER ) { if( ( path_index + 1 ) > path_length ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid path index value out of bounds.", function ); goto on_error; } character = path[ path_index++ ]; /* Replace: * \x## (or ^x## on Windows) by control characters ([U+1-U+1f, U+7f-U+9f]) * * On Windows replace: * ^^ by ^ * ^x5c by \ * ^x## by <, >, :, ", /, |, ?, * * * On other platforms replace: * \\ by \ * \x2f by / */ if( character == ESCAPE_CHARACTER ) { escaped_value = (uint32_t) character; } #if defined( WINAPI ) else if( ( character == (system_character_t) 'X' ) || ( character == (system_character_t) 'x' ) ) #else else if( character == (system_character_t) 'x' ) #endif { if( ( path_index + 2 ) > path_length ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid path index value out of bounds.", function ); goto on_error; } if( mount_path_string_copy_hexadecimal_to_integer_32_bit( &( path[ path_index ] ), 2, &escaped_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy string of hexadecimal to 32-bit integer.", function ); goto on_error; } path_index += 2; if( ( ( escaped_value >= 0x01 ) && ( escaped_value <= 0x1f ) ) || ( escaped_value == (uint32_t) LIBCPATH_SEPARATOR ) #if defined( WINAPI ) || ( escaped_value == (uint32_t) '<' ) || ( escaped_value == (uint32_t) '>' ) || ( escaped_value == (uint32_t) ':' ) || ( escaped_value == (uint32_t) '"' ) || ( escaped_value == (uint32_t) '/' ) || ( escaped_value == (uint32_t) '|' ) || ( escaped_value == (uint32_t) '?' ) || ( escaped_value == (uint32_t) '*' ) #endif || ( ( escaped_value >= 0x7f ) && ( escaped_value <= 0x9f ) ) ) { } else { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid escaped character: %" PRIc_SYSTEM "x%02" PRIx32 " value out of bounds.", function, ESCAPE_CHARACTER, escaped_value ); goto on_error; } } /* Replace \U######## (or ^U######## on Windows) with: * Unicode surrogate characters ([U+d800-U+dfff]) * Undefined Unicode characters ([ * U+fdd0-U+fddf, U+fffe-U+ffff, U+1fffe-U+1ffff, U+2fffe-U+2ffff, * U+3fffe-U+3ffff, U+4fffe-U+4ffff, U+5fffe-U+5ffff, U+6fffe-U+6ffff, * U+7fffe-U+7ffff, U+8fffe-U+8ffff, U+9fffe-U+9ffff, U+afffe-U+affff, * U+bfffe-U+bffff, U+cfffe-U+cffff, U+dfffe-U+dffff, U+efffe-U+effff, * U+ffffe-U+fffff, U+10fffe-U+ffffffff]) * Observed unprintable characters ([ * U+2028, U+2029, U+e000, U+f8ff, U+f0000, U+ffffd, U+100000, U+10fffd]) */ #if defined( WINAPI ) else if( ( character == (system_character_t) 'U' ) || ( character == (system_character_t) 'u' ) ) #else else if( character == (system_character_t) 'U' ) #endif { if( ( path_index + 8 ) > path_length ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid path index value out of bounds.", function ); goto on_error; } if( mount_path_string_copy_hexadecimal_to_integer_32_bit( &( path[ path_index ] ), 8, &escaped_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy string of hexadecimal to 32-bit integer.", function ); goto on_error; } path_index += 8; if( ( ( escaped_value >= 0x00002028UL ) && ( escaped_value <= 0x00002029UL ) ) || ( ( escaped_value >= 0x0000d800UL ) && ( escaped_value <= 0x0000dfffUL ) ) || ( escaped_value == 0x0000e000UL ) || ( escaped_value == 0x0000f8ffUL ) || ( ( escaped_value >= 0x0000fdd0UL ) && ( escaped_value <= 0x0000fddfUL ) ) || ( ( ( escaped_value & 0x0000ffffUL ) >= 0x0000fffeUL ) && ( ( escaped_value & 0x0000ffffUL ) <= 0x0000ffffUL ) ) || ( escaped_value == 0x000f0000UL ) || ( escaped_value == 0x000ffffdUL ) || ( escaped_value == 0x00100000UL ) || ( escaped_value >= 0x0010fffdUL ) ) { } else { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid escaped character: %" PRIc_SYSTEM "U%08" PRIx32 " value out of bounds.", function, ESCAPE_CHARACTER, escaped_value ); goto on_error; } } else { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported path - invalid character: %" PRIc_SYSTEM " after escape character: %" PRIc_SYSTEM ".", function, character, ESCAPE_CHARACTER ); goto on_error; } unicode_character = (libuna_unicode_character_t) escaped_value; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libuna_unicode_character_copy_to_utf16( unicode_character, (libuna_utf16_character_t *) safe_file_entry_path, safe_file_entry_path_size, &file_entry_path_index, error ); #else result = libuna_unicode_character_copy_to_utf8( unicode_character, (libuna_utf8_character_t *) safe_file_entry_path, safe_file_entry_path_size, &file_entry_path_index, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_INPUT_FAILED, "%s: unable to copy Unicode character to file entry path.", function ); goto on_error; } } if( file_entry_path_index >= safe_file_entry_path_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid file entry path index value out of bounds.", function ); goto on_error; } safe_file_entry_path[ file_entry_path_index ] = 0; *file_entry_path = safe_file_entry_path; *file_entry_path_size = safe_file_entry_path_size; return( 1 ); on_error: if( safe_file_entry_path != NULL ) { memory_free( safe_file_entry_path ); } return( -1 ); } ================================================ FILE: fsntfstools/mount_path_string.h ================================================ /* * Mount path string functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _MOUNT_PATH_STRING_H ) #define _MOUNT_PATH_STRING_H #include #include #include "fsntfstools_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif int mount_path_string_copy_hexadecimal_to_integer_32_bit( const system_character_t *string, size_t string_size, uint32_t *value_32bit, libcerror_error_t **error ); int mount_path_string_copy_from_file_entry_path( system_character_t **path, size_t *path_size, const system_character_t *file_entry_path, size_t file_entry_path_length, libcerror_error_t **error ); int mount_path_string_copy_to_file_entry_path( const system_character_t *path, size_t path_length, system_character_t **file_entry_path, size_t *file_entry_path_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _MOUNT_PATH_STRING_H ) */ ================================================ FILE: fsntfstools/path_string.c ================================================ /* * Path string functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include "fsntfstools_libcerror.h" #include "fsntfstools_libfsntfs.h" #include "fsntfstools_libuna.h" #include "path_string.h" /* Copies a string of a hexadecimal value to a 32-bit value * Returns 1 if successful or -1 on error */ int path_string_copy_hexadecimal_to_integer_32_bit( const system_character_t *string, size_t string_size, uint32_t *value_32bit, libcerror_error_t **error ) { static char *function = "path_string_copy_hexadecimal_to_integer_32_bit"; system_character_t character_value = 0; size_t string_index = 0; uint32_t safe_value_32bit = 0; if( string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid string.", function ); return( -1 ); } if( ( string_size == 0 ) || ( string_size > (size_t) SSIZE_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid string size value out of bounds.", function ); return( -1 ); } if( value_32bit == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid value 32-bit.", function ); return( -1 ); } for( string_index = 0; string_index < string_size; string_index++ ) { safe_value_32bit <<= 4; character_value = string[ string_index ]; if( ( character_value >= (system_character_t) '0' ) && ( character_value <= (system_character_t) '9' ) ) { safe_value_32bit |= (uint8_t) ( character_value - (system_character_t) '0' ); } else if( ( character_value >= (system_character_t) 'a' ) && ( character_value <= (system_character_t) 'f' ) ) { safe_value_32bit |= (uint8_t) ( character_value - (system_character_t) 'a' + 10 ); } else { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported character value: %" PRIc_SYSTEM " at index: %d.", function, character_value, string_index ); return( -1 ); } } *value_32bit = safe_value_32bit; return( 1 ); } /* Copies the path from a comparable file entry path * Returns 1 if successful or -1 on error */ int path_string_copy_from_file_entry_path( system_character_t **path, size_t *path_size, const system_character_t *file_entry_path, size_t file_entry_path_length, libcerror_error_t **error ) { system_character_t *safe_path = NULL; static char *function = "path_string_copy_from_file_entry_path"; libuna_unicode_character_t unicode_character = 0; system_character_t escape_character = 0; size_t file_entry_path_index = 0; size_t path_index = 0; size_t safe_path_size = 0; int print_count = 0; int result = 0; if( path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); return( -1 ); } if( path_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path size.", function ); return( -1 ); } if( file_entry_path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry path.", function ); return( -1 ); } if( ( file_entry_path_length == 0 ) || ( file_entry_path_length > (size_t) ( SSIZE_MAX - 1 ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid file entry path length value out of bounds.", function ); return( -1 ); } /* Note that there is a worst-case of a 1 to 10 ratio for each escaped character. */ if( file_entry_path_length > (size_t) ( ( SSIZE_MAX - 1 ) / ( sizeof( system_character_t ) * 10 ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid value string length value exceeds maximum.", function ); return( -1 ); } safe_path_size = ( file_entry_path_length * 10 ) + 1; safe_path = system_string_allocate( safe_path_size ); if( safe_path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create path.", function ); goto on_error; } escape_character = (system_character_t) '\\'; /* Using UCS-2 or RFC 2279 UTF-8 to support unpaired UTF-16 surrogates */ while( file_entry_path_index < file_entry_path_length ) { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libuna_unicode_character_copy_from_ucs2( &unicode_character, (libuna_utf16_character_t *) file_entry_path, file_entry_path_length, &file_entry_path_index, error ); #else result = libuna_unicode_character_copy_from_utf8_rfc2279( &unicode_character, (libuna_utf8_character_t *) file_entry_path, file_entry_path_length, &file_entry_path_index, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_INPUT_FAILED, "%s: unable to copy Unicode character from value string.", function ); goto on_error; } /* Replace by \x##: * Control characters ([U+0-U+1f, U+7f-U+9f]) */ if( ( unicode_character <= 0x1f ) || ( ( unicode_character >= 0x7f ) && ( unicode_character <= 0x9f ) ) ) { print_count = system_string_sprintf( &( safe_path[ path_index ] ), safe_path_size - path_index, _SYSTEM_STRING( "%" PRIc_SYSTEM "x%02" PRIx32 "" ), escape_character, unicode_character ); if( print_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_INPUT_FAILED, "%s: unable to copy escaped Unicode character to path.", function ); goto on_error; } path_index += print_count; } /* Replace by \U########: * Unicode surrogate characters ([U+d800-U+dfff]) * Undefined Unicode characters ([ * U+fdd0-U+fddf, U+fffe-U+ffff, U+1fffe-U+1ffff, U+2fffe-U+2ffff, * U+3fffe-U+3ffff, U+4fffe-U+4ffff, U+5fffe-U+5ffff, U+6fffe-U+6ffff, * U+7fffe-U+7ffff, U+8fffe-U+8ffff, U+9fffe-U+9ffff, U+afffe-U+affff, * U+bfffe-U+bffff, U+cfffe-U+cffff, U+dfffe-U+dffff, U+efffe-U+effff, * U+ffffe-U+fffff, U+10fffe-U+ffffffff]) * Observed unprintable characters ([ * U+2028, U+2029, U+e000, U+f8ff, U+f0000, U+ffffd, U+100000, U+10fffd]) */ else if( ( ( unicode_character >= 0x00002028UL ) && ( unicode_character <= 0x00002029UL ) ) || ( ( unicode_character >= 0x0000d800UL ) && ( unicode_character <= 0x0000dfffUL ) ) || ( unicode_character == 0x0000e000UL ) || ( unicode_character == 0x0000f8ffUL ) || ( ( unicode_character >= 0x0000fdd0UL ) && ( unicode_character <= 0x0000fddfUL ) ) || ( ( ( unicode_character & 0x0000ffffUL ) >= 0x0000fffeUL ) && ( ( unicode_character & 0x0000ffffUL ) <= 0x0000ffffUL ) ) || ( unicode_character == 0x000f0000UL ) || ( unicode_character == 0x000ffffdUL ) || ( unicode_character == 0x00100000UL ) || ( unicode_character >= 0x0010fffdUL ) ) { print_count = system_string_sprintf( &( safe_path[ path_index ] ), safe_path_size - path_index, _SYSTEM_STRING( "%" PRIc_SYSTEM "U%08" PRIx32 "" ), escape_character, unicode_character ); if( print_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_INPUT_FAILED, "%s: unable to copy escaped Unicode character to path.", function ); goto on_error; } path_index += print_count; } /* Replace: * Escape character (\) by \\ */ else if( unicode_character == (libuna_unicode_character_t) escape_character ) { if( ( path_index + 2 ) > safe_path_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid path index value out of bounds.", function ); goto on_error; } safe_path[ path_index++ ] = escape_character; safe_path[ path_index++ ] = (system_character_t) unicode_character; } else { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libuna_unicode_character_copy_to_utf16( unicode_character, (libuna_utf16_character_t *) safe_path, safe_path_size, &path_index, error ); #else result = libuna_unicode_character_copy_to_utf8( unicode_character, (libuna_utf8_character_t *) safe_path, safe_path_size, &path_index, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_INPUT_FAILED, "%s: unable to copy Unicode character to path.", function ); goto on_error; } } } safe_path[ path_index ] = 0; *path = safe_path; *path_size = safe_path_size; return( 1 ); on_error: if( safe_path != NULL ) { memory_free( safe_path ); } return( -1 ); } /* Copies the path to a comparable file entry path * Returns 1 if successful or -1 on error */ int path_string_copy_to_file_entry_path( const system_character_t *path, size_t path_length, system_character_t path_segment_separator, system_character_t **file_entry_path, size_t *file_entry_path_size, libcerror_error_t **error ) { system_character_t *safe_file_entry_path = NULL; static char *function = "path_string_copy_to_file_entry_path"; libuna_unicode_character_t unicode_character = 0; system_character_t character = 0; system_character_t escape_character = 0; size_t file_entry_path_index = 0; size_t path_index = 0; size_t safe_file_entry_path_size = 0; uint32_t escaped_value = 0; int result = 0; if( path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path.", function ); return( -1 ); } if( ( path_length == 0 ) || ( path_length > (size_t) ( SSIZE_MAX - 1 ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid path length value out of bounds.", function ); return( -1 ); } if( file_entry_path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry path.", function ); return( -1 ); } if( file_entry_path_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry path size.", function ); return( -1 ); } safe_file_entry_path_size = path_length + 1; if( safe_file_entry_path_size > (size_t) ( SSIZE_MAX / sizeof( system_character_t ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid file entry path size value exceeds maximum.", function ); goto on_error; } safe_file_entry_path = system_string_allocate( safe_file_entry_path_size ); if( safe_file_entry_path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create file entry path.", function ); goto on_error; } escape_character = (system_character_t) '\\'; while( path_index < path_length ) { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libuna_unicode_character_copy_from_utf16( &unicode_character, (libuna_utf16_character_t *) path, path_length, &path_index, error ); #else result = libuna_unicode_character_copy_from_utf8( &unicode_character, (libuna_utf8_character_t *) path, path_length, &path_index, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_INPUT_FAILED, "%s: unable to copy Unicode character from path.", function ); goto on_error; } if( unicode_character == (libuna_unicode_character_t) escape_character ) { if( ( path_index + 1 ) > path_length ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid path index value out of bounds.", function ); goto on_error; } character = path[ path_index++ ]; /* Replace: * \\ by \ */ if( character == escape_character ) { escaped_value = (uint32_t) character; } /* Replace \x## by: * Control characters ([U+0-U+1f, U+7f-U+9f]) */ else if( character == (system_character_t) 'x' ) { if( ( path_index + 2 ) > path_length ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid path - insufficient characters for escaped character value.", function ); goto on_error; } if( path_string_copy_hexadecimal_to_integer_32_bit( &( path[ path_index ] ), 2, &escaped_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy string of hexadecimal to 32-bit integer.", function ); goto on_error; } path_index += 2; if( ( ( escaped_value >= 0x01 ) && ( escaped_value <= 0x1f ) ) || ( ( escaped_value >= 0x7f ) && ( escaped_value <= 0x9f ) ) ) { } else { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid escaped character: %" PRIc_SYSTEM "x%02" PRIx32 " value out of bounds.", function, escape_character, escaped_value ); goto on_error; } } /* Replace \U######## with: * Unicode surrogate characters ([U+d800-U+dfff]) * Undefined Unicode characters ([ * U+fdd0-U+fddf, U+fffe-U+ffff, U+1fffe-U+1ffff, U+2fffe-U+2ffff, * U+3fffe-U+3ffff, U+4fffe-U+4ffff, U+5fffe-U+5ffff, U+6fffe-U+6ffff, * U+7fffe-U+7ffff, U+8fffe-U+8ffff, U+9fffe-U+9ffff, U+afffe-U+affff, * U+bfffe-U+bffff, U+cfffe-U+cffff, U+dfffe-U+dffff, U+efffe-U+effff, * U+ffffe-U+fffff, U+10fffe-U+ffffffff]) * Observed unprintable characters ([ * U+2028, U+2029, U+e000, U+f8ff, U+f0000, U+ffffd, U+100000, U+10fffd]) */ else if( character == (system_character_t) 'U' ) { if( ( path_index + 8 ) > path_length ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid path - insufficient characters for escaped character value.", function ); goto on_error; } if( path_string_copy_hexadecimal_to_integer_32_bit( &( path[ path_index ] ), 8, &escaped_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy string of hexadecimal to 32-bit integer.", function ); goto on_error; } path_index += 8; if( ( ( escaped_value >= 0x00002028UL ) && ( escaped_value <= 0x00002029UL ) ) || ( ( escaped_value >= 0x0000d800UL ) && ( escaped_value <= 0x0000dfffUL ) ) || ( escaped_value == 0x0000e000UL ) || ( escaped_value == 0x0000f8ffUL ) || ( ( escaped_value >= 0x0000fdd0UL ) && ( escaped_value <= 0x0000fddfUL ) ) || ( ( ( escaped_value & 0x0000ffffUL ) >= 0x0000fffeUL ) && ( ( escaped_value & 0x0000ffffUL ) <= 0x0000ffffUL ) ) || ( escaped_value == 0x000f0000UL ) || ( escaped_value == 0x000ffffdUL ) || ( escaped_value == 0x00100000UL ) || ( escaped_value >= 0x0010fffdUL ) ) { } else { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid escaped character: %" PRIc_SYSTEM "U%08" PRIx32 " value out of bounds.", function, escape_character, escaped_value ); goto on_error; } } else { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported path - invalid character: %" PRIc_SYSTEM " after escape character: %" PRIc_SYSTEM ".", function, character, escape_character ); goto on_error; } unicode_character = (libuna_unicode_character_t) escaped_value; } if( unicode_character == (libuna_unicode_character_t) path_segment_separator ) { unicode_character = (libuna_unicode_character_t) LIBFSNTFS_SEPARATOR; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libuna_unicode_character_copy_to_ucs2( unicode_character, (libuna_utf16_character_t *) safe_file_entry_path, safe_file_entry_path_size, &file_entry_path_index, error ); #else result = libuna_unicode_character_copy_to_utf8_rfc2279( unicode_character, (libuna_utf8_character_t *) safe_file_entry_path, safe_file_entry_path_size, &file_entry_path_index, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_INPUT_FAILED, "%s: unable to copy Unicode character to file entry path.", function ); goto on_error; } } if( file_entry_path_index >= safe_file_entry_path_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid file entry path index value out of bounds.", function ); goto on_error; } safe_file_entry_path[ file_entry_path_index ] = 0; *file_entry_path = safe_file_entry_path; *file_entry_path_size = safe_file_entry_path_size; return( 1 ); on_error: if( safe_file_entry_path != NULL ) { memory_free( safe_file_entry_path ); } return( -1 ); } ================================================ FILE: fsntfstools/path_string.h ================================================ /* * Path string functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PATH_STRING_H ) #define _PATH_STRING_H #include #include #include "fsntfstools_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif int path_string_copy_hexadecimal_to_integer_32_bit( const system_character_t *string, size_t string_size, uint32_t *value_32bit, libcerror_error_t **error ); int path_string_copy_from_file_entry_path( system_character_t **path, size_t *path_size, const system_character_t *file_entry_path, size_t file_entry_path_length, libcerror_error_t **error ); int path_string_copy_to_file_entry_path( const system_character_t *path, size_t path_length, system_character_t path_segment_separator, system_character_t **file_entry_path, size_t *file_entry_path_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PATH_STRING_H ) */ ================================================ FILE: include/Makefile.am ================================================ include_HEADERS = \ libfsntfs.h pkginclude_HEADERS = \ libfsntfs/codepage.h \ libfsntfs/definitions.h \ libfsntfs/error.h \ libfsntfs/extern.h \ libfsntfs/features.h \ libfsntfs/types.h EXTRA_DIST = \ libfsntfs.h.in \ libfsntfs/definitions.h.in \ libfsntfs/features.h.in \ libfsntfs/types.h.in DISTCLEANFILES = \ libfsntfs.h \ libfsntfs/definitions.h \ libfsntfs/features.h \ libfsntfs/types.h \ Makefile \ Makefile.in ================================================ FILE: include/libfsntfs/codepage.h ================================================ /* * Codepage definitions for libfsntfs * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_CODEPAGE_H ) #define _LIBFSNTFS_CODEPAGE_H #include #if defined( __cplusplus ) extern "C" { #endif /* The codepage definitions */ enum LIBFSNTFS_CODEPAGES { LIBFSNTFS_CODEPAGE_ASCII = 20127, LIBFSNTFS_CODEPAGE_ISO_8859_1 = 28591, LIBFSNTFS_CODEPAGE_ISO_8859_2 = 28592, LIBFSNTFS_CODEPAGE_ISO_8859_3 = 28593, LIBFSNTFS_CODEPAGE_ISO_8859_4 = 28594, LIBFSNTFS_CODEPAGE_ISO_8859_5 = 28595, LIBFSNTFS_CODEPAGE_ISO_8859_6 = 28596, LIBFSNTFS_CODEPAGE_ISO_8859_7 = 28597, LIBFSNTFS_CODEPAGE_ISO_8859_8 = 28598, LIBFSNTFS_CODEPAGE_ISO_8859_9 = 28599, LIBFSNTFS_CODEPAGE_ISO_8859_10 = 28600, LIBFSNTFS_CODEPAGE_ISO_8859_11 = 28601, LIBFSNTFS_CODEPAGE_ISO_8859_13 = 28603, LIBFSNTFS_CODEPAGE_ISO_8859_14 = 28604, LIBFSNTFS_CODEPAGE_ISO_8859_15 = 28605, LIBFSNTFS_CODEPAGE_ISO_8859_16 = 28606, LIBFSNTFS_CODEPAGE_KOI8_R = 20866, LIBFSNTFS_CODEPAGE_KOI8_U = 21866, LIBFSNTFS_CODEPAGE_WINDOWS_874 = 874, LIBFSNTFS_CODEPAGE_WINDOWS_932 = 932, LIBFSNTFS_CODEPAGE_WINDOWS_936 = 936, LIBFSNTFS_CODEPAGE_WINDOWS_949 = 949, LIBFSNTFS_CODEPAGE_WINDOWS_950 = 950, LIBFSNTFS_CODEPAGE_WINDOWS_1250 = 1250, LIBFSNTFS_CODEPAGE_WINDOWS_1251 = 1251, LIBFSNTFS_CODEPAGE_WINDOWS_1252 = 1252, LIBFSNTFS_CODEPAGE_WINDOWS_1253 = 1253, LIBFSNTFS_CODEPAGE_WINDOWS_1254 = 1254, LIBFSNTFS_CODEPAGE_WINDOWS_1255 = 1255, LIBFSNTFS_CODEPAGE_WINDOWS_1256 = 1256, LIBFSNTFS_CODEPAGE_WINDOWS_1257 = 1257, LIBFSNTFS_CODEPAGE_WINDOWS_1258 = 1258 }; #define LIBFSNTFS_CODEPAGE_US_ASCII LIBFSNTFS_CODEPAGE_ASCII #define LIBFSNTFS_CODEPAGE_ISO_WESTERN_EUROPEAN LIBFSNTFS_CODEPAGE_ISO_8859_1 #define LIBFSNTFS_CODEPAGE_ISO_CENTRAL_EUROPEAN LIBFSNTFS_CODEPAGE_ISO_8859_2 #define LIBFSNTFS_CODEPAGE_ISO_SOUTH_EUROPEAN LIBFSNTFS_CODEPAGE_ISO_8859_3 #define LIBFSNTFS_CODEPAGE_ISO_NORTH_EUROPEAN LIBFSNTFS_CODEPAGE_ISO_8859_4 #define LIBFSNTFS_CODEPAGE_ISO_CYRILLIC LIBFSNTFS_CODEPAGE_ISO_8859_5 #define LIBFSNTFS_CODEPAGE_ISO_ARABIC LIBFSNTFS_CODEPAGE_ISO_8859_6 #define LIBFSNTFS_CODEPAGE_ISO_GREEK LIBFSNTFS_CODEPAGE_ISO_8859_7 #define LIBFSNTFS_CODEPAGE_ISO_HEBREW LIBFSNTFS_CODEPAGE_ISO_8859_8 #define LIBFSNTFS_CODEPAGE_ISO_TURKISH LIBFSNTFS_CODEPAGE_ISO_8859_9 #define LIBFSNTFS_CODEPAGE_ISO_NORDIC LIBFSNTFS_CODEPAGE_ISO_8859_10 #define LIBFSNTFS_CODEPAGE_ISO_THAI LIBFSNTFS_CODEPAGE_ISO_8859_11 #define LIBFSNTFS_CODEPAGE_ISO_BALTIC LIBFSNTFS_CODEPAGE_ISO_8859_13 #define LIBFSNTFS_CODEPAGE_ISO_CELTIC LIBFSNTFS_CODEPAGE_ISO_8859_14 #define LIBFSNTFS_CODEPAGE_ISO_LATIN_1 LIBFSNTFS_CODEPAGE_ISO_8859_1 #define LIBFSNTFS_CODEPAGE_ISO_LATIN_2 LIBFSNTFS_CODEPAGE_ISO_8859_2 #define LIBFSNTFS_CODEPAGE_ISO_LATIN_3 LIBFSNTFS_CODEPAGE_ISO_8859_3 #define LIBFSNTFS_CODEPAGE_ISO_LATIN_4 LIBFSNTFS_CODEPAGE_ISO_8859_4 #define LIBFSNTFS_CODEPAGE_ISO_LATIN_5 LIBFSNTFS_CODEPAGE_ISO_8859_9 #define LIBFSNTFS_CODEPAGE_ISO_LATIN_6 LIBFSNTFS_CODEPAGE_ISO_8859_10 #define LIBFSNTFS_CODEPAGE_ISO_LATIN_7 LIBFSNTFS_CODEPAGE_ISO_8859_13 #define LIBFSNTFS_CODEPAGE_ISO_LATIN_8 LIBFSNTFS_CODEPAGE_ISO_8859_14 #define LIBFSNTFS_CODEPAGE_ISO_LATIN_9 LIBFSNTFS_CODEPAGE_ISO_8859_15 #define LIBFSNTFS_CODEPAGE_ISO_LATIN_10 LIBFSNTFS_CODEPAGE_ISO_8859_16 #define LIBFSNTFS_CODEPAGE_KOI8_RUSSIAN LIBFSNTFS_CODEPAGE_KOI8_R #define LIBFSNTFS_CODEPAGE_KOI8_UKRAINIAN LIBFSNTFS_CODEPAGE_KOI8_U #define LIBFSNTFS_CODEPAGE_WINDOWS_THAI LIBFSNTFS_CODEPAGE_WINDOWS_874 #define LIBFSNTFS_CODEPAGE_WINDOWS_JAPANESE LIBFSNTFS_CODEPAGE_WINDOWS_932 #define LIBFSNTFS_CODEPAGE_WINDOWS_CHINESE_SIMPLIFIED LIBFSNTFS_CODEPAGE_WINDOWS_936 #define LIBFSNTFS_CODEPAGE_WINDOWS_KOREAN LIBFSNTFS_CODEPAGE_WINDOWS_949 #define LIBFSNTFS_CODEPAGE_WINDOWS_CHINESE_TRADITIONAL LIBFSNTFS_CODEPAGE_WINDOWS_950 #define LIBFSNTFS_CODEPAGE_WINDOWS_CENTRAL_EUROPEAN LIBFSNTFS_CODEPAGE_WINDOWS_1250 #define LIBFSNTFS_CODEPAGE_WINDOWS_CYRILLIC LIBFSNTFS_CODEPAGE_WINDOWS_1251 #define LIBFSNTFS_CODEPAGE_WINDOWS_WESTERN_EUROPEAN LIBFSNTFS_CODEPAGE_WINDOWS_1252 #define LIBFSNTFS_CODEPAGE_WINDOWS_GREEK LIBFSNTFS_CODEPAGE_WINDOWS_1253 #define LIBFSNTFS_CODEPAGE_WINDOWS_TURKISH LIBFSNTFS_CODEPAGE_WINDOWS_1254 #define LIBFSNTFS_CODEPAGE_WINDOWS_HEBREW LIBFSNTFS_CODEPAGE_WINDOWS_1255 #define LIBFSNTFS_CODEPAGE_WINDOWS_ARABIC LIBFSNTFS_CODEPAGE_WINDOWS_1256 #define LIBFSNTFS_CODEPAGE_WINDOWS_BALTIC LIBFSNTFS_CODEPAGE_WINDOWS_1257 #define LIBFSNTFS_CODEPAGE_WINDOWS_VIETNAMESE LIBFSNTFS_CODEPAGE_WINDOWS_1258 #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_CODEPAGE_H ) */ ================================================ FILE: include/libfsntfs/definitions.h.in ================================================ /* * Definitions for libfsntfs * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_DEFINITIONS_H ) #define _LIBFSNTFS_DEFINITIONS_H #include #define LIBFSNTFS_VERSION @VERSION@ /* The version string */ #define LIBFSNTFS_VERSION_STRING "@VERSION@" /* The file access * bit 1 set to 1 for read access * bit 2 set to 1 for write access * bit 3-8 not used */ enum LIBFSNTFS_ACCESS_FLAGS { LIBFSNTFS_ACCESS_FLAG_READ = 0x01, /* Reserved: not supported yet */ LIBFSNTFS_ACCESS_FLAG_WRITE = 0x02 }; /* The file access macros */ #define LIBFSNTFS_OPEN_READ ( LIBFSNTFS_ACCESS_FLAG_READ ) /* Reserved: not supported yet */ #define LIBFSNTFS_OPEN_WRITE ( LIBFSNTFS_ACCESS_FLAG_WRITE ) /* Reserved: not supported yet */ #define LIBFSNTFS_OPEN_READ_WRITE ( LIBFSNTFS_ACCESS_FLAG_READ | LIBFSNTFS_ACCESS_FLAG_WRITE ) /* The path segment separator */ #define LIBFSNTFS_SEPARATOR '\\' /* The file attribute flags */ enum LIBFSNTFS_FILE_ATTRIBUTE_FLAGS { LIBFSNTFS_FILE_ATTRIBUTE_FLAG_READ_ONLY = 0x00000001UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_HIDDEN = 0x00000002UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_SYSTEM = 0x00000004UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_DIRECTORY = 0x00000010UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_ARCHIVE = 0x00000020UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_DEVICE = 0x00000040UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_NORMAL = 0x00000080UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_TEMPORARY = 0x00000100UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_SPARSE_FILE = 0x00000200UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_REPARSE_POINT = 0x00000400UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_COMPRESSED = 0x00000800UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_OFFLINE = 0x00001000UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_NOT_CONTENT_INDEXED = 0x00002000UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_ENCRYPTED = 0x00004000UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_VIRTUAL = 0x00010000UL }; /* The attribute types */ enum LIBFSNTFS_ATTRIBUTE_TYPES { LIBFSNTFS_ATTRIBUTE_TYPE_UNUSED = 0x00000000UL, LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION = 0x00000010UL, LIBFSNTFS_ATTRIBUTE_TYPE_ATTRIBUTE_LIST = 0x00000020UL, LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME = 0x00000030UL, LIBFSNTFS_ATTRIBUTE_TYPE_OBJECT_IDENTIFIER = 0x00000040UL, LIBFSNTFS_ATTRIBUTE_TYPE_SECURITY_DESCRIPTOR = 0x00000050UL, LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME = 0x00000060UL, LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_INFORMATION = 0x00000070UL, LIBFSNTFS_ATTRIBUTE_TYPE_DATA = 0x00000080UL, LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ROOT = 0x00000090UL, LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ALLOCATION = 0x000000a0UL, LIBFSNTFS_ATTRIBUTE_TYPE_BITMAP = 0x000000b0UL, LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT = 0x000000c0UL, LIBFSNTFS_ATTRIBUTE_TYPE_EXTENDED_INFORMATION = 0x000000d0UL, LIBFSNTFS_ATTRIBUTE_TYPE_EXTENDED = 0x000000e0UL, LIBFSNTFS_ATTRIBUTE_TYPE_PROPERTY_SET = 0x000000f0UL, LIBFSNTFS_ATTRIBUTE_TYPE_LOGGED_UTILITY_STREAM = 0x00000100UL, LIBFSNTFS_ATTRIBUTE_TYPE_END_OF_ATTRIBUTES = 0xffffffffUL }; /* The extent flag definitions */ enum LIBFSNTFS_EXTENT_FLAGS { /* The extent is sparse */ LIBFSNTFS_EXTENT_FLAG_IS_SPARSE = 0x00000001UL, /* The extent is compressed */ LIBFSNTFS_EXTENT_FLAG_IS_COMPRESSED = 0x00000002UL }; #endif /* !defined( _LIBFSNTFS_DEFINITIONS_H ) */ ================================================ FILE: include/libfsntfs/error.h ================================================ /* * The error code definitions for libfsntfs * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_ERROR_H ) #define _LIBFSNTFS_ERROR_H #include /* External error type definition hides internal structure */ typedef intptr_t libfsntfs_error_t; /* The error domains */ enum LIBFSNTFS_ERROR_DOMAINS { LIBFSNTFS_ERROR_DOMAIN_ARGUMENTS = (int) 'a', LIBFSNTFS_ERROR_DOMAIN_CONVERSION = (int) 'c', LIBFSNTFS_ERROR_DOMAIN_COMPRESSION = (int) 'C', LIBFSNTFS_ERROR_DOMAIN_IO = (int) 'I', LIBFSNTFS_ERROR_DOMAIN_INPUT = (int) 'i', LIBFSNTFS_ERROR_DOMAIN_MEMORY = (int) 'm', LIBFSNTFS_ERROR_DOMAIN_OUTPUT = (int) 'o', LIBFSNTFS_ERROR_DOMAIN_RUNTIME = (int) 'r' }; /* The argument error codes * to signify errors regarding arguments passed to a function */ enum LIBFSNTFS_ARGUMENT_ERROR { LIBFSNTFS_ARGUMENT_ERROR_GENERIC = 0, /* The argument contains an invalid value */ LIBFSNTFS_ARGUMENT_ERROR_INVALID_VALUE = 1, /* The argument contains a value less than zero */ LIBFSNTFS_ARGUMENT_ERROR_VALUE_LESS_THAN_ZERO = 2, /* The argument contains a value zero or less */ LIBFSNTFS_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS = 3, /* The argument contains a value that exceeds the maximum * for the specific type */ LIBFSNTFS_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM = 4, /* The argument contains a value that is too small */ LIBFSNTFS_ARGUMENT_ERROR_VALUE_TOO_SMALL = 5, /* The argument contains a value that is too large */ LIBFSNTFS_ARGUMENT_ERROR_VALUE_TOO_LARGE = 6, /* The argument contains a value that is out of bounds */ LIBFSNTFS_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS = 7, /* The argument contains a value that is not supported */ LIBFSNTFS_ARGUMENT_ERROR_UNSUPPORTED_VALUE = 8, /* The argument contains a value that conficts with another argument */ LIBFSNTFS_ARGUMENT_ERROR_CONFLICTING_VALUE = 9 }; /* The conversion error codes * to signify errors regarding conversions */ enum LIBFSNTFS_CONVERSION_ERROR { LIBFSNTFS_CONVERSION_ERROR_GENERIC = 0, /* The conversion failed on the input */ LIBFSNTFS_CONVERSION_ERROR_INPUT_FAILED = 1, /* The conversion failed on the output */ LIBFSNTFS_CONVERSION_ERROR_OUTPUT_FAILED = 2 }; /* The compression error codes * to signify errors regarding compression */ enum LIBFSNTFS_COMPRESSION_ERROR { LIBFSNTFS_COMPRESSION_ERROR_GENERIC = 0, /* The compression failed */ LIBFSNTFS_COMPRESSION_ERROR_COMPRESS_FAILED = 1, /* The decompression failed */ LIBFSNTFS_COMPRESSION_ERROR_DECOMPRESS_FAILED = 2 }; /* The input/output error codes * to signify errors regarding input/output */ enum LIBFSNTFS_IO_ERROR { LIBFSNTFS_IO_ERROR_GENERIC = 0, /* The open failed */ LIBFSNTFS_IO_ERROR_OPEN_FAILED = 1, /* The close failed */ LIBFSNTFS_IO_ERROR_CLOSE_FAILED = 2, /* The seek failed */ LIBFSNTFS_IO_ERROR_SEEK_FAILED = 3, /* The read failed */ LIBFSNTFS_IO_ERROR_READ_FAILED = 4, /* The write failed */ LIBFSNTFS_IO_ERROR_WRITE_FAILED = 5, /* Access denied */ LIBFSNTFS_IO_ERROR_ACCESS_DENIED = 6, /* The resource is invalid i.e. a missing file */ LIBFSNTFS_IO_ERROR_INVALID_RESOURCE = 7, /* The ioctl failed */ LIBFSNTFS_IO_ERROR_IOCTL_FAILED = 8, /* The unlink failed */ LIBFSNTFS_IO_ERROR_UNLINK_FAILED = 9 }; /* The input error codes * to signify errors regarding handing input data */ enum LIBFSNTFS_INPUT_ERROR { LIBFSNTFS_INPUT_ERROR_GENERIC = 0, /* The input contains invalid data */ LIBFSNTFS_INPUT_ERROR_INVALID_DATA = 1, /* The input contains an unsupported signature */ LIBFSNTFS_INPUT_ERROR_SIGNATURE_MISMATCH = 2, /* A checksum in the input did not match */ LIBFSNTFS_INPUT_ERROR_CHECKSUM_MISMATCH = 3, /* A value in the input did not match a previously * read value or calculated value */ LIBFSNTFS_INPUT_ERROR_VALUE_MISMATCH = 4 }; /* The memory error codes * to signify errors regarding memory */ enum LIBFSNTFS_MEMORY_ERROR { LIBFSNTFS_MEMORY_ERROR_GENERIC = 0, /* There is insufficient memory available */ LIBFSNTFS_MEMORY_ERROR_INSUFFICIENT = 1, /* The memory failed to be copied */ LIBFSNTFS_MEMORY_ERROR_COPY_FAILED = 2, /* The memory failed to be set */ LIBFSNTFS_MEMORY_ERROR_SET_FAILED = 3 }; /* The output error codes */ enum LIBFSNTFS_OUTPUT_ERROR { LIBFSNTFS_OUTPUT_ERROR_GENERIC = 0, /* There is insuficient space to write the output */ LIBFSNTFS_OUTPUT_ERROR_INSUFFICIENT_SPACE = 1 }; /* The runtime error codes * to signify errors regarding runtime processing */ enum LIBFSNTFS_RUNTIME_ERROR { LIBFSNTFS_RUNTIME_ERROR_GENERIC = 0, /* The value is missing */ LIBFSNTFS_RUNTIME_ERROR_VALUE_MISSING = 1, /* The value was already set */ LIBFSNTFS_RUNTIME_ERROR_VALUE_ALREADY_SET = 2, /* The creation and/or initialization of an internal structure failed */ LIBFSNTFS_RUNTIME_ERROR_INITIALIZE_FAILED = 3, /* The resize of an internal structure failed */ LIBFSNTFS_RUNTIME_ERROR_RESIZE_FAILED = 4, /* The free and/or finalization of an internal structure failed */ LIBFSNTFS_RUNTIME_ERROR_FINALIZE_FAILED = 5, /* The value could not be determined */ LIBFSNTFS_RUNTIME_ERROR_GET_FAILED = 6, /* The value could not be set */ LIBFSNTFS_RUNTIME_ERROR_SET_FAILED = 7, /* The value could not be appended/prepended */ LIBFSNTFS_RUNTIME_ERROR_APPEND_FAILED = 8, /* The value could not be copied */ LIBFSNTFS_RUNTIME_ERROR_COPY_FAILED = 9, /* The value could not be removed */ LIBFSNTFS_RUNTIME_ERROR_REMOVE_FAILED = 10, /* The value could not be printed */ LIBFSNTFS_RUNTIME_ERROR_PRINT_FAILED = 11, /* The value was out of bounds */ LIBFSNTFS_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS = 12, /* The value exceeds the maximum for its specific type */ LIBFSNTFS_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM = 13, /* The value is unsupported */ LIBFSNTFS_RUNTIME_ERROR_UNSUPPORTED_VALUE = 14, /* An abort was requested */ LIBFSNTFS_RUNTIME_ERROR_ABORT_REQUESTED = 15 }; #endif /* !defined( _LIBFSNTFS_ERROR_H ) */ ================================================ FILE: include/libfsntfs/extern.h ================================================ /* * The extern definition * * This header should be included in header files that export or import * library functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_EXTERN_H ) #define _LIBFSNTFS_EXTERN_H /* To export functions from the libfsntfs DLL define LIBFSNTFS_DLL_EXPORT * To import functions from the libfsntfs DLL define LIBFSNTFS_DLL_IMPORT * Otherwise use default extern statement */ #if defined( LIBFSNTFS_DLL_EXPORT ) #define LIBFSNTFS_EXTERN __declspec(dllexport) #elif defined( LIBFSNTFS_DLL_IMPORT ) #define LIBFSNTFS_EXTERN extern __declspec(dllimport) #else #define LIBFSNTFS_EXTERN extern #endif #endif /* !defined( _LIBFSNTFS_EXTERN_H ) */ ================================================ FILE: include/libfsntfs/features.h.in ================================================ /* * Features of libfsntfs * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_FEATURES_H ) #define _LIBFSNTFS_FEATURES_H /* The libfsntfs type support features */ #if defined( WINAPI ) || @HAVE_WIDE_CHARACTER_TYPE@ #define LIBFSNTFS_HAVE_WIDE_CHARACTER_TYPE 1 #endif #if defined( WINAPI ) || @HAVE_MULTI_THREAD_SUPPORT@ #define LIBFSNTFS_HAVE_MULTI_THREAD_SUPPORT 1 #endif #if defined( HAVE_LIBBFIO ) || ( !defined( WINAPI ) && @HAVE_LIBBFIO@ ) #define LIBFSNTFS_HAVE_BFIO 1 #endif #if !defined( LIBFSNTFS_DEPRECATED ) #if defined( __GNUC__ ) && __GNUC__ >= 3 #define LIBFSNTFS_DEPRECATED __attribute__ ((__deprecated__)) #elif defined( _MSC_VER ) #define LIBFSNTFS_DEPRECATED __declspec(deprecated) #else #define LIBFSNTFS_DEPRECATED #endif #endif #endif /* !defined( _LIBFSNTFS_FEATURES_H ) */ ================================================ FILE: include/libfsntfs/types.h.in ================================================ /* * Type definitions for libfsntfs * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_TYPES_H ) #define _LIBFSNTFS_TYPES_H #include /* Integer type definitions */ #if ( defined( _MSC_VER ) && ( _MSC_VER < 1600 ) ) || ( defined( __BORLANDC__ ) && ( __BORLANDC__ <= 0x0560 ) ) #ifdef __cplusplus extern "C" { #endif /* Microsoft Visual Studio C++ before Visual Studio 2010 or earlier versions of the Borland C++ Builder * do not support the (u)int#_t type definitions but have __int# definitions instead */ #if !defined( HAVE_INT8_T ) #define HAVE_INT8_T typedef __int8 int8_t; #endif #if !defined( HAVE_UINT8_T ) #define HAVE_UINT8_T typedef unsigned __int8 uint8_t; #endif #if !defined( HAVE_INT16_T ) #define HAVE_INT16_T typedef __int16 int16_t; #endif #if !defined( HAVE_UINT16_T ) #define HAVE_UINT16_T typedef unsigned __int16 uint16_t; #endif #if !defined( HAVE_INT32_T ) #define HAVE_INT32_T typedef __int32 int32_t; #endif #if !defined( HAVE_UINT32_T ) #define HAVE_UINT32_T typedef unsigned __int32 uint32_t; #endif #if !defined( HAVE_INT64_T ) #define HAVE_INT64_T typedef __int64 int64_t; #endif #if !defined( HAVE_UINT64_T ) #define HAVE_UINT64_T typedef unsigned __int64 uint64_t; #endif #ifdef __cplusplus } #endif #elif defined( _MSC_VER ) || defined( __BORLANDC__ ) /* Later versions of Microsoft Visual Studio C++ and Borland C/C++ define the types in */ #include #else #if @HAVE_SYS_TYPES_H@ || defined( HAVE_SYS_TYPES_H ) #include #else #error Missing system type definitions (sys/types.h) #endif /* Type definitions for compilers that have access to * or */ #if @HAVE_INTTYPES_H@ || defined( HAVE_INTTYPES_H ) #include #elif @HAVE_STDINT_H@ || defined( HAVE_STDINT_H ) #include #else #error Missing integer type definitions (inttypes.h, stdint.h) #endif #endif #ifdef __cplusplus extern "C" { #endif #if defined( _MSC_VER ) || ( defined( __BORLANDC__ ) && ( __BORLANDC__ <= 0x0560 ) ) /* Microsoft Visual Studio C++ or earlier versions of the Borland C++ Builder * do not support the ssize_t type definition */ #if !defined( HAVE_SSIZE_T ) #define HAVE_SSIZE_T #if defined( _WIN64 ) typedef __int64 ssize_t; #else typedef __int32 ssize_t; #endif #endif /* !defined( HAVE_SSIZE_T ) */ #endif /* defined( _MSC_VER ) || ( defined( __BORLANDC__ ) && ( __BORLANDC__ <= 0x0560 ) ) */ #if defined( __BORLANDC__ ) && ( __BORLANDC__ <= 0x0560 ) /* Earlier versions of Borland C++ Builder do not support the intptr_t type definition */ #if !defined( HAVE_INTPTR_T ) #define HAVE_INTPTR_T #if defined( _WIN64 ) typedef __int64 intptr_t; #else typedef __int32 intptr_t; #endif #endif /* !defined( HAVE_INTPTR_T ) */ #endif /* defined( __BORLANDC__ ) && ( __BORLANDC__ <= 0x0560 ) */ #if ( !defined( HAVE_SIZE32_T ) && ! @HAVE_SIZE32_T@ ) || HAVE_SIZE32_T == 0 #define HAVE_SIZE32_T 1 typedef uint32_t size32_t; #endif #if ( !defined( HAVE_SSIZE32_T ) && ! @HAVE_SSIZE32_T@ ) || HAVE_SSIZE32_T == 0 #define HAVE_SSIZE32_T 1 typedef int32_t ssize32_t; #endif #if ( !defined( HAVE_SIZE64_T ) && ! @HAVE_SIZE64_T@ ) || HAVE_SIZE64_T == 0 #define HAVE_SIZE64_T 1 typedef uint64_t size64_t; #endif #if ( !defined( HAVE_SSIZE64_T ) && ! @HAVE_SSIZE64_T@ ) || HAVE_SSIZE64_T == 0 #define HAVE_SSIZE64_T 1 typedef int64_t ssize64_t; #endif #if ( !defined( HAVE_OFF64_T ) && ! @HAVE_OFF64_T@ ) || HAVE_OFF64_T == 0 #define HAVE_OFF64_T 1 typedef int64_t off64_t; #endif /* Wide character definition */ #if defined( __BORLANDC__ ) && ( __BORLANDC__ <= 0x0520 ) #include #elif defined( WINAPI ) #include #elif @HAVE_WCHAR_H@ || defined( HAVE_WCHAR_H ) /* __USE_UNIX98 is required to add swprintf definition */ #if !defined( __USE_UNIX98 ) #define __USE_UNIX98 #define LIBFSNTFS_DEFINITION_UNIX98 #endif #include #if defined( LIBFSNTFS_DEFINITION_UNIX98 ) #undef __USE_UNIX98 #undef LIBFSNTFS_DEFINITION_UNIX98 #endif #endif /* The following type definitions hide internal data structures */ typedef intptr_t libfsntfs_attribute_t; typedef intptr_t libfsntfs_attribute_list_entry_t; typedef intptr_t libfsntfs_data_stream_t; typedef intptr_t libfsntfs_file_entry_t; typedef intptr_t libfsntfs_mft_metadata_file_t; typedef intptr_t libfsntfs_usn_change_journal_t; typedef intptr_t libfsntfs_volume_t; #ifdef __cplusplus } #endif #endif /* !defined( _LIBFSNTFS_TYPES_H ) */ ================================================ FILE: include/libfsntfs.h.in ================================================ /* * Library to access the New Technology File System (NTFS) format * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_H ) #define _LIBFSNTFS_H #include #include #include #include #include #include #include #if defined( LIBFSNTFS_HAVE_BFIO ) #include #endif #if defined( __cplusplus ) extern "C" { #endif /* ------------------------------------------------------------------------- * Support functions * ------------------------------------------------------------------------- */ /* Returns the library version */ LIBFSNTFS_EXTERN \ const char *libfsntfs_get_version( void ); /* Returns the access flags for reading */ LIBFSNTFS_EXTERN \ int libfsntfs_get_access_flags_read( void ); /* Retrieves the narrow system string codepage * A value of 0 represents no codepage, UTF-8 encoding is used instead * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_get_codepage( int *codepage, libfsntfs_error_t **error ); /* Sets the narrow system string codepage * A value of 0 represents no codepage, UTF-8 encoding is used instead * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_set_codepage( int codepage, libfsntfs_error_t **error ); /* Determines if a file contains a NTFS volume signature * Returns 1 if true, 0 if not or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_check_volume_signature( const char *filename, libfsntfs_error_t **error ); #if defined( LIBFSNTFS_HAVE_WIDE_CHARACTER_TYPE ) /* Determines if a file contains a NTFS volume signature * Returns 1 if true, 0 if not or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_check_volume_signature_wide( const wchar_t *filename, libfsntfs_error_t **error ); #endif /* defined( LIBFSNTFS_HAVE_WIDE_CHARACTER_TYPE ) */ #if defined( LIBFSNTFS_HAVE_BFIO ) /* Determines if a file contains a NTFS volume signature using a Basic File IO (bfio) handle * Returns 1 if true, 0 if not or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_check_volume_signature_file_io_handle( libbfio_handle_t *file_io_handle, libfsntfs_error_t **error ); #endif /* defined( LIBFSNTFS_HAVE_BFIO ) */ /* Determines if a file contains a NTFS MFT metadata file signature * Returns 1 if true, 0 if not or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_check_mft_metadata_file_signature( const char *filename, libfsntfs_error_t **error ); #if defined( LIBFSNTFS_HAVE_WIDE_CHARACTER_TYPE ) /* Determines if a file contains a NTFS MFT metadata file signature * Returns 1 if true, 0 if not or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_check_mft_metadata_file_signature_wide( const wchar_t *filename, libfsntfs_error_t **error ); #endif /* defined( LIBFSNTFS_HAVE_WIDE_CHARACTER_TYPE ) */ #if defined( LIBFSNTFS_HAVE_BFIO ) /* Determines if a file contains a NTFS MFT metadata file signature using a Basic File IO (bfio) handle * Returns 1 if true, 0 if not or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_check_mft_metadata_file_signature_file_io_handle( libbfio_handle_t *file_io_handle, libfsntfs_error_t **error ); #endif /* defined( LIBFSNTFS_HAVE_BFIO ) */ /* ------------------------------------------------------------------------- * Notify functions * ------------------------------------------------------------------------- */ /* Sets the verbose notification */ LIBFSNTFS_EXTERN \ void libfsntfs_notify_set_verbose( int verbose ); /* Sets the notification stream * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_notify_set_stream( FILE *stream, libfsntfs_error_t **error ); /* Opens the notification stream using a filename * The stream is opened in append mode * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_notify_stream_open( const char *filename, libfsntfs_error_t **error ); /* Closes the notification stream if opened using a filename * Returns 0 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_notify_stream_close( libfsntfs_error_t **error ); /* ------------------------------------------------------------------------- * Error functions * ------------------------------------------------------------------------- */ /* Frees an error */ LIBFSNTFS_EXTERN \ void libfsntfs_error_free( libfsntfs_error_t **error ); /* Prints a descriptive string of the error to the stream * Returns the number of printed characters if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_error_fprint( libfsntfs_error_t *error, FILE *stream ); /* Prints a descriptive string of the error to the string * The end-of-string character is not included in the return value * Returns the number of printed characters if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_error_sprint( libfsntfs_error_t *error, char *string, size_t size ); /* Prints a backtrace of the error to the stream * Returns the number of printed characters if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_error_backtrace_fprint( libfsntfs_error_t *error, FILE *stream ); /* Prints a backtrace of the error to the string * The end-of-string character is not included in the return value * Returns the number of printed characters if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_error_backtrace_sprint( libfsntfs_error_t *error, char *string, size_t size ); /* ------------------------------------------------------------------------- * Volume functions * ------------------------------------------------------------------------- */ /* Creates a volume * Make sure the value volume is referencing, is set to NULL * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_initialize( libfsntfs_volume_t **volume, libfsntfs_error_t **error ); /* Frees a volume * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_free( libfsntfs_volume_t **volume, libfsntfs_error_t **error ); /* Signals the volume to abort its current activity * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_signal_abort( libfsntfs_volume_t *volume, libfsntfs_error_t **error ); /* Opens a volume * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_open( libfsntfs_volume_t *volume, const char *filename, int access_flags, libfsntfs_error_t **error ); #if defined( LIBFSNTFS_HAVE_WIDE_CHARACTER_TYPE ) /* Opens a volume * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_open_wide( libfsntfs_volume_t *volume, const wchar_t *filename, int access_flags, libfsntfs_error_t **error ); #endif /* defined( LIBFSNTFS_HAVE_WIDE_CHARACTER_TYPE ) */ #if defined( LIBFSNTFS_HAVE_BFIO ) /* Opens a volume using a Basic File IO (bfio) handle * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_open_file_io_handle( libfsntfs_volume_t *volume, libbfio_handle_t *file_io_handle, int access_flags, libfsntfs_error_t **error ); #endif /* defined( LIBFSNTFS_HAVE_BFIO ) */ /* Closes a volume * Returns 0 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_close( libfsntfs_volume_t *volume, libfsntfs_error_t **error ); /* Determines if the volume has BitLocker Drive Encryption (BDE) * Returns 1 if the volume has BitLocker Drive Encryption, 0 if not or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_has_bitlocker_drive_encryption( libfsntfs_volume_t *volume, libfsntfs_error_t **error ); /* Determines if the volume has Volume Shadow Snapshots (VSS) * Returns 1 if the volume has Volume Shadow Snapshots, 0 if not or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_has_volume_shadow_snapshots( libfsntfs_volume_t *volume, libfsntfs_error_t **error ); /* Retrieves the bytes per sector * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_bytes_per_sector( libfsntfs_volume_t *volume, uint16_t *bytes_per_sector, libfsntfs_error_t **error ); /* Retrieves the cluster block size * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_cluster_block_size( libfsntfs_volume_t *volume, size32_t *cluster_block_size, libfsntfs_error_t **error ); /* Retrieves the MFT entry size * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_mft_entry_size( libfsntfs_volume_t *volume, size32_t *mft_entry_size, libfsntfs_error_t **error ); /* Retrieves the index entry size * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_index_entry_size( libfsntfs_volume_t *volume, size32_t *index_entry_size, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-8 encoded name * The returned size includes the end of string character * This value is retrieved from the $VOLUME_NAME attribute of the $Volume metadata file * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_utf8_name_size( libfsntfs_volume_t *volume, size_t *utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-8 encoded name * The size should include the end of string character * This value is retrieved from the $VOLUME_NAME attribute of the $Volume metadata file * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_utf8_name( libfsntfs_volume_t *volume, uint8_t *utf8_string, size_t utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-16 encoded name * The returned size includes the end of string character * This value is retrieved from the $VOLUME_NAME attribute of the $Volume metadata file * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_utf16_name_size( libfsntfs_volume_t *volume, size_t *utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-16 encoded name * The size should include the end of string character * This value is retrieved from the $VOLUME_NAME attribute of the $Volume metadata file * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_utf16_name( libfsntfs_volume_t *volume, uint16_t *utf16_string, size_t utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the format version * This value is retrieved from the $VOLUME_INFORMATION attribute * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_version( libfsntfs_volume_t *volume, uint8_t *major_version, uint8_t *minor_version, libfsntfs_error_t **error ); /* Retrieves the flags * This value is retrieved from the $VOLUME_INFORMATION attribute * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_flags( libfsntfs_volume_t *volume, uint16_t *flags, libfsntfs_error_t **error ); /* Retrieves the serial number * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_serial_number( libfsntfs_volume_t *volume, uint64_t *serial_number, libfsntfs_error_t **error ); /* Retrieves the root directory file entry * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_root_directory( libfsntfs_volume_t *volume, libfsntfs_file_entry_t **file_entry, libfsntfs_error_t **error ); /* Retrieves the number of file entries (MFT entries) * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_number_of_file_entries( libfsntfs_volume_t *volume, uint64_t *number_of_file_entries, libfsntfs_error_t **error ); /* Retrieves the file entry of a specific MFT entry index * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_file_entry_by_index( libfsntfs_volume_t *volume, uint64_t mft_entry_index, libfsntfs_file_entry_t **file_entry, libfsntfs_error_t **error ); /* Retrieves the file entry for an UTF-8 encoded path * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode * Returns 1 if successful, 0 if no such file entry or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_file_entry_by_utf8_path( libfsntfs_volume_t *volume, const uint8_t *utf8_string, size_t utf8_string_length, libfsntfs_file_entry_t **file_entry, libfsntfs_error_t **error ); /* Retrieves the file entry for an UTF-16 encoded path * This function uses UCS-2 (with surrogates) to support characters outside Unicode * Returns 1 if successful, 0 if no such file entry or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_file_entry_by_utf16_path( libfsntfs_volume_t *volume, const uint16_t *utf16_string, size_t utf16_string_length, libfsntfs_file_entry_t **file_entry, libfsntfs_error_t **error ); /* Retrieves the usn change journal * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_usn_change_journal( libfsntfs_volume_t *volume, libfsntfs_usn_change_journal_t **usn_change_journal, libfsntfs_error_t **error ); /* ------------------------------------------------------------------------- * File entry functions * ------------------------------------------------------------------------- */ /* Frees a file entry * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_free( libfsntfs_file_entry_t **file_entry, libfsntfs_error_t **error ); /* Determines if the file entry is emtpy * Returns 1 if empty, 0 if not or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_is_empty( libfsntfs_file_entry_t *file_entry, libfsntfs_error_t **error ); /* Determines if the file entry is allocated (MFT entry in use flag is set) * Returns 1 if allocated, 0 if not or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_is_allocated( libfsntfs_file_entry_t *file_entry, libfsntfs_error_t **error ); /* Determines if the file entry is corrupted * Returns 1 if corrupted, 0 if not or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_is_corrupted( libfsntfs_file_entry_t *file_entry, libfsntfs_error_t **error ); /* Retrieves the file reference * This value is retrieved from the MFT entry * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_file_reference( libfsntfs_file_entry_t *file_entry, uint64_t *file_reference, libfsntfs_error_t **error ); /* Retrieves the base record file reference * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_base_record_file_reference( libfsntfs_file_entry_t *file_entry, uint64_t *file_reference, libfsntfs_error_t **error ); /* Retrieves the parent file reference * This value is retrieved from the directory entry $FILE_NAME attribute * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_parent_file_reference( libfsntfs_file_entry_t *file_entry, uint64_t *parent_file_reference, libfsntfs_error_t **error ); /* Retrieves the parent file reference for a specific $FILE_NAME attribute * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_parent_file_reference_by_attribute_index( libfsntfs_file_entry_t *file_entry, int attribute_index, uint64_t *parent_file_reference, libfsntfs_error_t **error ); /* Retrieves the journal sequence number * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_journal_sequence_number( libfsntfs_file_entry_t *file_entry, uint64_t *journal_sequence_number, libfsntfs_error_t **error ); /* Retrieves the creation date and time * This value is retrieved from the $STANDARD_INFORMATION attribute * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_creation_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libfsntfs_error_t **error ); /* Retrieves the modification date and time * This value is retrieved from the $STANDARD_INFORMATION attribute * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_modification_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libfsntfs_error_t **error ); /* Retrieves the access date and time * This value is retrieved from the $STANDARD_INFORMATION attribute * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_access_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libfsntfs_error_t **error ); /* Retrieves the entry modification date and time * This value is retrieved from the $STANDARD_INFORMATION attribute * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_entry_modification_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libfsntfs_error_t **error ); /* Retrieves the file attribute flags * This value is retrieved from the $STANDARD_INFORMATION attribute * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_file_attribute_flags( libfsntfs_file_entry_t *file_entry, uint32_t *file_attribute_flags, libfsntfs_error_t **error ); /* Retrieves the file reference * This value is retrieved from the $I30 $FILE_NAME directory entry * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_i30_file_reference( libfsntfs_file_entry_t *file_entry, uint64_t *file_reference, libfsntfs_error_t **error ); /* Retrieves the creation date and time * This value is retrieved from the $I30 $FILE_NAME directory entry * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_i30_creation_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libfsntfs_error_t **error ); /* Retrieves the modification date and time * This value is retrieved from the $I30 $FILE_NAME directory entry * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_i30_modification_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libfsntfs_error_t **error ); /* Retrieves the access date and time * This value is retrieved from the $I30 $FILE_NAME directory entry * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_i30_access_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libfsntfs_error_t **error ); /* Retrieves the entry modification date and time * This value is retrieved from the $I30 $FILE_NAME directory entry * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_i30_entry_modification_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libfsntfs_error_t **error ); /* Retrieves the size * This value is retrieved from the $I30 $FILE_NAME directory entry * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_i30_size( libfsntfs_file_entry_t *file_entry, uint64_t *size, libfsntfs_error_t **error ); /* Retrieves the file attribute flags * This value is retrieved from the $I30 $FILE_NAME directory entry * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_i30_file_attribute_flags( libfsntfs_file_entry_t *file_entry, uint32_t *file_attribute_flags, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-8 encoded name * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode * The returned size includes the end of string character * This value is retrieved from the directory entry $FILE_NAME attribute * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf8_name_size( libfsntfs_file_entry_t *file_entry, size_t *utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-8 encoded name * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode * The size should include the end of string character * This value is retrieved from the directory entry $FILE_NAME attribute * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf8_name( libfsntfs_file_entry_t *file_entry, uint8_t *utf8_string, size_t utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-16 encoded name * This function uses UCS-2 (with surrogates) to support characters outside Unicode * The returned size includes the end of string character * This value is retrieved from the directory entry $FILE_NAME attribute * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf16_name_size( libfsntfs_file_entry_t *file_entry, size_t *utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-16 encoded name * This function uses UCS-2 (with surrogates) to support characters outside Unicode * The size should include the end of string character * This value is retrieved from the directory entry $FILE_NAME attribute * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf16_name( libfsntfs_file_entry_t *file_entry, uint16_t *utf16_string, size_t utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the $FILE_NAME attribute index * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_name_attribute_index( libfsntfs_file_entry_t *file_entry, int *attribute_index, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-8 encoded name for a specific $FILE_NAME attribute * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf8_name_size_by_attribute_index( libfsntfs_file_entry_t *file_entry, int attribute_index, size_t *utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-8 encoded name for a specific $FILE_NAME attribute * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode * The size should include the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf8_name_by_attribute_index( libfsntfs_file_entry_t *file_entry, int attribute_index, uint8_t *utf8_string, size_t utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-16 encoded name for a specific $FILE_NAME attribute * This function uses UCS-2 (with surrogates) to support characters outside Unicode * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf16_name_size_by_attribute_index( libfsntfs_file_entry_t *file_entry, int attribute_index, size_t *utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-16 encoded name for a specific $FILE_NAME attribute * The size should include the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf16_name_by_attribute_index( libfsntfs_file_entry_t *file_entry, int attribute_index, uint16_t *utf16_string, size_t utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-8 encoded path hint for a specific $FILE_NAME attribute * The returned size includes the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf8_path_hint_size( libfsntfs_file_entry_t *file_entry, int attribute_index, size_t *utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-8 encoded path hint for a specific $FILE_NAME attribute * The size should include the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf8_path_hint( libfsntfs_file_entry_t *file_entry, int attribute_index, uint8_t *utf8_string, size_t utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-16 encoded path hint for a specific $FILE_NAME attribute * The returned size includes the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf16_path_hint_size( libfsntfs_file_entry_t *file_entry, int attribute_index, size_t *utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-16 encoded path hint for a specific $FILE_NAME attribute * The size should include the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf16_path_hint( libfsntfs_file_entry_t *file_entry, int attribute_index, uint16_t *utf16_string, size_t utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-8 encoded symbolic link target * The returned size includes the end of string character * This value is retrieved from a symbolic link $REPARSE_POINT attribute * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf8_symbolic_link_target_size( libfsntfs_file_entry_t *file_entry, size_t *utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-8 encoded symbolic link target * The size should include the end of string character * This value is retrieved from a symbolic link $REPARSE_POINT attribute * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf8_symbolic_link_target( libfsntfs_file_entry_t *file_entry, uint8_t *utf8_string, size_t utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-16 encoded symbolic link target * The returned size includes the end of string character * This value is retrieved from a symbolic link $REPARSE_POINT attribute * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf16_symbolic_link_target_size( libfsntfs_file_entry_t *file_entry, size_t *utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-16 encoded symbolic link target * The size should include the end of string character * This value is retrieved from a symbolic link $REPARSE_POINT attribute * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf16_symbolic_link_target( libfsntfs_file_entry_t *file_entry, uint16_t *utf16_string, size_t utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the security descriptor (data) size * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_security_descriptor_size( libfsntfs_file_entry_t *file_entry, size_t *data_size, libfsntfs_error_t **error ); /* Retrieves the security descriptor (data) * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_security_descriptor( libfsntfs_file_entry_t *file_entry, uint8_t *data, size_t data_size, libfsntfs_error_t **error ); /* Retrieves the number of attributes * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_number_of_attributes( libfsntfs_file_entry_t *file_entry, int *number_of_attributes, libfsntfs_error_t **error ); /* Retrieves the attribute for the specific index * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_attribute_by_index( libfsntfs_file_entry_t *file_entry, int attribute_index, libfsntfs_attribute_t **attribute, libfsntfs_error_t **error ); /* Determines if the file entry has the directory entries ($I30) index * Returns 1 if the file entry has a directory entries index, 0 if not or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_has_directory_entries_index( libfsntfs_file_entry_t *file_entry, libfsntfs_error_t **error ); /* Determines if the file entry has a default data stream (nameless $DATA attribute) * Returns 1 if the file entry has a default data stream, 0 if not or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_has_default_data_stream( libfsntfs_file_entry_t *file_entry, libfsntfs_error_t **error ); /* Determines if the file entry has a $I30 entry * Returns 1 if the file entry has a $I30 entry, 0 if not or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_has_i30_entry( libfsntfs_file_entry_t *file_entry, libfsntfs_error_t **error ); /* Determines if the file entry is a symbolic link * Returns 1 if the file entry is a symbolic link, 0 if not or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_is_symbolic_link( libfsntfs_file_entry_t *file_entry, libfsntfs_error_t **error ); /* Retrieves the number of alternate data streams * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_number_of_alternate_data_streams( libfsntfs_file_entry_t *file_entry, int *number_of_alternate_data_streams, libfsntfs_error_t **error ); /* Retrieves the alternate data stream for the specific index * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_alternate_data_stream_by_index( libfsntfs_file_entry_t *file_entry, int alternate_data_stream_index, libfsntfs_data_stream_t **alternate_data_stream, libfsntfs_error_t **error ); /* Determines if there is an alternate data stream for an UTF-8 encoded name * Returns 1 if available, 0 if not or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_has_alternate_data_stream_by_utf8_name( libfsntfs_file_entry_t *file_entry, const uint8_t *utf8_string, size_t utf8_string_length, libfsntfs_error_t **error ); /* Determines if there is an alternate data stream for an UTF-16 encoded name * Returns 1 if available, 0 if not or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_has_alternate_data_stream_by_utf16_name( libfsntfs_file_entry_t *file_entry, const uint16_t *utf16_string, size_t utf16_string_length, libfsntfs_error_t **error ); /* Retrieves the alternate data stream for an UTF-8 encoded name * Returns 1 if successful, 0 if the file entry does not contain such value or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_alternate_data_stream_by_utf8_name( libfsntfs_file_entry_t *file_entry, const uint8_t *utf8_string, size_t utf8_string_length, libfsntfs_data_stream_t **alternate_data_stream, libfsntfs_error_t **error ); /* Retrieves the alternate data stream for an UTF-16 encoded name * Returns 1 if successful, 0 if the file entry does not contain such value or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_alternate_data_stream_by_utf16_name( libfsntfs_file_entry_t *file_entry, const uint16_t *utf16_string, size_t utf16_string_length, libfsntfs_data_stream_t **alternate_data_stream, libfsntfs_error_t **error ); /* Retrieves the number of sub file entries * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_number_of_sub_file_entries( libfsntfs_file_entry_t *file_entry, int *number_of_sub_file_entries, libfsntfs_error_t **error ); /* Retrieves the sub file entry for the specific index * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_sub_file_entry_by_index( libfsntfs_file_entry_t *file_entry, int sub_file_entry_index, libfsntfs_file_entry_t **sub_file_entry, libfsntfs_error_t **error ); /* Retrieves the sub file entry for an UTF-8 encoded name * Returns 1 if successful, 0 if the file entry does not contain such value or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_sub_file_entry_by_utf8_name( libfsntfs_file_entry_t *file_entry, const uint8_t *utf8_string, size_t utf8_string_length, libfsntfs_file_entry_t **sub_file_entry, libfsntfs_error_t **error ); /* Retrieves the sub file entry for an UTF-16 encoded name * Returns 1 if successful, 0 if the file entry does not contain such value or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_sub_file_entry_by_utf16_name( libfsntfs_file_entry_t *file_entry, const uint16_t *utf16_string, size_t utf16_string_length, libfsntfs_file_entry_t **sub_file_entry, libfsntfs_error_t **error ); /* Reads data at the current offset from the default data stream (nameless $DATA attribute) * Returns the number of bytes read or -1 on error */ LIBFSNTFS_EXTERN \ ssize_t libfsntfs_file_entry_read_buffer( libfsntfs_file_entry_t *file_entry, void *buffer, size_t buffer_size, libfsntfs_error_t **error ); /* Reads data at a specific offset from the default data stream (nameless $DATA attribute) * Returns the number of bytes read or -1 on error */ LIBFSNTFS_EXTERN \ ssize_t libfsntfs_file_entry_read_buffer_at_offset( libfsntfs_file_entry_t *file_entry, void *buffer, size_t buffer_size, off64_t offset, libfsntfs_error_t **error ); /* Seeks a certain offset of in the default data stream (nameless $DATA attribute) * Returns the offset if seek is successful or -1 on error */ LIBFSNTFS_EXTERN \ off64_t libfsntfs_file_entry_seek_offset( libfsntfs_file_entry_t *file_entry, off64_t offset, int whence, libfsntfs_error_t **error ); /* Retrieves the current offset of the default data stream (nameless $DATA attribute) * Returns the offset if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_offset( libfsntfs_file_entry_t *file_entry, off64_t *offset, libfsntfs_error_t **error ); /* Retrieves the size of the default data stream (nameless $DATA attribute) * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_size( libfsntfs_file_entry_t *file_entry, size64_t *size, libfsntfs_error_t **error ); /* Retrieves the number of extents (decoded data runs) of the default data stream (nameless $DATA attribute) * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_number_of_extents( libfsntfs_file_entry_t *file_entry, int *number_of_extents, libfsntfs_error_t **error ); /* Retrieves a specific extent (decoded data run) of the default data stream (nameless $DATA attribute) * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_extent_by_index( libfsntfs_file_entry_t *file_entry, int extent_index, off64_t *extent_offset, size64_t *extent_size, uint32_t *extent_flags, libfsntfs_error_t **error ); /* ------------------------------------------------------------------------- * Attribute functions * ------------------------------------------------------------------------- */ /* Frees an attribute * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_free( libfsntfs_attribute_t **attribute, libfsntfs_error_t **error ); /* Retrieves the type * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_get_type( libfsntfs_attribute_t *attribute, uint32_t *type, libfsntfs_error_t **error ); /* Retrieves the data flags * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_get_data_flags( libfsntfs_attribute_t *attribute, uint16_t *data_flags, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-8 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_get_utf8_name_size( libfsntfs_attribute_t *attribute, size_t *utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-8 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_get_utf8_name( libfsntfs_attribute_t *attribute, uint8_t *utf8_string, size_t utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-16 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_get_utf16_name_size( libfsntfs_attribute_t *attribute, size_t *utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-16 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_get_utf16_name( libfsntfs_attribute_t *attribute, uint16_t *utf16_string, size_t utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the data VCN range * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_get_data_vcn_range( libfsntfs_attribute_t *attribute, uint64_t *data_first_vcn, uint64_t *data_last_vcn, libfsntfs_error_t **error ); /* Retrieves the data size * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_get_data_size( libfsntfs_attribute_t *attribute, size64_t *data_size, libfsntfs_error_t **error ); /* Retrieves the valid data size * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_get_valid_data_size( libfsntfs_attribute_t *attribute, size64_t *valid_data_size, libfsntfs_error_t **error ); /* ------------------------------------------------------------------------- * $ATTRIBUTE_LIST attribute functions * ------------------------------------------------------------------------- */ /* Retrieves the number of attribute list entries * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_list_attribute_get_number_of_entries( libfsntfs_attribute_t *attribute, int *number_of_entries, libfsntfs_error_t **error ); /* Retrieves a specific attribute list entry * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_list_attribute_get_entry_by_index( libfsntfs_attribute_t *attribute, int entry_index, libfsntfs_attribute_list_entry_t **entry, libfsntfs_error_t **error ); /* ------------------------------------------------------------------------- * Attribute list entry functions * ------------------------------------------------------------------------- */ /* Frees an attribute list entry * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_list_entry_free( libfsntfs_attribute_list_entry_t **attribute_list_entry, libfsntfs_error_t **error ); /* Retrieves the attribute type * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_list_entry_get_attribute_type( libfsntfs_attribute_list_entry_t *attribute_list_entry, uint32_t *attribute_type, libfsntfs_error_t **error ); /* Retrieves the file reference * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_list_entry_get_file_reference( libfsntfs_attribute_list_entry_t *attribute_list_entry, uint64_t *file_reference, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-8 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_list_entry_get_utf8_name_size( libfsntfs_attribute_list_entry_t *attribute_list_entry, size_t *utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-8 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_list_entry_get_utf8_name( libfsntfs_attribute_list_entry_t *attribute_list_entry, uint8_t *utf8_string, size_t utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-16 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_list_entry_get_utf16_name_size( libfsntfs_attribute_list_entry_t *attribute_list_entry, size_t *utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-16 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_attribute_list_entry_get_utf16_name( libfsntfs_attribute_list_entry_t *attribute_list_entry, uint16_t *utf16_string, size_t utf16_string_size, libfsntfs_error_t **error ); /* ------------------------------------------------------------------------- * $FILE_NAME attribute functions * ------------------------------------------------------------------------- */ /* Retrieves the parent file reference * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_parent_file_reference( libfsntfs_attribute_t *attribute, uint64_t *parent_file_reference, libfsntfs_error_t **error ); /* Retrieves the creation date and time * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_creation_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libfsntfs_error_t **error ); /* Retrieves the modification date and time * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_modification_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libfsntfs_error_t **error ); /* Retrieves the access date and time * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_access_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libfsntfs_error_t **error ); /* Retrieves the entry modification date and time * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_entry_modification_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libfsntfs_error_t **error ); /* Retrieves the file attribute flags * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_file_attribute_flags( libfsntfs_attribute_t *attribute, uint32_t *file_attribute_flags, libfsntfs_error_t **error ); /* Retrieves the name space * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_name_space( libfsntfs_attribute_t *attribute, uint8_t *name_space, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-8 encoded name * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_utf8_name_size( libfsntfs_attribute_t *attribute, size_t *utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-8 encoded name * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode * The size should include the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_utf8_name( libfsntfs_attribute_t *attribute, uint8_t *utf8_string, size_t utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-16 encoded name * This function uses UCS-2 (with surrogates) to support characters outside Unicode * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_utf16_name_size( libfsntfs_attribute_t *attribute, size_t *utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-16 encoded name * This function uses UCS-2 (with surrogates) to support characters outside Unicode * The size should include the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_utf16_name( libfsntfs_attribute_t *attribute, uint16_t *utf16_string, size_t utf16_string_size, libfsntfs_error_t **error ); /* ------------------------------------------------------------------------- * $OBJECT_ID attribute functions * ------------------------------------------------------------------------- */ /* Retrieves the droid file identifier * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_object_identifier_attribute_get_droid_file_identifier( libfsntfs_attribute_t *attribute, uint8_t *guid, size_t size, libfsntfs_error_t **error ); /* Retrieves the birth droid volume identifier * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_object_identifier_attribute_get_birth_droid_volume_identifier( libfsntfs_attribute_t *attribute, uint8_t *guid, size_t size, libfsntfs_error_t **error ); /* Retrieves the birth droid file identifier * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_object_identifier_attribute_get_birth_droid_file_identifier( libfsntfs_attribute_t *attribute, uint8_t *guid, size_t size, libfsntfs_error_t **error ); /* Retrieves the birth droid domain identifier * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_object_identifier_attribute_get_birth_droid_domain_identifier( libfsntfs_attribute_t *attribute, uint8_t *guid, size_t size, libfsntfs_error_t **error ); /* ------------------------------------------------------------------------- * $REPARSE_POINT attribute functions * ------------------------------------------------------------------------- */ /* Retrieves the type and flags * The tag is a combination of the type and flags * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_tag( libfsntfs_attribute_t *attribute, uint32_t *tag, libfsntfs_error_t **error ); /* Retrieves the Windows Overlay Filter (WOF) compression method * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_compression_method( libfsntfs_attribute_t *attribute, uint32_t *compression_method, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-8 encoded substitute name * The returned size includes the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_utf8_substitute_name_size( libfsntfs_attribute_t *attribute, size_t *utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-8 encoded substitute name * The size should include the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_utf8_substitute_name( libfsntfs_attribute_t *attribute, uint8_t *utf8_string, size_t utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-16 encoded substitute name * The returned size includes the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_utf16_substitute_name_size( libfsntfs_attribute_t *attribute, size_t *utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-16 encoded substitute name * The size should include the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_utf16_substitute_name( libfsntfs_attribute_t *attribute, uint16_t *utf16_string, size_t utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-8 encoded print name * The returned size includes the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_utf8_print_name_size( libfsntfs_attribute_t *attribute, size_t *utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-8 encoded print name * The size should include the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_utf8_print_name( libfsntfs_attribute_t *attribute, uint8_t *utf8_string, size_t utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-16 encoded print name * The returned size includes the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_utf16_print_name_size( libfsntfs_attribute_t *attribute, size_t *utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-16 encoded print name * The size should include the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_utf16_print_name( libfsntfs_attribute_t *attribute, uint16_t *utf16_string, size_t utf16_string_size, libfsntfs_error_t **error ); /* ------------------------------------------------------------------------- * $SECURITY_DESCRIPTOR attribute functions * ------------------------------------------------------------------------- */ /* Retrieves the security descriptor (data) size * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_security_descriptor_attribute_get_security_descriptor_size( libfsntfs_attribute_t *attribute, size_t *data_size, libfsntfs_error_t **error ); /* Retrieves the security descriptor (data) * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_security_descriptor_attribute_get_security_descriptor( libfsntfs_attribute_t *attribute, uint8_t *data, size_t data_size, libfsntfs_error_t **error ); /* ------------------------------------------------------------------------- * $STANDARD_INFORMATION attribute functions * ------------------------------------------------------------------------- */ /* Retrieves the creation date and time * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_standard_information_attribute_get_creation_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libfsntfs_error_t **error ); /* Retrieves the modification date and time * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_standard_information_attribute_get_modification_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libfsntfs_error_t **error ); /* Retrieves the access date and time * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_standard_information_attribute_get_access_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libfsntfs_error_t **error ); /* Retrieves the entry modification date and time * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_standard_information_attribute_get_entry_modification_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libfsntfs_error_t **error ); /* Retrieves the file attribute flags * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_standard_information_attribute_get_file_attribute_flags( libfsntfs_attribute_t *attribute, uint32_t *file_attribute_flags, libfsntfs_error_t **error ); /* Retrieves the owner identifier * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_standard_information_attribute_get_owner_identifier( libfsntfs_attribute_t *attribute, uint32_t *owner_identifier, libfsntfs_error_t **error ); /* Retrieves the security descriptor identifier * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_standard_information_attribute_get_security_descriptor_identifier( libfsntfs_attribute_t *attribute, uint32_t *security_descriptor_identifier, libfsntfs_error_t **error ); /* Retrieves the update sequence number (USN) * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_standard_information_attribute_get_update_sequence_number( libfsntfs_attribute_t *attribute, uint64_t *update_sequence_number, libfsntfs_error_t **error ); /* ------------------------------------------------------------------------- * $VOLUME_INFORMATION attribute functions * ------------------------------------------------------------------------- */ /* Retrieves the version * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_information_attribute_get_version( libfsntfs_attribute_t *attribute, uint8_t *major_version, uint8_t *minor_version, libfsntfs_error_t **error ); /* Retrieves the flags * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_information_attribute_get_flags( libfsntfs_attribute_t *attribute, uint16_t *flags, libfsntfs_error_t **error ); /* ------------------------------------------------------------------------- * $VOLUME_NAME attribute functions * ------------------------------------------------------------------------- */ /* Retrieves the size of the UTF-8 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_name_attribute_get_utf8_name_size( libfsntfs_attribute_t *attribute, size_t *utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-8 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_name_attribute_get_utf8_name( libfsntfs_attribute_t *attribute, uint8_t *utf8_string, size_t utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-16 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_name_attribute_get_utf16_name_size( libfsntfs_attribute_t *attribute, size_t *utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-16 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_name_attribute_get_utf16_name( libfsntfs_attribute_t *attribute, uint16_t *utf16_string, size_t utf16_string_size, libfsntfs_error_t **error ); /* ------------------------------------------------------------------------- * Data stream functions * ------------------------------------------------------------------------- */ /* Frees a data stream * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_data_stream_free( libfsntfs_data_stream_t **data_stream, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-8 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_data_stream_get_utf8_name_size( libfsntfs_data_stream_t *data_stream, size_t *utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-8 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_data_stream_get_utf8_name( libfsntfs_data_stream_t *data_stream, uint8_t *utf8_string, size_t utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-16 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_data_stream_get_utf16_name_size( libfsntfs_data_stream_t *data_stream, size_t *utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-16 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_data_stream_get_utf16_name( libfsntfs_data_stream_t *data_stream, uint16_t *utf16_string, size_t utf16_string_size, libfsntfs_error_t **error ); /* Reads data at the current offset * Returns the number of bytes read or -1 on error */ LIBFSNTFS_EXTERN \ ssize_t libfsntfs_data_stream_read_buffer( libfsntfs_data_stream_t *data_stream, void *buffer, size_t buffer_size, libfsntfs_error_t **error ); /* Reads data at a specific offset * Returns the number of bytes read or -1 on error */ LIBFSNTFS_EXTERN \ ssize_t libfsntfs_data_stream_read_buffer_at_offset( libfsntfs_data_stream_t *data_stream, void *buffer, size_t buffer_size, off64_t offset, libfsntfs_error_t **error ); /* Seeks a certain offset of the data * Returns the offset if seek is successful or -1 on error */ LIBFSNTFS_EXTERN \ off64_t libfsntfs_data_stream_seek_offset( libfsntfs_data_stream_t *data_stream, off64_t offset, int whence, libfsntfs_error_t **error ); /* Retrieves the current offset of the data * Returns the offset if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_data_stream_get_offset( libfsntfs_data_stream_t *data_stream, off64_t *offset, libfsntfs_error_t **error ); /* Retrieves the size * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_data_stream_get_size( libfsntfs_data_stream_t *data_stream, size64_t *size, libfsntfs_error_t **error ); /* Retrieves the number of extents (decoded data runs) * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_data_stream_get_number_of_extents( libfsntfs_data_stream_t *data_stream, int *number_of_extents, libfsntfs_error_t **error ); /* Retrieves a specific extent (decoded data run) * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_data_stream_get_extent_by_index( libfsntfs_data_stream_t *data_stream, int extent_index, off64_t *extent_offset, size64_t *extent_size, uint32_t *extent_flags, libfsntfs_error_t **error ); /* ------------------------------------------------------------------------- * MFT metadata file functions * ------------------------------------------------------------------------- */ /* Creates a MFT metadata file * Make sure the value mft_metadata_file is referencing, is set to NULL * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_initialize( libfsntfs_mft_metadata_file_t **mft_metadata_file, libfsntfs_error_t **error ); /* Frees a MFT metadata file * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_free( libfsntfs_mft_metadata_file_t **mft_metadata_file, libfsntfs_error_t **error ); /* Opens a MFT metadata file * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_open( libfsntfs_mft_metadata_file_t *mft_metadata_file, const char *filename, int access_flags, libfsntfs_error_t **error ); #if defined( LIBFSNTFS_HAVE_WIDE_CHARACTER_TYPE ) /* Opens a MFT metadata file * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_open_wide( libfsntfs_mft_metadata_file_t *mft_metadata_file, const wchar_t *filename, int access_flags, libfsntfs_error_t **error ); #endif /* defined( LIBFSNTFS_HAVE_WIDE_CHARACTER_TYPE ) */ #if defined( LIBFSNTFS_HAVE_BFIO ) /* Opens a MFT metadata file using a Basic File IO (bfio) handle * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_open_file_io_handle( libfsntfs_mft_metadata_file_t *mft_metadata_file, libbfio_handle_t *file_io_handle, int access_flags, libfsntfs_error_t **error ); #endif /* defined( LIBFSNTFS_HAVE_BFIO ) */ /* Closes a MFT metadata file * Returns 0 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_close( libfsntfs_mft_metadata_file_t *mft_metadata_file, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-8 encoded volume name * The returned size includes the end of string character * This value is retrieved from the $VOLUME_NAME attribute of the $Volume metadata file * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_get_utf8_volume_name_size( libfsntfs_mft_metadata_file_t *mft_metadata_file, size_t *utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-8 encoded volume name * The size should include the end of string character * This value is retrieved from the $VOLUME_NAME attribute of the $Volume metadata file * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_get_utf8_volume_name( libfsntfs_mft_metadata_file_t *mft_metadata_file, uint8_t *utf8_string, size_t utf8_string_size, libfsntfs_error_t **error ); /* Retrieves the size of the UTF-16 encoded volume name * The returned size includes the end of string character * This value is retrieved from the $VOLUME_NAME attribute of the $Volume metadata file * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_get_utf16_volume_name_size( libfsntfs_mft_metadata_file_t *mft_metadata_file, size_t *utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the UTF-16 encoded volume name * The size should include the end of string character * This value is retrieved from the $VOLUME_NAME attribute of the $Volume metadata file * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_get_utf16_volume_name( libfsntfs_mft_metadata_file_t *mft_metadata_file, uint16_t *utf16_string, size_t utf16_string_size, libfsntfs_error_t **error ); /* Retrieves the volume version * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_get_volume_version( libfsntfs_mft_metadata_file_t *mft_metadata_file, uint8_t *major_version, uint8_t *minor_version, libfsntfs_error_t **error ); /* Retrieves the volume flags * Returns 1 if successful, 0 if not available or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_get_volume_flags( libfsntfs_mft_metadata_file_t *mft_metadata_file, uint16_t *flags, libfsntfs_error_t **error ); /* Retrieves the number of file entries (MFT entries) * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_get_number_of_file_entries( libfsntfs_mft_metadata_file_t *mft_metadata_file, uint64_t *number_of_file_entries, libfsntfs_error_t **error ); /* Retrieves the file entry of a specific MFT entry index * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_get_file_entry_by_index( libfsntfs_mft_metadata_file_t *mft_metadata_file, uint64_t mft_entry_index, libfsntfs_file_entry_t **file_entry, libfsntfs_error_t **error ); /* ------------------------------------------------------------------------- * USN change journal functions * ------------------------------------------------------------------------- */ /* Frees an USN change journal * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_usn_change_journal_free( libfsntfs_usn_change_journal_t **usn_change_journal, libfsntfs_error_t **error ); /* Retrieves the current offset of the USN change journal * Returns the offset if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_usn_change_journal_get_offset( libfsntfs_usn_change_journal_t *usn_change_journal, off64_t *offset, libfsntfs_error_t **error ); /* Reads an USN record from the USN change journal * Returns the number of bytes read if successful or -1 on error */ LIBFSNTFS_EXTERN \ ssize_t libfsntfs_usn_change_journal_read_usn_record( libfsntfs_usn_change_journal_t *usn_change_journal, uint8_t *usn_record_data, size_t usn_record_data_size, libfsntfs_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_H ) */ ================================================ FILE: libfsntfs/Makefile.am ================================================ AM_CPPFLAGS = \ -I../include -I$(top_srcdir)/include \ -I../common -I$(top_srcdir)/common \ @LIBCERROR_CPPFLAGS@ \ @LIBCTHREADS_CPPFLAGS@ \ @LIBCDATA_CPPFLAGS@ \ @LIBCLOCALE_CPPFLAGS@ \ @LIBCNOTIFY_CPPFLAGS@ \ @LIBCSPLIT_CPPFLAGS@ \ @LIBUNA_CPPFLAGS@ \ @LIBCFILE_CPPFLAGS@ \ @LIBCPATH_CPPFLAGS@ \ @LIBBFIO_CPPFLAGS@ \ @LIBFCACHE_CPPFLAGS@ \ @LIBFDATA_CPPFLAGS@ \ @LIBFDATETIME_CPPFLAGS@ \ @LIBFGUID_CPPFLAGS@ \ @LIBFWNT_CPPFLAGS@ \ @PTHREAD_CPPFLAGS@ \ @LIBFSNTFS_DLL_EXPORT@ lib_LTLIBRARIES = libfsntfs.la libfsntfs_la_SOURCES = \ fsntfs_file_name.h \ fsntfs_index.h \ fsntfs_logged_utility_stream.h \ fsntfs_mft_attribute.h \ fsntfs_mft_attribute_list.h \ fsntfs_mft_entry.h \ fsntfs_object_identifier.h \ fsntfs_reparse_point.h \ fsntfs_secure.h \ fsntfs_standard_information.h \ fsntfs_txf_data.h \ fsntfs_volume_header.h \ fsntfs_volume_information.h \ libfsntfs.c \ libfsntfs_attribute.c libfsntfs_attribute.h \ libfsntfs_attribute_list_attribute.c libfsntfs_attribute_list_attribute.h \ libfsntfs_attribute_list_entry.c libfsntfs_attribute_list_entry.h \ libfsntfs_bitmap_values.c libfsntfs_bitmap_values.h \ libfsntfs_buffer_data_handle.c libfsntfs_buffer_data_handle.h \ libfsntfs_cluster_block.c libfsntfs_cluster_block.h \ libfsntfs_cluster_block_data.c libfsntfs_cluster_block_data.h \ libfsntfs_cluster_block_stream.c libfsntfs_cluster_block_stream.h \ libfsntfs_cluster_block_vector.c libfsntfs_cluster_block_vector.h \ libfsntfs_compressed_block.c libfsntfs_compressed_block.h \ libfsntfs_compressed_block_data_handle.c libfsntfs_compressed_block_data_handle.h \ libfsntfs_compressed_block_vector.c libfsntfs_compressed_block_vector.h \ libfsntfs_compressed_data_handle.c libfsntfs_compressed_data_handle.h \ libfsntfs_compression.c libfsntfs_compression.h \ libfsntfs_compression_unit_data_handle.c libfsntfs_compression_unit_data_handle.h \ libfsntfs_compression_unit_descriptor.c libfsntfs_compression_unit_descriptor.h \ libfsntfs_data_run.c libfsntfs_data_run.h \ libfsntfs_data_stream.c libfsntfs_data_stream.h \ libfsntfs_debug.c libfsntfs_debug.h \ libfsntfs_definitions.h \ libfsntfs_directory_entries_tree.c libfsntfs_directory_entries_tree.h \ libfsntfs_directory_entry.c libfsntfs_directory_entry.h \ libfsntfs_error.c libfsntfs_error.h \ libfsntfs_extent.c libfsntfs_extent.h \ libfsntfs_extern.h \ libfsntfs_file_entry.c libfsntfs_file_entry.h \ libfsntfs_file_name_attribute.c libfsntfs_file_name_attribute.h \ libfsntfs_file_name_values.c libfsntfs_file_name_values.h \ libfsntfs_file_system.c libfsntfs_file_system.h \ libfsntfs_fixup_values.c libfsntfs_fixup_values.h \ libfsntfs_index.c libfsntfs_index.h \ libfsntfs_index_entry.c libfsntfs_index_entry.h \ libfsntfs_index_entry_header.c libfsntfs_index_entry_header.h \ libfsntfs_index_entry_vector.c libfsntfs_index_entry_vector.h \ libfsntfs_index_node.c libfsntfs_index_node.h \ libfsntfs_index_node_header.c libfsntfs_index_node_header.h \ libfsntfs_index_root_header.c libfsntfs_index_root_header.h \ libfsntfs_index_value.c libfsntfs_index_value.h \ libfsntfs_io_handle.c libfsntfs_io_handle.h \ libfsntfs_libbfio.h \ libfsntfs_libcdata.h \ libfsntfs_libcerror.h \ libfsntfs_libclocale.h \ libfsntfs_libcnotify.h \ libfsntfs_libcthreads.h \ libfsntfs_libfcache.h \ libfsntfs_libfdata.h \ libfsntfs_libfdatetime.h \ libfsntfs_libfguid.h \ libfsntfs_libfwnt.h \ libfsntfs_libuna.h \ libfsntfs_logged_utility_stream_values.c libfsntfs_logged_utility_stream_values.h \ libfsntfs_mft.c libfsntfs_mft.h \ libfsntfs_mft_attribute.c libfsntfs_mft_attribute.h \ libfsntfs_mft_attribute_list.c libfsntfs_mft_attribute_list.h \ libfsntfs_mft_attribute_list_entry.c libfsntfs_mft_attribute_list_entry.h \ libfsntfs_mft_entry.c libfsntfs_mft_entry.h \ libfsntfs_mft_entry_header.c libfsntfs_mft_entry_header.h \ libfsntfs_mft_metadata_file.c libfsntfs_mft_metadata_file.h \ libfsntfs_name.c libfsntfs_name.h \ libfsntfs_notify.c libfsntfs_notify.h \ libfsntfs_object_identifier_attribute.c libfsntfs_object_identifier_attribute.h \ libfsntfs_object_identifier_values.c libfsntfs_object_identifier_values.h \ libfsntfs_path_hint.c libfsntfs_path_hint.h \ libfsntfs_profiler.c libfsntfs_profiler.h \ libfsntfs_reparse_point_attribute.c libfsntfs_reparse_point_attribute.h \ libfsntfs_reparse_point_values.c libfsntfs_reparse_point_values.h \ libfsntfs_sds_index_value.c libfsntfs_sds_index_value.h \ libfsntfs_security_descriptor_attribute.c libfsntfs_security_descriptor_attribute.h \ libfsntfs_security_descriptor_index.c libfsntfs_security_descriptor_index.h \ libfsntfs_security_descriptor_index_value.c libfsntfs_security_descriptor_index_value.h \ libfsntfs_security_descriptor_values.c libfsntfs_security_descriptor_values.h \ libfsntfs_standard_information_attribute.c libfsntfs_standard_information_attribute.h \ libfsntfs_standard_information_values.c libfsntfs_standard_information_values.h \ libfsntfs_support.c libfsntfs_support.h \ libfsntfs_types.h \ libfsntfs_txf_data_values.c libfsntfs_txf_data_values.h \ libfsntfs_unused.h \ libfsntfs_usn_change_journal.c libfsntfs_usn_change_journal.h \ libfsntfs_volume.c libfsntfs_volume.h \ libfsntfs_volume_header.c libfsntfs_volume_header.h \ libfsntfs_volume_information_attribute.c libfsntfs_volume_information_attribute.h \ libfsntfs_volume_information_values.c libfsntfs_volume_information_values.h \ libfsntfs_volume_name_attribute.c libfsntfs_volume_name_attribute.h \ libfsntfs_volume_name_values.c libfsntfs_volume_name_values.h libfsntfs_la_LIBADD = \ @LIBCERROR_LIBADD@ \ @LIBCTHREADS_LIBADD@ \ @LIBCDATA_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBBFIO_LIBADD@ \ @LIBFCACHE_LIBADD@ \ @LIBFDATA_LIBADD@ \ @LIBFDATETIME_LIBADD@ \ @LIBFGUID_LIBADD@ \ @LIBFWNT_LIBADD@ \ @PTHREAD_LIBADD@ libfsntfs_la_LDFLAGS = -no-undefined -version-info 1:0:0 EXTRA_DIST = \ libfsntfs_definitions.h.in \ libfsntfs.rc \ libfsntfs.rc.in DISTCLEANFILES = \ libfsntfs_definitions.h \ libfsntfs.rc \ Makefile \ Makefile.in sources-local: $(BUILT_SOURCES) splint-local: @echo "Running splint on libfsntfs ..." -splint -preproc -redef $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(libfsntfs_la_SOURCES) ================================================ FILE: libfsntfs/fsntfs_file_name.h ================================================ /* * The NTFS file name attribute ($FILE_NAME) definition * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_FILE_NAME_H ) #define _FSNTFS_FILE_NAME_H #include #include #if defined( __cplusplus ) extern "C" { #endif typedef struct fsntfs_file_name fsntfs_file_name_t; struct fsntfs_file_name { /* The parent file reference * Consists of 8 bytes */ uint8_t parent_file_reference[ 8 ]; /* The creation date and time * Consists of 8 bytes * Contains a FILETIME */ uint8_t creation_time[ 8 ]; /* The last modification date and time * Consists of 8 bytes * Contains a FILETIME */ uint8_t modification_time[ 8 ]; /* The entry last modification date and time * Consists of 8 bytes * Contains a FILETIME */ uint8_t entry_modification_time[ 8 ]; /* The last access date and time * Consists of 8 bytes * Contains a FILETIME */ uint8_t access_time[ 8 ]; /* The allocated (or reserved) data size * Consists of 8 bytes */ uint8_t allocated_data_size[ 8 ]; /* The data size * Consists of 8 bytes */ uint8_t data_size[ 8 ]; /* The file attribute flags * Consists of 4 bytes */ uint8_t file_attribute_flags[ 4 ]; /* The extended data * Consists of 4 bytes */ uint8_t extended_data[ 4 ]; /* The name size * Consists of 1 byte * Contains the number of characters without the end-of-string character */ uint8_t name_size; /* The name space * Consists of 1 byte */ uint8_t name_space; }; #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFS_FILE_NAME_H ) */ ================================================ FILE: libfsntfs/fsntfs_index.h ================================================ /* * The NTFS index definition * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_INDEX_H ) #define _FSNTFS_INDEX_H #include #include #if defined( __cplusplus ) extern "C" { #endif typedef struct fsntfs_index_root_header fsntfs_index_root_header_t; struct fsntfs_index_root_header { /* The attribute type * Consists of 4 bytes */ uint8_t attribute_type[ 4 ]; /* The collation type * Consists of 4 bytes */ uint8_t collation_type[ 4 ]; /* The index entry size * Consists of 4 bytes */ uint8_t index_entry_size[ 4 ]; /* The index entry number of cluster blocks * Consists of 4 bytes */ uint8_t index_entry_number_of_cluster_blocks[ 4 ]; }; typedef struct fsntfs_index_entry_header fsntfs_index_entry_header_t; struct fsntfs_index_entry_header { /* The signature * Consists of 4 bytes * Contains: "INDX" */ uint8_t signature[ 4 ]; /* The fixup values offset * Consists of 2 bytes */ uint8_t fixup_values_offset[ 2 ]; /* The number of fixup values * Consists of 2 bytes */ uint8_t number_of_fixup_values[ 2 ]; /* The journal sequence number * Consists of 8 bytes */ uint8_t journal_sequence_number[ 8 ]; /* The virtual cluster number (VCN) * Consists of 8 bytes */ uint8_t vcn[ 8 ]; }; typedef struct fsntfs_index_node_header fsntfs_index_node_header_t; struct fsntfs_index_node_header { /* The index values offset * Consists of 4 bytes * Contains a value relative to the start of the index node header */ uint8_t index_values_offset[ 4 ]; /* The size * Consists of 4 bytes */ uint8_t size[ 4 ]; /* The allocated size * Consists of 4 bytes */ uint8_t allocated_size[ 4 ]; /* The flags * Consists of 4 bytes */ uint8_t flags[ 4 ]; /* The index values */ }; typedef struct fsntfs_index_value fsntfs_index_value_t; struct fsntfs_index_value { /* The file reference * Consists of 8 bytes */ uint8_t file_reference[ 8 ]; /* The index value size * Consists of 2 bytes */ uint8_t size[ 2 ]; /* The index value key data size * Consists of 2 bytes */ uint8_t key_data_size[ 2 ]; /* The index value flags * Consists of 4 bytes */ uint8_t flags[ 4 ]; /* The index value key and value data */ /* The sub node virtual cluster number (VCN) * Consists of 8 bytes */ }; #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFS_INDEX_H ) */ ================================================ FILE: libfsntfs/fsntfs_logged_utility_stream.h ================================================ /* * The NTFS logged utillity stream attribute ($LOGGED_UTILITY_STREAM) definition * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_LOGGED_UTILITY_STREAM_H ) #define _FSNTFS_LOGGED_UTILITY_STREAM_H #include #include #if defined( __cplusplus ) extern "C" { #endif typedef struct fsntfs_logged_utility_stream fsntfs_logged_utility_stream_t; struct fsntfs_logged_utility_stream { /* The type and flags * Consists of 4 bytes */ uint8_t type[ 4 ]; /* The data size * Consists of 2 bytes */ uint8_t data_size[ 2 ]; /* Padding * Consists of 2 bytes */ uint8_t padding1[ 2 ]; }; #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFS_LOGGED_UTILITY_STREAM_H ) */ ================================================ FILE: libfsntfs/fsntfs_mft_attribute.h ================================================ /* * The NTFS Master File Table (MFT) attribute definition * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_MFT_ATTRIBUTE_H ) #define _FSNTFS_MFT_ATTRIBUTE_H #include #include #if defined( __cplusplus ) extern "C" { #endif typedef struct fsntfs_mft_attribute_header fsntfs_mft_attribute_header_t; struct fsntfs_mft_attribute_header { /* The type * Consists of 4 bytes */ uint8_t type[ 4 ]; /* The size * Consists of 4 bytes */ uint8_t size[ 4 ]; /* The non-resident flag * Consists of 1 byte */ uint8_t non_resident_flag; /* The name size * Consists of 1 byte */ uint8_t name_size; /* The name offset * Consists of 2 bytes */ uint8_t name_offset[ 2 ]; /* The data flags * Consists of 2 bytes */ uint8_t data_flags[ 2 ]; /* The identifier * Consists of 2 bytes */ uint8_t identifier[ 2 ]; }; typedef struct fsntfs_mft_attribute_resident fsntfs_mft_attribute_resident_t; struct fsntfs_mft_attribute_resident { /* The data size * Consists of 4 bytes */ uint8_t data_size[ 4 ]; /* The data offset * Consists of 2 bytes */ uint8_t data_offset[ 2 ]; /* The indexed flag * Consists of 1 byte */ uint8_t indexed_flag; /* Padding * Consists of 1 byte */ uint8_t padding; }; typedef struct fsntfs_mft_attribute_non_resident fsntfs_mft_attribute_non_resident_t; struct fsntfs_mft_attribute_non_resident { /* The data first virtual cluster number (VCN) * Consists of 8 bytes */ uint8_t data_first_vcn[ 8 ]; /* The data last virtual cluster number (VCN) * Consists of 8 bytes */ uint8_t data_last_vcn[ 8 ]; /* The data runs offset * Consists of 2 bytes */ uint8_t data_runs_offset[ 2 ]; /* The compression unit size * Consists of 2 bytes */ uint8_t compression_unit_size[ 2 ]; /* Padding * Consists of 4 bytes */ uint8_t padding[ 4 ]; /* The allocated data size * Consists of 8 bytes */ uint8_t allocated_data_size[ 8 ]; /* The data size * Consists of 8 bytes */ uint8_t data_size[ 8 ]; /* The valid data size * Consists of 8 bytes */ uint8_t valid_data_size[ 8 ]; }; typedef struct fsntfs_mft_attribute_non_resident_compressed fsntfs_mft_attribute_non_resident_compressed_t; struct fsntfs_mft_attribute_non_resident_compressed { /* The data first virtual cluster number (VCN) * Consists of 8 bytes */ uint8_t data_first_vcn[ 8 ]; /* The data last virtual cluster number (VCN) * Consists of 8 bytes */ uint8_t data_last_vcn[ 8 ]; /* The data runs offset * Consists of 2 bytes */ uint8_t data_runs_offset[ 2 ]; /* The compression unit size * Consists of 2 bytes */ uint8_t compression_unit_size[ 2 ]; /* Padding * Consists of 4 bytes */ uint8_t padding[ 4 ]; /* The allocated data size * Consists of 8 bytes */ uint8_t allocated_data_size[ 8 ]; /* The data size * Consists of 8 bytes */ uint8_t data_size[ 8 ]; /* The valid data size * Consists of 8 bytes */ uint8_t valid_data_size[ 8 ]; /* The total data size * Consists of 8 bytes */ uint8_t total_data_size[ 8 ]; }; #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFS_MFT_ATTRIBUTE_H ) */ ================================================ FILE: libfsntfs/fsntfs_mft_attribute_list.h ================================================ /* * The NTFS attribute list attribute ($ATTRIBUTE_LIST) definition * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_MFT_ATTRIBUTE_LIST_H ) #define _FSNTFS_MFT_ATTRIBUTE_LIST_H #include #include #if defined( __cplusplus ) extern "C" { #endif typedef struct fsntfs_mft_attribute_list_entry_header fsntfs_mft_attribute_list_entry_header_t; struct fsntfs_mft_attribute_list_entry_header { /* The type * Consists of 4 bytes */ uint8_t type[ 4 ]; /* The size * Consists of 2 bytes */ uint8_t size[ 2 ]; /* The name size * Consists of 1 byte */ uint8_t name_size; /* The name offset * Consists of 1 byte */ uint8_t name_offset; /* The data first Virtual Cluster Number (VCN) * Consists of 8 bytes */ uint8_t data_first_vcn[ 8 ]; /* The file reference * Consists of 8 bytes */ uint8_t file_reference[ 8 ]; /* The identifier * Consists of 2 bytes */ uint8_t identifier[ 2 ]; }; #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFS_MFT_ATTRIBUTE_LIST_H ) */ ================================================ FILE: libfsntfs/fsntfs_mft_entry.h ================================================ /* * The NTFS Master File Table (MFT) entry definition * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_MFT_ENTRY_H ) #define _FSNTFS_MFT_ENTRY_H #include #include #if defined( __cplusplus ) extern "C" { #endif typedef struct fsntfs_mft_entry_header fsntfs_mft_entry_header_t; struct fsntfs_mft_entry_header { /* The signature * Consists of 4 bytes * Contains: "FILE" */ uint8_t signature[ 4 ]; /* The fixup values offset * Consists of 2 bytes */ uint8_t fixup_values_offset[ 2 ]; /* The number of fixup values * Consists of 2 bytes */ uint8_t number_of_fixup_values[ 2 ]; /* The journal sequence number * Consists of 8 bytes */ uint8_t journal_sequence_number[ 8 ]; /* The sequence (value) * Consists of 2 bytes */ uint8_t sequence[ 2 ]; /* The reference (link) count * Consists of 2 bytes */ uint8_t reference_count[ 2 ]; /* The attributes offset * Consists of 2 bytes */ uint8_t attributes_offset[ 2 ]; /* The flags * Consists of 2 bytes */ uint8_t flags[ 2 ]; /* The used entry size * Consists of 4 bytes */ uint8_t used_entry_size[ 4 ]; /* The total entry size * Consists of 4 bytes */ uint8_t total_entry_size[ 4 ]; /* The base record file reference * Consists of 8 bytes */ uint8_t base_record_file_reference[ 8 ]; /* The first available attribute identifier * Consists of 2 bytes */ uint8_t first_available_attribute_identifier[ 2 ]; /* Unknown * Consists of 2 bytes */ uint8_t unknown1[ 2 ]; /* The index * Consists of 4 bytes */ uint8_t index[ 4 ]; }; #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFS_MFT_ENTRY_H ) */ ================================================ FILE: libfsntfs/fsntfs_object_identifier.h ================================================ /* * The NTFS object identifier attribute ($OBJECT_ID) definition * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_OBJECT_IDENTIFIER_H ) #define _FSNTFS_OBJECT_IDENTIFIER_H #include #include #if defined( __cplusplus ) extern "C" { #endif typedef struct fsntfs_object_identifier fsntfs_object_identifier_t; struct fsntfs_object_identifier { /* The droid file identifier * Consists of 16 bytes * Contains a GUID */ uint8_t droid_file_identifier[ 16 ]; /* The birth droid volume identifier * Consists of 16 bytes * Contains a GUID */ uint8_t birth_droid_volume_identifier[ 16 ]; /* The birth droid file identifier * Consists of 16 bytes * Contains a GUID */ uint8_t birth_droid_file_identifier[ 16 ]; /* The birth droid domain identifier * Consists of 16 bytes * Contains a GUID */ uint8_t birth_droid_domain_identifier[ 16 ]; }; #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFS_OBJECT_IDENTIFIER_H ) */ ================================================ FILE: libfsntfs/fsntfs_reparse_point.h ================================================ /* * The NTFS reparse point attribute ($REPARSE_POINT) definition * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_REPARSE_POINT_H ) #define _FSNTFS_REPARSE_POINT_H #include #include #if defined( __cplusplus ) extern "C" { #endif typedef struct fsntfs_reparse_point fsntfs_reparse_point_t; struct fsntfs_reparse_point { /* The tag (type and flags) * Consists of 4 bytes */ uint8_t tag[ 4 ]; /* The reparse data size * Consists of 2 bytes */ uint8_t reparse_data_size[ 2 ]; /* Padding * Consists of 2 bytes */ uint8_t padding1[ 2 ]; }; typedef struct fsntfs_mount_point_reparse_data fsntfs_mount_point_reparse_data_t; struct fsntfs_mount_point_reparse_data { /* The substitute name offset * Consists of 2 bytes */ uint8_t substitute_name_offset[ 2 ]; /* The substitute name size * Consists of 2 bytes */ uint8_t substitute_name_size[ 2 ]; /* The print name offset * Consists of 2 bytes */ uint8_t print_name_offset[ 2 ]; /* The print name size * Consists of 2 bytes */ uint8_t print_name_size[ 2 ]; }; typedef struct fsntfs_symbolic_link_reparse_data fsntfs_symbolic_link_reparse_data_t; struct fsntfs_symbolic_link_reparse_data { /* The substitute name offset * Consists of 2 bytes */ uint8_t substitute_name_offset[ 2 ]; /* The substitute name size * Consists of 2 bytes */ uint8_t substitute_name_size[ 2 ]; /* The print name offset * Consists of 2 bytes */ uint8_t print_name_offset[ 2 ]; /* The print name size * Consists of 2 bytes */ uint8_t print_name_size[ 2 ]; /* The flags * Consists of 4 bytes */ uint8_t flags[ 4 ]; }; #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFS_REPARSE_POINT_H ) */ ================================================ FILE: libfsntfs/fsntfs_secure.h ================================================ /* * The NTFS $Secure definitions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_SECURE_H ) #define _FSNTFS_SECURE_H #include #include #if defined( __cplusplus ) extern "C" { #endif typedef struct fsntfs_secure_hash_index_key fsntfs_secure_hash_index_key_t; struct fsntfs_secure_hash_index_key { /* The hash * Consists of 4 bytes */ uint8_t hash[ 4 ]; /* The identifier * Consists of 4 bytes */ uint8_t identifier[ 4 ]; }; typedef struct fsntfs_secure_identifier_index_key fsntfs_secure_identifier_index_key_t; struct fsntfs_secure_identifier_index_key { /* The identifier * Consists of 4 bytes */ uint8_t identifier[ 4 ]; }; typedef struct fsntfs_secure_index_value fsntfs_secure_index_value_t; struct fsntfs_secure_index_value { /* The hash * Consists of 4 bytes */ uint8_t hash[ 4 ]; /* The identifier * Consists of 4 bytes */ uint8_t identifier[ 4 ]; /* The data offset * Consists of 8 bytes */ uint8_t data_offset[ 8 ]; /* The data size * Consists of 4 bytes */ uint8_t data_size[ 4 ]; }; #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFS_SECURE_H ) */ ================================================ FILE: libfsntfs/fsntfs_standard_information.h ================================================ /* * The NTFS standard information attribute ($STANDARD_INFORMATION) definition * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_STANDARD_INFORMATION_H ) #define _FSNTFS_STANDARD_INFORMATION_H #include #include #if defined( __cplusplus ) extern "C" { #endif typedef struct fsntfs_standard_information fsntfs_standard_information_t; struct fsntfs_standard_information { /* The creation date and time * Consists of 8 bytes * Contains a filetime */ uint8_t creation_time[ 8 ]; /* The last modification date and time * Consists of 8 bytes * Contains a filetime */ uint8_t modification_time[ 8 ]; /* The entry last modification date and time * Consists of 8 bytes * Contains a filetime */ uint8_t entry_modification_time[ 8 ]; /* The last access date and time * Consists of 8 bytes * Contains a filetime */ uint8_t access_time[ 8 ]; /* The file attribute flags * Consists of 4 bytes */ uint8_t file_attribute_flags[ 4 ]; /* The maximum number of versions * Consists of 4 bytes */ uint8_t maximum_number_of_versions[ 4 ]; /* The version number * Consists of 4 bytes */ uint8_t version_number[ 4 ]; /* The class identifier * Consists of 4 bytes */ uint8_t class_identifier[ 4 ]; /* The owner identifier * Consists of 4 bytes */ uint8_t owner_identifier[ 4 ]; /* The security descriptor identifier * Consists of 4 bytes */ uint8_t security_descriptor_identifier[ 4 ]; /* The quota charged * Consists of 8 bytes */ uint8_t quota_charged[ 8 ]; /* The update sequence number (USN) * Consists of 8 bytes */ uint8_t update_sequence_number[ 8 ]; }; #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFS_STANDARD_INFORMATION_H ) */ ================================================ FILE: libfsntfs/fsntfs_txf_data.h ================================================ /* * The Transactional NTFS (TxF) data ($TXF_DATA) logged utility stream * attribute ($LOGGED_UTILITY_STREAM) definition * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_TXF_DATA_H ) #define _FSNTFS_TXF_DATA_H #include #include #if defined( __cplusplus ) extern "C" { #endif typedef struct fsntfs_txf_data fsntfs_txf_data_t; struct fsntfs_txf_data { /* Unknown * Consists of 6 bytes */ uint8_t unknown1[ 6 ]; /* The resource manager root file reference * Consists of 8 bytes */ uint8_t rm_root_file_reference[ 8 ]; /* The USN index * Consists of 8 bytes */ uint8_t usn_index[ 8 ]; /* The file identifier * Consists of 8 bytes */ uint8_t file_identifier[ 8 ]; /* The file data LSN * Consists of 8 bytes */ uint8_t data_lsn[ 8 ]; /* The file system metadata LSN * Consists of 8 bytes */ uint8_t metadata_lsn[ 8 ]; /* The directory index LSN * Consists of 8 bytes */ uint8_t directory_index_lsn[ 8 ]; /* The flags * Consists of 2 bytes */ uint8_t flags[ 2 ]; }; #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFS_TXF_DATA_H ) */ ================================================ FILE: libfsntfs/fsntfs_volume_header.h ================================================ /* * The NTFS volume header definition * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_VOLUME_HEADER_H ) #define _FSNTFS_VOLUME_HEADER_H #include #include #if defined( __cplusplus ) extern "C" { #endif typedef struct fsntfs_volume_header fsntfs_volume_header_t; struct fsntfs_volume_header { /* Boot entry point * Consists of 3 bytes * Contains a jump instruction to the boot loader */ uint8_t boot_entry_point[ 3 ]; /* The file system signature * Consists of 8 bytes * Contains: "NTFS\x20\x20\x20\x20" */ uint8_t file_system_signature[ 8 ]; /* The number of bytes per sector * Consists of 2 bytes */ uint8_t bytes_per_sector[ 2 ]; /* The number of sectors per cluster block * Consists of 1 byte */ uint8_t sectors_per_cluster_block; /* Unknown * Consists of 7 bytes */ uint8_t unknown1[ 7 ]; /* The media descriptor * Consists of 1 byte */ uint8_t media_descriptor; /* Unknown * Consists of 2 bytes */ uint8_t unknown2[ 2 ]; /* The number of sectors per track * Consists of 2 bytes */ uint8_t sectors_per_track[ 2 ]; /* The number of heads * Consists of 2 bytes */ uint8_t number_of_heads[ 2 ]; /* The number of hidden sectors * Consists of 4 bytes */ uint8_t number_of_hidden_sectors[ 4 ]; /* Unknown * Consists of 4 bytes */ uint8_t unknown3[ 4 ]; /* Unknown * Consists of 4 bytes */ uint8_t unknown4[ 4 ]; /* The total number of sectors * Consists of 8 bytes */ uint8_t total_number_of_sectors[ 8 ]; /* The master file table (MFT) cluster block number * Consists of 8 bytes */ uint8_t mft_cluster_block_number[ 8 ]; /* The mirror MFT cluster block number * Consists of 8 bytes */ uint8_t mirror_mft_cluster_block_number[ 8 ]; /* The MFT entry size * Consists of 4 bytes * Contains the number of cluster blocks or a byte size */ uint8_t mft_entry_size[ 4 ]; /* The index entry size * Consists of 4 bytes * Contains the number of cluster blocks or a byte size */ uint8_t index_entry_size[ 4 ]; /* The volume serial number * Consists of 8 bytes */ uint8_t volume_serial_number[ 8 ]; /* The checksum * Consists of 4 bytes */ uint8_t checksum[ 4 ]; /* The bootcode * Consists of 426 bytes */ uint8_t bootcode[ 426 ]; /* The sector signature * Consists of 2 bytes * Contains: 0x55 0xaa */ uint8_t sector_signature[ 2 ]; }; #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFS_VOLUME_HEADER_H ) */ ================================================ FILE: libfsntfs/fsntfs_volume_information.h ================================================ /* * The NTFS volume information attribute ($VOLUME_INFORMATION) definition * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_VOLUME_INFORMATION_H ) #define _FSNTFS_VOLUME_INFORMATION_H #include #include #if defined( __cplusplus ) extern "C" { #endif typedef struct fsntfs_volume_information fsntfs_volume_information_t; struct fsntfs_volume_information { /* Unknown * Consists of 8 bytes */ uint8_t unknown1[ 8 ]; /* The major version (number) * Consists of 1 byte */ uint8_t major_version; /* The minor version (number) * Consists of 1 byte */ uint8_t minor_version; /* The flags * Consists of 2 bytes */ uint8_t flags[ 2 ]; }; #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFS_VOLUME_INFORMATION_H ) */ ================================================ FILE: libfsntfs/libfsntfs.c ================================================ /* * Library to access the New Technology File System (NTFS) format * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #if defined( WINAPI ) #include #endif #include "libfsntfs_unused.h" /* Define HAVE_LOCAL_LIBFSNTFS for local use of libfsntfs */ #if !defined( HAVE_LOCAL_LIBFSNTFS ) #if defined( WINAPI ) && defined( HAVE_DLLMAIN ) #if defined( _MANAGED ) #pragma managed( push, off ) #endif /* Defines the entry point for the DLL */ BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) { LIBFSNTFS_UNREFERENCED_PARAMETER( lpvReserved ) switch( fdwReason ) { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls( hinstDLL ); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } return( TRUE ); } /* Function that indicates the library is a DLL * Returns 1 */ int libfsntfs_is_dll( void ) { return( 1 ); } #endif /* defined( WINAPI ) && defined( HAVE_DLLMAIN ) */ #endif /* !defined( HAVE_LOCAL_LIBFSNTFS ) */ ================================================ FILE: libfsntfs/libfsntfs.rc.in ================================================ #include #ifdef GCC_WINDRES VS_VERSION_INFO VERSIONINFO #else VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE #endif FILEVERSION 1,0,0,0 PRODUCTVERSION 1,0,0,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS VOS__WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "FileDescription", "Library to access the New Technology File System (NTFS) format\0" VALUE "FileVersion", "@VERSION@" "\0" VALUE "InternalName", "libfsntfs.dll\0" VALUE "LegalCopyright", "(C) 2010-2026, Joachim Metz \0" VALUE "OriginalFilename", "libfsntfs.dll\0" VALUE "ProductName", "libfsntfs\0" VALUE "ProductVersion", "@VERSION@" "\0" VALUE "Comments", "For more information visit https://github.com/libyal/libfsntfs/\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0409, 1200 END END ================================================ FILE: libfsntfs/libfsntfs_attribute.c ================================================ /* * Attribute functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_attribute.h" #include "libfsntfs_bitmap_values.h" #include "libfsntfs_data_run.h" #include "libfsntfs_debug.h" #include "libfsntfs_definitions.h" #include "libfsntfs_file_name_values.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_logged_utility_stream_values.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_object_identifier_values.h" #include "libfsntfs_path_hint.h" #include "libfsntfs_reparse_point_values.h" #include "libfsntfs_security_descriptor_values.h" #include "libfsntfs_standard_information_values.h" #include "libfsntfs_txf_data_values.h" #include "libfsntfs_types.h" #include "libfsntfs_unused.h" #include "libfsntfs_volume_information_values.h" #include "libfsntfs_volume_name_values.h" /* Creates an attribute * Make sure the value attribute is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_initialize( libfsntfs_attribute_t **attribute, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_attribute_initialize"; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( *attribute != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid attribute value already set.", function ); return( -1 ); } if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } internal_attribute = memory_allocate_structure( libfsntfs_internal_attribute_t ); if( internal_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create attribute.", function ); goto on_error; } if( memory_set( internal_attribute, 0, sizeof( libfsntfs_internal_attribute_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear attribute.", function ); memory_free( internal_attribute ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_initialize( &( internal_attribute->read_write_lock ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize read/write lock.", function ); goto on_error; } #endif internal_attribute->mft_attribute = mft_attribute; *attribute = (libfsntfs_attribute_t *) internal_attribute; return( 1 ); on_error: if( internal_attribute != NULL ) { memory_free( internal_attribute ); } return( -1 ); } /* Frees an attribute * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_free( libfsntfs_attribute_t **attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_attribute_free"; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( *attribute != NULL ) { *attribute = NULL; } return( 1 ); } /* Frees an attribute * Returns 1 if successful or -1 on error */ int libfsntfs_internal_attribute_free( libfsntfs_internal_attribute_t **internal_attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_internal_attribute_free"; int result = 1; if( internal_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( *internal_attribute != NULL ) { /* The mft_attribute reference is freed elsewhere */ #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_free( &( ( *internal_attribute )->read_write_lock ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free read/write lock.", function ); result = -1; } #endif if( ( *internal_attribute )->path_hint != NULL ) { if( libfsntfs_path_hint_free( &( ( *internal_attribute )->path_hint ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free attribute path hint.", function ); result = -1; } } if( ( *internal_attribute )->value != NULL ) { if( ( *internal_attribute )->free_value != NULL ) { if( ( *internal_attribute )->free_value( &( ( *internal_attribute )->value ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free attribute value.", function ); result = -1; } } } memory_free( *internal_attribute ); *internal_attribute = NULL; } return( result ); } /* Reads the attribute value * Returns 1 if successful or -1 on error */ int libfsntfs_internal_attribute_read_value( libfsntfs_internal_attribute_t *internal_attribute, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, uint8_t flags, libcerror_error_t **error ) { static char *function = "libfsntfs_internal_attribute_read_value"; uint32_t attribute_type = 0; int result = 0; if( internal_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( internal_attribute->value != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid attribute - value already set.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve type from attribute.", function ); goto on_error; } switch( attribute_type ) { case LIBFSNTFS_ATTRIBUTE_TYPE_BITMAP: internal_attribute->free_value = (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_bitmap_values_free; if( libfsntfs_bitmap_values_initialize( (libfsntfs_bitmap_values_t **) &( internal_attribute->value ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create bitmap values.", function ); goto on_error; } if( libfsntfs_bitmap_values_read_from_mft_attribute( (libfsntfs_bitmap_values_t *) internal_attribute->value, internal_attribute->mft_attribute, io_handle, file_io_handle, io_handle->cluster_block_size, flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read bitmap values.", function ); goto on_error; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME: internal_attribute->free_value = (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_file_name_values_free; if( libfsntfs_file_name_values_initialize( (libfsntfs_file_name_values_t **) &( internal_attribute->value ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file name values.", function ); goto on_error; } if( libfsntfs_file_name_values_read_from_mft_attribute( (libfsntfs_file_name_values_t *) internal_attribute->value, internal_attribute->mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read file name values.", function ); goto on_error; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_LOGGED_UTILITY_STREAM: result = libfsntfs_mft_attribute_compare_name_with_utf8_string( internal_attribute->mft_attribute, (uint8_t *) "$TXF_DATA", 9, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GENERIC, "%s: unable to compare UTF-8 string with attribute name.", function ); goto on_error; } else if( result != 0 ) { internal_attribute->free_value = (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_txf_data_values_free; if( libfsntfs_txf_data_values_initialize( (libfsntfs_txf_data_values_t **) &( internal_attribute->value ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create TxF data values.", function ); goto on_error; } if( libfsntfs_txf_data_values_read_from_mft_attribute( (libfsntfs_txf_data_values_t *) internal_attribute->value, internal_attribute->mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read TxF data values.", function ); goto on_error; } } else { internal_attribute->free_value = (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_logged_utility_stream_values_free; if( libfsntfs_logged_utility_stream_values_initialize( (libfsntfs_logged_utility_stream_values_t **) &( internal_attribute->value ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create logged utility stream values.", function ); goto on_error; } if( libfsntfs_logged_utility_stream_values_read_from_mft_attribute( (libfsntfs_logged_utility_stream_values_t *) internal_attribute->value, internal_attribute->mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read logged utility stream values.", function ); goto on_error; } } break; case LIBFSNTFS_ATTRIBUTE_TYPE_OBJECT_IDENTIFIER: internal_attribute->free_value = (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_object_identifier_values_free; if( libfsntfs_object_identifier_values_initialize( (libfsntfs_object_identifier_values_t **) &( internal_attribute->value ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create object identifier values.", function ); goto on_error; } if( libfsntfs_object_identifier_values_read_from_mft_attribute( (libfsntfs_object_identifier_values_t *) internal_attribute->value, internal_attribute->mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read object identifier values.", function ); goto on_error; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT: internal_attribute->free_value = (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_reparse_point_values_free; if( libfsntfs_reparse_point_values_initialize( (libfsntfs_reparse_point_values_t **) &( internal_attribute->value ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create reparse point values.", function ); goto on_error; } if( libfsntfs_reparse_point_values_read_from_mft_attribute( (libfsntfs_reparse_point_values_t *) internal_attribute->value, internal_attribute->mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read reparse point values.", function ); goto on_error; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_SECURITY_DESCRIPTOR: internal_attribute->free_value = (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_security_descriptor_values_free; if( libfsntfs_security_descriptor_values_initialize( (libfsntfs_security_descriptor_values_t **) &( internal_attribute->value ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create security descriptor values.", function ); goto on_error; } if( libfsntfs_security_descriptor_values_read_from_mft_attribute( (libfsntfs_security_descriptor_values_t *) internal_attribute->value, internal_attribute->mft_attribute, io_handle, file_io_handle, flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read security descriptor values.", function ); goto on_error; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION: internal_attribute->free_value = (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_standard_information_values_free; if( libfsntfs_standard_information_values_initialize( (libfsntfs_standard_information_values_t **) &( internal_attribute->value ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create standard information values.", function ); goto on_error; } if( libfsntfs_standard_information_values_read_from_mft_attribute( (libfsntfs_standard_information_values_t *) internal_attribute->value, internal_attribute->mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read standard information values.", function ); goto on_error; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_INFORMATION: internal_attribute->free_value = (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_volume_information_values_free; if( libfsntfs_volume_information_values_initialize( (libfsntfs_volume_information_values_t **) &( internal_attribute->value ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create volume information values.", function ); goto on_error; } if( libfsntfs_volume_information_values_read_from_mft_attribute( (libfsntfs_volume_information_values_t *) internal_attribute->value, internal_attribute->mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read volume information values.", function ); goto on_error; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME: internal_attribute->free_value = (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_volume_name_values_free; if( libfsntfs_volume_name_values_initialize( (libfsntfs_volume_name_values_t **) &( internal_attribute->value ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create volume name values.", function ); goto on_error; } if( libfsntfs_volume_name_values_read_from_mft_attribute( (libfsntfs_volume_name_values_t *) internal_attribute->value, internal_attribute->mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read volume name values.", function ); goto on_error; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ALLOCATION: case LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ROOT: default: break; } return( 1 ); on_error: if( ( internal_attribute->value != NULL ) && ( internal_attribute->free_value != NULL ) ) { internal_attribute->free_value( &( internal_attribute->value ), NULL ); } return( -1 ); } /* Retrieves the type * Returns 1 if successful or -1 on error */ int libfsntfs_internal_attribute_get_type( libfsntfs_internal_attribute_t *internal_attribute, uint32_t *type, libcerror_error_t **error ) { static char *function = "libfsntfs_internal_attribute_get_type"; if( internal_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_type( internal_attribute->mft_attribute, type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve type from MFT attribute.", function ); return( -1 ); } return( 1 ); } /* Retrieves the type * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_get_type( libfsntfs_attribute_t *attribute, uint32_t *type, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_attribute_get_type"; int result = 1; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_internal_attribute_get_type( internal_attribute, type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve type.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the data flags * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_get_data_flags( libfsntfs_attribute_t *attribute, uint16_t *data_flags, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_attribute_get_data_flags"; uint16_t safe_data_flags = 0; int result = 1; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( data_flags == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data flags.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_attribute->mft_attribute != NULL ) { if( libfsntfs_mft_attribute_get_data_flags( internal_attribute->mft_attribute, &safe_data_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data flags from MFT attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif if( result == 1 ) { *data_flags = safe_data_flags; } return( result ); } /* Retrieves the value * Returns 1 if successful or -1 on error */ int libfsntfs_internal_attribute_get_value( libfsntfs_internal_attribute_t *internal_attribute, intptr_t **value, libcerror_error_t **error ) { static char *function = "libfsntfs_internal_attribute_get_value"; if( internal_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid value.", function ); return( -1 ); } *value = internal_attribute->value; return( 1 ); } /* Retrieves the size of the UTF-8 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_get_utf8_name_size( libfsntfs_attribute_t *attribute, size_t *utf8_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_attribute_get_utf8_name_size"; int result = 1; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_attribute_get_utf8_name_size( internal_attribute->mft_attribute, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 name size from MFT attribute.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the UTF-8 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_get_utf8_name( libfsntfs_attribute_t *attribute, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_attribute_get_utf8_name"; int result = 1; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_attribute_get_utf8_name( internal_attribute->mft_attribute, utf8_string, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 name from MFT attribute.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the size of the UTF-16 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_get_utf16_name_size( libfsntfs_attribute_t *attribute, size_t *utf16_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_attribute_get_utf16_name_size"; int result = 1; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_attribute_get_utf16_name_size( internal_attribute->mft_attribute, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 name size from MFT attribute.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the UTF-16 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_get_utf16_name( libfsntfs_attribute_t *attribute, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_attribute_get_utf16_name"; int result = 1; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_attribute_get_utf16_name( internal_attribute->mft_attribute, utf16_string, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 name from MFT attribute.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the data VCN range * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_attribute_get_data_vcn_range( libfsntfs_attribute_t *attribute, uint64_t *data_first_vcn, uint64_t *data_last_vcn, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_attribute_get_data_vcn_range"; int result = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( data_first_vcn == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data first VCN.", function ); return( -1 ); } if( data_last_vcn == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data last VCN.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_attribute->mft_attribute != NULL ) { result = libfsntfs_mft_attribute_get_data_vcn_range( internal_attribute->mft_attribute, data_first_vcn, data_last_vcn, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data VCN range from MFT attribute.", function ); result = -1; } } /* TODO add support for attribute list entry ? */ #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the data size * Returns 1 if successful or -1 on error */ int libfsntfs_internal_attribute_get_data_size( libfsntfs_internal_attribute_t *internal_attribute, size64_t *data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_internal_attribute_get_data_size"; if( internal_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( internal_attribute->mft_attribute != NULL ) { if( libfsntfs_mft_attribute_get_data_size( internal_attribute->mft_attribute, (uint64_t *) data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data size.", function ); return( -1 ); } } else { if( data_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data size.", function ); return( -1 ); } *data_size = 0; } return( 1 ); } /* Retrieves the data size * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_get_data_size( libfsntfs_attribute_t *attribute, size64_t *data_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_attribute_get_data_size"; int result = 1; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_internal_attribute_get_data_size( internal_attribute, data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data size.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the valid data size * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_get_valid_data_size( libfsntfs_attribute_t *attribute, size64_t *valid_data_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_attribute_get_valid_data_size"; uint64_t safe_valid_data_size = 0; int result = 1; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( valid_data_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid valid data size.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_attribute->mft_attribute != NULL ) { if( libfsntfs_mft_attribute_get_valid_data_size( internal_attribute->mft_attribute, &safe_valid_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve valid data size.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif if( result == 1 ) { *valid_data_size = safe_valid_data_size; } return( result ); } ================================================ FILE: libfsntfs/libfsntfs_attribute.h ================================================ /* * Attribute functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_ATTRIBUTE_H ) #define _LIBFSNTFS_ATTRIBUTE_H #include #include #include "libfsntfs_data_run.h" #include "libfsntfs_extern.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_path_hint.h" #include "libfsntfs_types.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_internal_attribute libfsntfs_internal_attribute_t; struct libfsntfs_internal_attribute { /* The MFT attribute */ libfsntfs_mft_attribute_t *mft_attribute; /* The path hint */ libfsntfs_path_hint_t *path_hint; /* The item value */ intptr_t *value; /* The item free value function */ int (*free_value)( intptr_t **value, libcerror_error_t **error ); #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) /* The read/write lock */ libcthreads_read_write_lock_t *read_write_lock; #endif }; int libfsntfs_attribute_initialize( libfsntfs_attribute_t **attribute, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_attribute_free( libfsntfs_attribute_t **attribute, libcerror_error_t **error ); int libfsntfs_internal_attribute_free( libfsntfs_internal_attribute_t **internal_attribute, libcerror_error_t **error ); int libfsntfs_internal_attribute_read_value( libfsntfs_internal_attribute_t *internal_attribute, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, uint8_t flags, libcerror_error_t **error ); int libfsntfs_internal_attribute_get_type( libfsntfs_internal_attribute_t *internal_attribute, uint32_t *type, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_attribute_get_type( libfsntfs_attribute_t *attribute, uint32_t *type, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_attribute_get_data_flags( libfsntfs_attribute_t *attribute, uint16_t *data_flags, libcerror_error_t **error ); int libfsntfs_internal_attribute_get_value( libfsntfs_internal_attribute_t *internal_attribute, intptr_t **value, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_attribute_get_utf8_name_size( libfsntfs_attribute_t *attribute, size_t *utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_attribute_get_utf8_name( libfsntfs_attribute_t *attribute, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_attribute_get_utf16_name_size( libfsntfs_attribute_t *attribute, size_t *utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_attribute_get_utf16_name( libfsntfs_attribute_t *attribute, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_attribute_get_data_vcn_range( libfsntfs_attribute_t *attribute, uint64_t *data_first_vcn, uint64_t *data_last_vcn, libcerror_error_t **error ); int libfsntfs_internal_attribute_get_data_size( libfsntfs_internal_attribute_t *internal_attribute, size64_t *data_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_attribute_get_data_size( libfsntfs_attribute_t *attribute, size64_t *data_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_attribute_get_valid_data_size( libfsntfs_attribute_t *attribute, size64_t *valid_data_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_ATTRIBUTE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_attribute_list_attribute.c ================================================ /* * Attribute list attribute ($ATTRIBUTE_LIST) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_attribute.h" #include "libfsntfs_attribute_list_attribute.h" #include "libfsntfs_attribute_list_entry.h" #include "libfsntfs_definitions.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_mft_attribute_list.h" #include "libfsntfs_mft_attribute_list_entry.h" #include "libfsntfs_types.h" /* Retrieves the number of attribute list entries * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_list_attribute_get_number_of_entries( libfsntfs_attribute_t *attribute, int *number_of_entries, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_attribute_list_attribute_get_number_of_entries"; uint32_t attribute_type = 0; int result = 1; int safe_number_of_entries = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( number_of_entries == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid number of entries.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); result = -1; } else if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_ATTRIBUTE_LIST ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); result = -1; } else if( internal_attribute->value != NULL ) { if( libfsntfs_mft_attribute_list_get_number_of_entries( (libfsntfs_mft_attribute_list_t *) internal_attribute->value, &safe_number_of_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of attribute list entries.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif if( result == 1 ) { *number_of_entries = safe_number_of_entries; } return( result ); } /* Retrieves a specific attribute list entry * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_list_attribute_get_entry_by_index( libfsntfs_attribute_t *attribute, int entry_index, libfsntfs_attribute_list_entry_t **attribute_list_entry, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry = NULL; static char *function = "libfsntfs_attribute_list_attribute_get_entry_by_index"; uint32_t attribute_type = 0; int result = 1; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); result = -1; } else if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_ATTRIBUTE_LIST ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); result = -1; } else if( internal_attribute->value != NULL ) { if( libfsntfs_mft_attribute_list_get_entry_by_index( (libfsntfs_mft_attribute_list_t *) internal_attribute->value, entry_index, &mft_attribute_list_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute list entry: %d.", function, entry_index ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_attribute->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif if( result == 1 ) { if( libfsntfs_attribute_list_entry_initialize( attribute_list_entry, mft_attribute_list_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create attribute list entry: %d.", function, entry_index ); result = -1; } } return( result ); } ================================================ FILE: libfsntfs/libfsntfs_attribute_list_attribute.h ================================================ /* * Attribute list attribute ($ATTRIBUTE_LIST) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_ATTRIBUTE_LIST_ATTRIBUTE_H ) #define _LIBFSNTFS_ATTRIBUTE_LIST_ATTRIBUTE_H #include #include #include "libfsntfs_extern.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_types.h" #if defined( __cplusplus ) extern "C" { #endif LIBFSNTFS_EXTERN \ int libfsntfs_attribute_list_attribute_get_number_of_entries( libfsntfs_attribute_t *attribute, int *number_of_entries, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_attribute_list_attribute_get_entry_by_index( libfsntfs_attribute_t *attribute, int entry_index, libfsntfs_attribute_list_entry_t **attribute_list_entry, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_ATTRIBUTE_LIST_ATTRIBUTE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_attribute_list_entry.c ================================================ /* * Attribute list entry functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_attribute_list_entry.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_mft_attribute_list_entry.h" #include "libfsntfs_types.h" /* Creates an attribute list entry * Make sure the value attribute_list_entry is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_list_entry_initialize( libfsntfs_attribute_list_entry_t **attribute_list_entry, libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry, libcerror_error_t **error ) { libfsntfs_internal_attribute_list_entry_t *internal_attribute_list_entry = NULL; static char *function = "libfsntfs_attribute_list_entry_initialize"; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list entry.", function ); return( -1 ); } if( *attribute_list_entry != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid attribute list entry value already set.", function ); return( -1 ); } if( mft_attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute list entry.", function ); return( -1 ); } internal_attribute_list_entry = memory_allocate_structure( libfsntfs_internal_attribute_list_entry_t ); if( internal_attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create attribute list entry.", function ); goto on_error; } if( memory_set( internal_attribute_list_entry, 0, sizeof( libfsntfs_internal_attribute_list_entry_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear attribute list entry.", function ); memory_free( internal_attribute_list_entry ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_initialize( &( internal_attribute_list_entry->read_write_lock ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize read/write lock.", function ); goto on_error; } #endif internal_attribute_list_entry->mft_attribute_list_entry = mft_attribute_list_entry; *attribute_list_entry = (libfsntfs_attribute_list_entry_t *) internal_attribute_list_entry; return( 1 ); on_error: if( internal_attribute_list_entry != NULL ) { memory_free( internal_attribute_list_entry ); } return( -1 ); } /* Frees an attribute list entry * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_list_entry_free( libfsntfs_attribute_list_entry_t **attribute_list_entry, libcerror_error_t **error ) { libfsntfs_internal_attribute_list_entry_t *internal_attribute_list_entry = NULL; static char *function = "libfsntfs_attribute_list_entry_free"; int result = 1; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list entry.", function ); return( -1 ); } if( *attribute_list_entry != NULL ) { internal_attribute_list_entry = (libfsntfs_internal_attribute_list_entry_t *) *attribute_list_entry; *attribute_list_entry = NULL; /* The mft_attribute_list_entry references is freed elsewhere */ #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_free( &( internal_attribute_list_entry->read_write_lock ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free read/write lock.", function ); result = -1; } #endif memory_free( internal_attribute_list_entry ); } return( result ); } /* Retrieves the attribute type * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_list_entry_get_attribute_type( libfsntfs_attribute_list_entry_t *attribute_list_entry, uint32_t *attribute_type, libcerror_error_t **error ) { libfsntfs_internal_attribute_list_entry_t *internal_attribute_list_entry = NULL; static char *function = "libfsntfs_attribute_list_entry_get_type"; int result = 1; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list entry.", function ); return( -1 ); } internal_attribute_list_entry = (libfsntfs_internal_attribute_list_entry_t *) attribute_list_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_attribute_list_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_attribute_list_entry_get_attribute_type( internal_attribute_list_entry->mft_attribute_list_entry, attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_attribute_list_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the file reference * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_list_entry_get_file_reference( libfsntfs_attribute_list_entry_t *attribute_list_entry, uint64_t *file_reference, libcerror_error_t **error ) { libfsntfs_internal_attribute_list_entry_t *internal_attribute_list_entry = NULL; static char *function = "libfsntfs_attribute_list_entry_get_type"; int result = 1; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list entry.", function ); return( -1 ); } internal_attribute_list_entry = (libfsntfs_internal_attribute_list_entry_t *) attribute_list_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_attribute_list_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_attribute_list_entry_get_file_reference( internal_attribute_list_entry->mft_attribute_list_entry, file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file reference.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_attribute_list_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the size of the UTF-8 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_list_entry_get_utf8_name_size( libfsntfs_attribute_list_entry_t *attribute_list_entry, size_t *utf8_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_list_entry_t *internal_attribute_list_entry = NULL; static char *function = "libfsntfs_attribute_list_entry_get_utf8_name_size"; int result = 1; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list entry.", function ); return( -1 ); } internal_attribute_list_entry = (libfsntfs_internal_attribute_list_entry_t *) attribute_list_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_attribute_list_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_attribute_list_entry_get_utf8_name_size( internal_attribute_list_entry->mft_attribute_list_entry, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 name size from attribute list entry.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_attribute_list_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the UTF-8 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_list_entry_get_utf8_name( libfsntfs_attribute_list_entry_t *attribute_list_entry, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_list_entry_t *internal_attribute_list_entry = NULL; static char *function = "libfsntfs_attribute_list_entry_get_utf8_name"; int result = 1; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list entry.", function ); return( -1 ); } internal_attribute_list_entry = (libfsntfs_internal_attribute_list_entry_t *) attribute_list_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_attribute_list_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_attribute_list_entry_get_utf8_name( internal_attribute_list_entry->mft_attribute_list_entry, utf8_string, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 name from attribute list entry.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_attribute_list_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the size of the UTF-16 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_list_entry_get_utf16_name_size( libfsntfs_attribute_list_entry_t *attribute_list_entry, size_t *utf16_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_list_entry_t *internal_attribute_list_entry = NULL; static char *function = "libfsntfs_attribute_list_entry_get_utf16_name_size"; int result = 1; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list entry.", function ); return( -1 ); } internal_attribute_list_entry = (libfsntfs_internal_attribute_list_entry_t *) attribute_list_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_attribute_list_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_attribute_list_entry_get_utf16_name_size( internal_attribute_list_entry->mft_attribute_list_entry, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 name size from attribute list entry.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_attribute_list_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the UTF-16 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_attribute_list_entry_get_utf16_name( libfsntfs_attribute_list_entry_t *attribute_list_entry, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_list_entry_t *internal_attribute_list_entry = NULL; static char *function = "libfsntfs_attribute_list_entry_get_utf16_name"; int result = 1; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list entry.", function ); return( -1 ); } internal_attribute_list_entry = (libfsntfs_internal_attribute_list_entry_t *) attribute_list_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_attribute_list_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_attribute_list_entry_get_utf16_name( internal_attribute_list_entry->mft_attribute_list_entry, utf16_string, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 name from attribute list entry.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_attribute_list_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } ================================================ FILE: libfsntfs/libfsntfs_attribute_list_entry.h ================================================ /* * Attribute list entry functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_ATTRIBUTE_LIST_ENTRY_H ) #define _LIBFSNTFS_ATTRIBUTE_LIST_ENTRY_H #include #include #include "libfsntfs_extern.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_mft_attribute_list_entry.h" #include "libfsntfs_types.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_internal_attribute_list_entry libfsntfs_internal_attribute_list_entry_t; struct libfsntfs_internal_attribute_list_entry { /* The MFT attribute list entry */ libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) /* The read/write lock */ libcthreads_read_write_lock_t *read_write_lock; #endif }; int libfsntfs_attribute_list_entry_initialize( libfsntfs_attribute_list_entry_t **attribute_list_entry, libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_attribute_list_entry_free( libfsntfs_attribute_list_entry_t **attribute_list_entry, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_attribute_list_entry_get_attribute_type( libfsntfs_attribute_list_entry_t *attribute_list_entry, uint32_t *attribute_type, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_attribute_list_entry_get_file_reference( libfsntfs_attribute_list_entry_t *attribute_list_entry, uint64_t *file_reference, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_attribute_list_entry_get_utf8_name_size( libfsntfs_attribute_list_entry_t *attribute_list_entry, size_t *utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_attribute_list_entry_get_utf8_name( libfsntfs_attribute_list_entry_t *attribute_list_entry, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_attribute_list_entry_get_utf16_name_size( libfsntfs_attribute_list_entry_t *attribute_list_entry, size_t *utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_attribute_list_entry_get_utf16_name( libfsntfs_attribute_list_entry_t *attribute_list_entry, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_ATTRIBUTE_LIST_ENTRY_H ) */ ================================================ FILE: libfsntfs/libfsntfs_bitmap_values.c ================================================ /* * Bitmap attribute ($BITMAP) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_bitmap_values.h" #include "libfsntfs_cluster_block.h" #include "libfsntfs_cluster_block_vector.h" #include "libfsntfs_definitions.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libfcache.h" #include "libfsntfs_libfdata.h" /* Creates bitmap values * Make sure the value bitmap_values is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_bitmap_values_initialize( libfsntfs_bitmap_values_t **bitmap_values, libcerror_error_t **error ) { static char *function = "libfsntfs_bitmap_values_initialize"; if( bitmap_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid bitmap values.", function ); return( -1 ); } if( *bitmap_values != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid bitmap values value already set.", function ); return( -1 ); } *bitmap_values = memory_allocate_structure( libfsntfs_bitmap_values_t ); if( *bitmap_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create bitmap values.", function ); goto on_error; } if( memory_set( *bitmap_values, 0, sizeof( libfsntfs_bitmap_values_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear bitmap values.", function ); memory_free( *bitmap_values ); *bitmap_values = NULL; return( -1 ); } if( libcdata_range_list_initialize( &( ( *bitmap_values )->allocated_block_list ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create allocated block list.", function ); goto on_error; } return( 1 ); on_error: if( *bitmap_values != NULL ) { memory_free( *bitmap_values ); *bitmap_values = NULL; } return( -1 ); } /* Frees bitmap values * Returns 1 if successful or -1 on error */ int libfsntfs_bitmap_values_free( libfsntfs_bitmap_values_t **bitmap_values, libcerror_error_t **error ) { static char *function = "libfsntfs_bitmap_values_free"; int result = 1; if( bitmap_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid bitmap values.", function ); return( -1 ); } if( *bitmap_values != NULL ) { if( libcdata_range_list_free( &( ( *bitmap_values )->allocated_block_list ), NULL, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free allocated data block list.", function ); result = -1; } memory_free( *bitmap_values ); *bitmap_values = NULL; } return( result ); } /* Reads the bitmap values * Returns 1 if successful or -1 on error */ int libfsntfs_bitmap_values_read_data( libfsntfs_bitmap_values_t *bitmap_values, const uint8_t *data, size_t data_size, size_t element_data_size, off64_t *base_offset, libcerror_error_t **error ) { static char *function = "libfsntfs_bitmap_values_read_data"; size64_t allocated_range_size = 0; size_t data_offset = 0; off64_t allocated_range_offset = 0; off64_t safe_base_offset = 0; uint8_t bit_index = 0; uint8_t byte_value = 0; uint8_t in_allocated_range = 0; int allocated_element_index = 0; int first_allocated_element_index = 0; int result = 0; if( bitmap_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid bitmap values.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } if( base_offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid base offset.", function ); return( -1 ); } safe_base_offset = *base_offset; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: bitmap data:\n", function ); libcnotify_print_data( data, data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif while( data_offset < data_size ) { byte_value = data[ data_offset ]; data_offset++; for( bit_index = 0; bit_index < 8; bit_index++ ) { if( in_allocated_range == 0 ) { if( ( byte_value & 0x01 ) != 0 ) { in_allocated_range = 1; first_allocated_element_index = allocated_element_index; } } else if( ( byte_value & 0x01 ) == 0 ) { allocated_range_offset = safe_base_offset + ( (off64_t) first_allocated_element_index * element_data_size ); allocated_range_size = ( (size64_t) allocated_element_index - first_allocated_element_index ) * element_data_size; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( first_allocated_element_index == ( allocated_element_index - 1 ) ) { libcnotify_printf( "%s: allocated element\t\t\t: %d\n", function, first_allocated_element_index ); } else { libcnotify_printf( "%s: allocated elements\t\t\t: %d - %d\n", function, first_allocated_element_index, allocated_element_index - 1 ); } libcnotify_printf( "%s: allocated block range\t\t: 0x%" PRIx64 " - 0x%" PRIx64 "\n", function, allocated_range_offset, allocated_range_offset + allocated_range_size ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ result = libcdata_range_list_insert_range( bitmap_values->allocated_block_list, allocated_range_offset, allocated_range_size, NULL, NULL, NULL, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append allocated block range to list.", function ); return( -1 ); } in_allocated_range = 0; } byte_value >>= 1; allocated_element_index++; } } if( in_allocated_range != 0 ) { allocated_range_offset = safe_base_offset + ( (off64_t) first_allocated_element_index * element_data_size ); allocated_range_size = ( (size64_t) allocated_element_index - first_allocated_element_index ) * element_data_size; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( first_allocated_element_index == ( allocated_element_index - 1 ) ) { libcnotify_printf( "%s: allocated element\t\t\t: %d\n", function, first_allocated_element_index ); } else { libcnotify_printf( "%s: allocated elements\t\t\t: %d - %d\n", function, first_allocated_element_index, allocated_element_index - 1 ); } libcnotify_printf( "%s: allocated block range\t\t: 0x%" PRIx64 " - 0x%" PRIx64 "\n", function, allocated_range_offset, allocated_range_offset + allocated_range_size ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ result = libcdata_range_list_insert_range( bitmap_values->allocated_block_list, allocated_range_offset, allocated_range_size, NULL, NULL, NULL, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append allocated block range to list.", function ); return( -1 ); } } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "\n" ); } #endif *base_offset = safe_base_offset + ( (off64_t) allocated_element_index * element_data_size ); return( 1 ); } /* Reads the bitmap values from an MFT attribute * Returns 1 if successful or -1 on error */ int libfsntfs_bitmap_values_read_from_mft_attribute( libfsntfs_bitmap_values_t *bitmap_values, libfsntfs_mft_attribute_t *mft_attribute, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, size_t element_data_size, uint8_t flags, libcerror_error_t **error ) { libfcache_cache_t *cluster_block_cache = NULL; libfdata_vector_t *cluster_block_vector = NULL; libfsntfs_cluster_block_t *cluster_block = NULL; uint8_t *data = NULL; static char *function = "libfsntfs_bitmap_values_read_from_mft_attribute"; size64_t segment_size = 0; size_t data_size = 0; off64_t base_offset = 0; off64_t segment_offset = 0; uint32_t attribute_type = 0; uint32_t segment_flags = 0; int cluster_block_index = 0; int number_of_cluster_blocks = 0; int number_of_segments = 0; int result = 0; int segment_file_index = 0; int segment_index = 0; if( bitmap_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid bitmap values.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( io_handle->cluster_block_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid IO handle - cluster block size value out of bounds.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_type( mft_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve type from attribute.", function ); goto on_error; } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_BITMAP ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); goto on_error; } result = libfsntfs_mft_attribute_data_is_resident( mft_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if attribute data is resident.", function ); goto on_error; } else if( result != 0 ) { if( libfsntfs_mft_attribute_get_resident_data( mft_attribute, &data, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve resident data from attribute.", function ); goto on_error; } if( libfsntfs_bitmap_values_read_data( bitmap_values, data, data_size, element_data_size, &base_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read bitmap values.", function ); goto on_error; } } else if( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) == 0 ) { if( libfsntfs_cluster_block_vector_initialize( &cluster_block_vector, io_handle, mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create cluster block vector.", function ); goto on_error; } if( libfcache_cache_initialize( &cluster_block_cache, 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create cluster block cache.", function ); goto on_error; } if( libfdata_vector_get_number_of_elements( cluster_block_vector, &number_of_cluster_blocks, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of cluster blocks.", function ); goto on_error; } if( libfdata_vector_get_number_of_segments( cluster_block_vector, &number_of_segments, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of cluster block vector segments.", function ); goto on_error; } for( segment_index = 0; segment_index < number_of_segments; segment_index++ ) { if( libfdata_vector_get_segment_by_index( cluster_block_vector, segment_index, &segment_file_index, &segment_offset, &segment_size, &segment_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve cluster block vector segment: %d.", function, segment_index ); goto on_error; } if( ( segment_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) != 0 ) { cluster_block_index += segment_size / io_handle->cluster_block_size; continue; } while( segment_size > 0 ) { if( cluster_block_index >= number_of_cluster_blocks ) { break; } if( libfdata_vector_get_element_value_by_index( cluster_block_vector, (intptr_t *) file_io_handle, (libfdata_cache_t *) cluster_block_cache, cluster_block_index, (intptr_t **) &cluster_block, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve cluster block: %d from vector.", function, cluster_block_index ); goto on_error; } if( cluster_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing cluster block: %d.", function, cluster_block_index ); goto on_error; } if( libfsntfs_bitmap_values_read_data( bitmap_values, cluster_block->data, cluster_block->data_size, element_data_size, &base_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read bitmap values.", function ); goto on_error; } segment_size -= io_handle->cluster_block_size; cluster_block_index++; } if( cluster_block_index >= number_of_cluster_blocks ) { break; } } if( libfdata_vector_free( &cluster_block_vector, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free cluster block vector.", function ); goto on_error; } if( libfcache_cache_free( &cluster_block_cache, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free cluster block cache.", function ); goto on_error; } } return( 1 ); on_error: if( cluster_block_cache != NULL ) { libfcache_cache_free( &cluster_block_cache, NULL ); } if( cluster_block_vector != NULL ) { libfdata_vector_free( &cluster_block_vector, NULL ); } return( -1 ); } ================================================ FILE: libfsntfs/libfsntfs_bitmap_values.h ================================================ /* * Bitmap attribute ($BITMAP) values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_BITMAP_VALUES_H ) #define _LIBFSNTFS_BITMAP_VALUES_H #include #include #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_mft_attribute.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_bitmap_values libfsntfs_bitmap_values_t; struct libfsntfs_bitmap_values { /* The allocated block (range) list */ libcdata_range_list_t *allocated_block_list; }; int libfsntfs_bitmap_values_initialize( libfsntfs_bitmap_values_t **bitmap_values, libcerror_error_t **error ); int libfsntfs_bitmap_values_free( libfsntfs_bitmap_values_t **bitmap_values, libcerror_error_t **error ); int libfsntfs_bitmap_values_read_data( libfsntfs_bitmap_values_t *bitmap_values, const uint8_t *data, size_t data_size, size_t element_data_size, off64_t *base_offset, libcerror_error_t **error ); int libfsntfs_bitmap_values_read_from_mft_attribute( libfsntfs_bitmap_values_t *bitmap_values, libfsntfs_mft_attribute_t *mft_attribute, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, size_t element_data_size, uint8_t flags, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_BITMAP_VALUES_H ) */ ================================================ FILE: libfsntfs/libfsntfs_buffer_data_handle.c ================================================ /* * The buffer data handle functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_buffer_data_handle.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_unused.h" /* Creates a buffer data handle * Make sure the value data_handle is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_buffer_data_handle_initialize( libfsntfs_buffer_data_handle_t **data_handle, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_buffer_data_handle_initialize"; if( data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data handle.", function ); return( -1 ); } if( *data_handle != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid data handle value already set.", function ); return( -1 ); } if( data_size > 0 ) { if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data.", function ); return( -1 ); } } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid data size value exceeds maximum.", function ); return( -1 ); } *data_handle = memory_allocate_structure( libfsntfs_buffer_data_handle_t ); if( *data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create data handle.", function ); goto on_error; } if( memory_set( *data_handle, 0, sizeof( libfsntfs_buffer_data_handle_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear data handle.", function ); goto on_error; } ( *data_handle )->data = data; ( *data_handle )->data_size = data_size; return( 1 ); on_error: if( *data_handle != NULL ) { memory_free( *data_handle ); *data_handle = NULL; } return( -1 ); } /* Frees a buffer data handle * Returns 1 if successful or -1 on error */ int libfsntfs_buffer_data_handle_free( libfsntfs_buffer_data_handle_t **data_handle, libcerror_error_t **error ) { static char *function = "libfsntfs_buffer_data_handle_free"; if( data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data handle.", function ); return( -1 ); } if( *data_handle != NULL ) { memory_free( *data_handle ); *data_handle = NULL; } return( 1 ); } /* Reads data from the current offset into a buffer * Callback for the data stream * Returns the number of bytes read or -1 on error */ ssize_t libfsntfs_buffer_data_handle_read_segment_data( libfsntfs_buffer_data_handle_t *data_handle, intptr_t *file_io_handle LIBFSNTFS_ATTRIBUTE_UNUSED, int segment_index, int segment_file_index LIBFSNTFS_ATTRIBUTE_UNUSED, uint8_t *segment_data, size_t segment_data_size, uint32_t segment_flags LIBFSNTFS_ATTRIBUTE_UNUSED, uint8_t read_flags LIBFSNTFS_ATTRIBUTE_UNUSED, libcerror_error_t **error ) { static char *function = "libfsntfs_buffer_data_handle_read_segment_data"; size_t read_size = 0; LIBFSNTFS_UNREFERENCED_PARAMETER( file_io_handle ) LIBFSNTFS_UNREFERENCED_PARAMETER( segment_file_index ) LIBFSNTFS_UNREFERENCED_PARAMETER( segment_flags ) LIBFSNTFS_UNREFERENCED_PARAMETER( read_flags ) if( data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data handle.", function ); return( -1 ); } if( data_handle->current_offset < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data handle - current offset value out of bounds.", function ); return( -1 ); } if( segment_index != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid segment index value out of bounds.", function ); return( -1 ); } if( segment_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid segment data.", function ); return( -1 ); } if( segment_data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid segment data size value exceeds maximum.", function ); return( -1 ); } if( data_handle->current_offset >= (off64_t) data_handle->data_size ) { return( 0 ); } read_size = data_handle->data_size - (size_t) data_handle->current_offset; if( read_size > segment_data_size ) { read_size = segment_data_size; } if( memory_copy( segment_data, &( data_handle->data[ data_handle->current_offset ] ), read_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy data.", function ); return( -1 ); } data_handle->current_offset += read_size; return( (ssize_t) read_size ); } /* Seeks a certain offset of the data * Callback for the data stream * Returns the offset if seek is successful or -1 on error */ off64_t libfsntfs_buffer_data_handle_seek_segment_offset( libfsntfs_buffer_data_handle_t *data_handle, intptr_t *file_io_handle LIBFSNTFS_ATTRIBUTE_UNUSED, int segment_index, int segment_file_index LIBFSNTFS_ATTRIBUTE_UNUSED, off64_t segment_offset, libcerror_error_t **error ) { static char *function = "libfsntfs_buffer_data_handle_seek_segment_offset"; LIBFSNTFS_UNREFERENCED_PARAMETER( file_io_handle ) LIBFSNTFS_UNREFERENCED_PARAMETER( segment_file_index ) if( data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data handle.", function ); return( -1 ); } if( segment_index != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid segment index value out of bounds.", function ); return( -1 ); } if( segment_offset < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid segment offset value out of bounds.", function ); return( -1 ); } data_handle->current_offset = segment_offset; return( segment_offset ); } ================================================ FILE: libfsntfs/libfsntfs_buffer_data_handle.h ================================================ /* * The buffer data handle functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_BUFFER_DATA_HANDLE_H ) #define _LIBFSNTFS_BUFFER_DATA_HANDLE_H #include #include #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_buffer_data_handle libfsntfs_buffer_data_handle_t; struct libfsntfs_buffer_data_handle { /* The current offset */ off64_t current_offset; /* The data */ const uint8_t *data; /* The data size */ size_t data_size; }; int libfsntfs_buffer_data_handle_initialize( libfsntfs_buffer_data_handle_t **data_handle, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_buffer_data_handle_free( libfsntfs_buffer_data_handle_t **data_handle, libcerror_error_t **error ); ssize_t libfsntfs_buffer_data_handle_read_segment_data( libfsntfs_buffer_data_handle_t *data_handle, intptr_t *file_io_handle, int segment_index, int segment_file_index, uint8_t *segment_data, size_t segment_data_size, uint32_t segment_flags, uint8_t read_flags, libcerror_error_t **error ); off64_t libfsntfs_buffer_data_handle_seek_segment_offset( libfsntfs_buffer_data_handle_t *data_handle, intptr_t *file_io_handle, int segment_index, int segment_file_index, off64_t segment_offset, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_BUFFER_DATA_HANDLE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_cluster_block.c ================================================ /* * Cluster block functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_cluster_block.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" /* Creates a cluster block * Make sure the value cluster_block is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_cluster_block_initialize( libfsntfs_cluster_block_t **cluster_block, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_cluster_block_initialize"; if( cluster_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid cluster block.", function ); return( -1 ); } if( *cluster_block != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid cluster block value already set.", function ); return( -1 ); } if( ( data_size == 0 ) || ( data_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } *cluster_block = memory_allocate_structure( libfsntfs_cluster_block_t ); if( *cluster_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create cluster block.", function ); goto on_error; } if( memory_set( *cluster_block, 0, sizeof( libfsntfs_cluster_block_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear cluster block.", function ); memory_free( *cluster_block ); *cluster_block = NULL; return( -1 ); } ( *cluster_block )->data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * data_size ); if( ( *cluster_block )->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create data.", function ); goto on_error; } ( *cluster_block )->data_size = data_size; return( 1 ); on_error: if( *cluster_block != NULL ) { memory_free( *cluster_block ); *cluster_block = NULL; } return( -1 ); } /* Frees a cluster block * Returns 1 if successful or -1 on error */ int libfsntfs_cluster_block_free( libfsntfs_cluster_block_t **cluster_block, libcerror_error_t **error ) { static char *function = "libfsntfs_cluster_block_free"; if( cluster_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid cluster block.", function ); return( -1 ); } if( *cluster_block != NULL ) { memory_free( ( *cluster_block )->data ); memory_free( *cluster_block ); *cluster_block = NULL; } return( 1 ); } /* Clears a cluster block * Returns 1 if successful or -1 on error */ int libfsntfs_cluster_block_clear( libfsntfs_cluster_block_t *cluster_block, libcerror_error_t **error ) { static char *function = "libfsntfs_cluster_block_clear"; if( cluster_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid cluster block.", function ); return( -1 ); } if( cluster_block->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid cluster block - missing data.", function ); return( -1 ); } if( memory_set( cluster_block->data, 0, cluster_block->data_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear cluster block data.", function ); return( -1 ); } return( 1 ); } /* Reads a cluster block * Returns 1 if successful or -1 on error */ int libfsntfs_cluster_block_read_file_io_handle( libfsntfs_cluster_block_t *cluster_block, libbfio_handle_t *file_io_handle, off64_t file_offset, libcerror_error_t **error ) { static char *function = "libfsntfs_cluster_block_read_file_io_handle"; ssize_t read_count = 0; if( cluster_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid cluster block.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading cluster block at offset: %" PRIi64 " (0x%08" PRIx64 ") with size: %" PRIu64 ".\n", function, file_offset, file_offset, cluster_block->data_size ); } #endif read_count = libbfio_handle_read_buffer_at_offset( file_io_handle, cluster_block->data, cluster_block->data_size, file_offset, error ); if( read_count != (ssize_t) cluster_block->data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read cluster block at offset: %" PRIi64 " (0x%08" PRIx64 ").", function, file_offset, file_offset ); return( -1 ); } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_cluster_block.h ================================================ /* * Cluster block functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_CLUSTER_BLOCK_H ) #define _LIBFSNTFS_CLUSTER_BLOCK_H #include #include #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_cluster_block libfsntfs_cluster_block_t; struct libfsntfs_cluster_block { /* The data */ uint8_t *data; /* The data size */ size_t data_size; }; int libfsntfs_cluster_block_initialize( libfsntfs_cluster_block_t **cluster_block, size_t data_size, libcerror_error_t **error ); int libfsntfs_cluster_block_free( libfsntfs_cluster_block_t **cluster_block, libcerror_error_t **error ); int libfsntfs_cluster_block_clear( libfsntfs_cluster_block_t *cluster_block, libcerror_error_t **error ); int libfsntfs_cluster_block_read_file_io_handle( libfsntfs_cluster_block_t *cluster_block, libbfio_handle_t *file_io_handle, off64_t file_offset, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_CLUSTER_BLOCK_H ) */ ================================================ FILE: libfsntfs/libfsntfs_cluster_block_data.c ================================================ /* * Cluster block data functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_cluster_block_data.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_unused.h" /* Reads data from the current offset into a buffer * Callback for the cluster block data stream * Returns the number of bytes read or -1 on error */ ssize_t libfsntfs_cluster_block_data_read_segment_data( intptr_t *data_handle LIBFSNTFS_ATTRIBUTE_UNUSED, libbfio_handle_t *file_io_handle, int segment_index LIBFSNTFS_ATTRIBUTE_UNUSED, int segment_file_index LIBFSNTFS_ATTRIBUTE_UNUSED, uint8_t *segment_data, size_t segment_data_size, uint32_t segment_flags, uint8_t read_flags LIBFSNTFS_ATTRIBUTE_UNUSED, libcerror_error_t **error ) { static char *function = "libfsntfs_cluster_block_data_read_segment_data"; ssize_t read_count = 0; LIBFSNTFS_UNREFERENCED_PARAMETER( data_handle ) LIBFSNTFS_UNREFERENCED_PARAMETER( segment_index ) LIBFSNTFS_UNREFERENCED_PARAMETER( segment_file_index ) LIBFSNTFS_UNREFERENCED_PARAMETER( read_flags ) if( segment_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid segment data.", function ); return( -1 ); } if( segment_data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid segment data size value exceeds maximum.", function ); return( -1 ); } if( ( segment_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) != 0 ) { if( memory_set( segment_data, 0, segment_data_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear segment data.", function ); return( -1 ); } read_count = (ssize_t) segment_data_size; } else { read_count = libbfio_handle_read_buffer( file_io_handle, segment_data, segment_data_size, error ); if( read_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read segment data.", function ); return( -1 ); } } return( read_count ); } /* Seeks a certain offset of the data * Callback for the cluster block data stream * Returns the offset if seek is successful or -1 on error */ off64_t libfsntfs_cluster_block_data_seek_segment_offset( intptr_t *data_handle LIBFSNTFS_ATTRIBUTE_UNUSED, libbfio_handle_t *file_io_handle, int segment_index LIBFSNTFS_ATTRIBUTE_UNUSED, int segment_file_index LIBFSNTFS_ATTRIBUTE_UNUSED, off64_t segment_offset, libcerror_error_t **error ) { static char *function = "libfsntfs_cluster_block_data_seek_segment_offset"; LIBFSNTFS_UNREFERENCED_PARAMETER( data_handle ) LIBFSNTFS_UNREFERENCED_PARAMETER( segment_index ) LIBFSNTFS_UNREFERENCED_PARAMETER( segment_file_index ) if( segment_offset < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid segment offset value out of bounds.", function ); return( -1 ); } if( libbfio_handle_seek_offset( file_io_handle, segment_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek segment offset: %" PRIi64 " (0x%08" PRIx64 ").", function, segment_offset, segment_offset ); return( -1 ); } return( segment_offset ); } ================================================ FILE: libfsntfs/libfsntfs_cluster_block_data.h ================================================ /* * Cluster block data functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_CLUSTER_BLOCK_DATA_H ) #define _LIBFSNTFS_CLUSTER_BLOCK_DATA_H #include #include #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfdata.h" #if defined( __cplusplus ) extern "C" { #endif ssize_t libfsntfs_cluster_block_data_read_segment_data( intptr_t *data_handle, libbfio_handle_t *file_io_handle, int segment_index, int segment_file_index, uint8_t *segment_data, size_t segment_data_size, uint32_t segment_flags, uint8_t read_flags, libcerror_error_t **error ); off64_t libfsntfs_cluster_block_data_seek_segment_offset( intptr_t *data_handle, libbfio_handle_t *file_io_handle, int segment_index, int segment_file_index, off64_t segment_offset, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_CLUSTER_BLOCK_DATA_H ) */ ================================================ FILE: libfsntfs/libfsntfs_cluster_block_stream.c ================================================ /* * Cluster block stream functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include "libfsntfs_buffer_data_handle.h" #include "libfsntfs_cluster_block_data.h" #include "libfsntfs_cluster_block_stream.h" #include "libfsntfs_compressed_block_data_handle.h" #include "libfsntfs_compressed_data_handle.h" #include "libfsntfs_definitions.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_attribute.h" /* Creates cluster block stream from a buffer of data * Make sure the value cluster_block_stream is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_cluster_block_stream_initialize_from_data( libfdata_stream_t **cluster_block_stream, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { libfdata_stream_t *safe_data_stream = NULL; libfsntfs_buffer_data_handle_t *data_handle = NULL; static char *function = "libfsntfs_cluster_block_stream_initialize_from_data"; int segment_index = 0; if( cluster_block_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid cluster block stream.", function ); return( -1 ); } if( libfsntfs_buffer_data_handle_initialize( &data_handle, data, data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create buffer data handle.", function ); goto on_error; } if( libfdata_stream_initialize( &safe_data_stream, (intptr_t *) data_handle, (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_buffer_data_handle_free, NULL, NULL, (ssize_t (*)(intptr_t *, intptr_t *, int, int, uint8_t *, size_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsntfs_buffer_data_handle_read_segment_data, NULL, (off64_t (*)(intptr_t *, intptr_t *, int, int, off64_t, libcerror_error_t **)) &libfsntfs_buffer_data_handle_seek_segment_offset, LIBFDATA_DATA_HANDLE_FLAG_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create data stream.", function ); goto on_error; } data_handle = NULL; if( libfdata_stream_append_segment( safe_data_stream, &segment_index, 0, 0, (size64_t) data_size, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append data stream segment.", function ); goto on_error; } *cluster_block_stream = safe_data_stream; return( 1 ); on_error: if( safe_data_stream != NULL ) { libfdata_stream_free( &safe_data_stream, NULL ); } if( data_handle != NULL ) { libfsntfs_buffer_data_handle_free( &data_handle, NULL ); } return( -1 ); } /* Creates cluster block stream from data runs * Make sure the value data_stream is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_cluster_block_stream_initialize_from_data_runs( libfdata_stream_t **cluster_block_stream, libfsntfs_io_handle_t *io_handle, libfsntfs_mft_attribute_t *data_attribute, size64_t data_size, libcerror_error_t **error ) { libfdata_stream_t *safe_data_stream = NULL; libfsntfs_data_run_t *data_run = NULL; static char *function = "libfsntfs_cluster_block_stream_initialize_from_data_runs"; size64_t attribute_data_vcn_size = 0; size64_t calculated_allocated_data_size = 0; size64_t data_segment_size = 0; size64_t stored_allocated_data_size = 0; size64_t valid_data_size = 0; off64_t attribute_data_vcn_offset = 0; off64_t calculated_attribute_data_vcn_offset = 0; off64_t data_segment_offset = 0; uint16_t attribute_data_flags = 0; int attribute_index = 0; int data_run_index = 0; int number_of_data_runs = 0; int segment_index = 0; if( cluster_block_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data stream.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( io_handle->cluster_block_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid IO handle - cluster block size value out of bounds.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_valid_data_size( data_attribute, &valid_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve valid data size.", function ); goto on_error; } if( libfsntfs_mft_attribute_get_data_flags( data_attribute, &attribute_data_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute data flags.", function ); goto on_error; } if( ( attribute_data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported compressed attribute data.", function ); goto on_error; } if( libfsntfs_mft_attribute_get_allocated_data_size( data_attribute, &stored_allocated_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute allocated data size.", function ); goto on_error; } if( libfdata_stream_initialize( &safe_data_stream, NULL, NULL, NULL, NULL, (ssize_t (*)(intptr_t *, intptr_t *, int, int, uint8_t *, size_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsntfs_cluster_block_data_read_segment_data, NULL, (off64_t (*)(intptr_t *, intptr_t *, int, int, off64_t, libcerror_error_t **)) &libfsntfs_cluster_block_data_seek_segment_offset, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create data stream.", function ); goto on_error; } while( data_attribute != NULL ) { if( libfsntfs_mft_attribute_get_data_vcn_range( data_attribute, (uint64_t *) &attribute_data_vcn_offset, (uint64_t *) &attribute_data_vcn_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute data VCN range.", function ); goto on_error; } if( attribute_data_vcn_size != 0xffffffffffffffffULL ) { if( (uint64_t) attribute_data_vcn_offset > (uint64_t) ( ( INT64_MAX / io_handle->cluster_block_size ) - 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data first VCN value out of bounds.", function ); goto on_error; } if( attribute_data_vcn_size > (size64_t) ( ( INT64_MAX / io_handle->cluster_block_size ) - 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data last VCN value out of bounds.", function ); goto on_error; } if( attribute_data_vcn_offset > (off64_t) attribute_data_vcn_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data first VCN value exceeds last VCN value.", function ); goto on_error; } attribute_data_vcn_size += 1; attribute_data_vcn_size -= attribute_data_vcn_offset; attribute_data_vcn_offset *= io_handle->cluster_block_size; attribute_data_vcn_size *= io_handle->cluster_block_size; if( ( calculated_attribute_data_vcn_offset != 0 ) && ( calculated_attribute_data_vcn_offset != attribute_data_vcn_offset ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data VCN offset value out of bounds.", function ); goto on_error; } calculated_attribute_data_vcn_offset = attribute_data_vcn_offset + (off64_t) attribute_data_vcn_size; } if( libfsntfs_mft_attribute_get_number_of_data_runs( data_attribute, &number_of_data_runs, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d number of data runs.", function, attribute_index ); goto on_error; } for( data_run_index = 0; data_run_index < number_of_data_runs; data_run_index++ ) { if( libfsntfs_mft_attribute_get_data_run_by_index( data_attribute, data_run_index, &data_run, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d data run: %d.", function, attribute_index, data_run_index ); goto on_error; } if( data_run == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing attribute: %d data run: %d.", function, attribute_index, data_run_index ); goto on_error; } if( data_run->size > ( valid_data_size - data_segment_offset ) ) { data_segment_size = valid_data_size - data_segment_offset; } else { data_segment_size = data_run->size; } if( (size64_t) data_segment_offset < valid_data_size ) { if( libfdata_stream_append_segment( safe_data_stream, &segment_index, 0, data_run->start_offset, data_segment_size, data_run->range_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append attribute: %d data run: %d data stream segment.", function, attribute_index, data_run_index ); goto on_error; } data_segment_offset += data_segment_size; } calculated_allocated_data_size += data_run->size; } attribute_index++; if( libfsntfs_mft_attribute_get_next_attribute( data_attribute, &data_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve next MFT attribute: %d.", function, attribute_index ); goto on_error; } } if( calculated_allocated_data_size != stored_allocated_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: size of data runs: %" PRIu64 " does not match allocated data size: %" PRIu64 ".", function, calculated_allocated_data_size, stored_allocated_data_size ); goto on_error; } if( (size64_t) data_segment_offset < data_size ) { if( libfdata_stream_append_segment( safe_data_stream, &segment_index, 0, 0, data_size - data_segment_offset, LIBFDATA_RANGE_FLAG_IS_SPARSE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append sparse data stream segment.", function ); goto on_error; } } *cluster_block_stream = safe_data_stream; return( 1 ); on_error: if( safe_data_stream != NULL ) { libfdata_stream_free( &safe_data_stream, NULL ); } return( -1 ); } /* Creates cluster block stream from compressed data runs * Make sure the value data_stream is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_cluster_block_stream_initialize_from_compressed_data_runs( libfdata_stream_t **cluster_block_stream, libfsntfs_io_handle_t *io_handle, libfsntfs_mft_attribute_t *data_attribute, size64_t data_size, libcerror_error_t **error ) { libfdata_stream_t *safe_data_stream = NULL; libfsntfs_compressed_block_data_handle_t *data_handle = NULL; static char *function = "libfsntfs_cluster_block_stream_initialize_from_compressed_data_runs"; size64_t valid_data_size = 0; int segment_index = 0; if( cluster_block_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data stream.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_valid_data_size( data_attribute, &valid_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve valid data size.", function ); goto on_error; } if( valid_data_size == 0 ) { valid_data_size = data_size; } if( libfsntfs_compressed_block_data_handle_initialize( &data_handle, io_handle, data_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create data handle.", function ); goto on_error; } if( libfdata_stream_initialize( &safe_data_stream, (intptr_t *) data_handle, (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_compressed_block_data_handle_free, NULL, NULL, (ssize_t (*)(intptr_t *, intptr_t *, int, int, uint8_t *, size_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsntfs_compressed_block_data_handle_read_segment_data, NULL, (off64_t (*)(intptr_t *, intptr_t *, int, int, off64_t, libcerror_error_t **)) &libfsntfs_compressed_block_data_handle_seek_segment_offset, LIBFDATA_DATA_HANDLE_FLAG_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create data stream.", function ); goto on_error; } data_handle = NULL; if( libfdata_stream_append_segment( safe_data_stream, &segment_index, 0, 0, valid_data_size, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append data stream segment.", function ); goto on_error; } if( valid_data_size < data_size ) { if( libfdata_stream_append_segment( safe_data_stream, &segment_index, 0, 0, data_size - valid_data_size, LIBFDATA_RANGE_FLAG_IS_SPARSE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append sparse data stream segment.", function ); goto on_error; } } *cluster_block_stream = safe_data_stream; return( 1 ); on_error: if( safe_data_stream != NULL ) { libfdata_stream_free( &safe_data_stream, NULL ); } if( data_handle != NULL ) { libfsntfs_compressed_block_data_handle_free( &data_handle, NULL ); } return( -1 ); } /* Creates cluster block stream from a compressed stream * Make sure the value data_stream is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_cluster_block_stream_initialize_from_compressed_stream( libfdata_stream_t **cluster_block_stream, libfdata_stream_t *compressed_data_stream, libfsntfs_mft_attribute_t *data_attribute, uint32_t compression_method, libcerror_error_t **error ) { libfdata_stream_t *safe_data_stream = NULL; libfsntfs_compressed_data_handle_t *data_handle = NULL; static char *function = "libfsntfs_cluster_block_stream_initialize_from_compressed_stream"; size64_t data_size = 0; size64_t valid_data_size = 0; int segment_index = 0; if( cluster_block_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data stream.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_data_size( data_attribute, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data size.", function ); goto on_error; } if( libfsntfs_mft_attribute_get_valid_data_size( data_attribute, &valid_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve valid data size.", function ); goto on_error; } if( valid_data_size == 0 ) { valid_data_size = data_size; } if( libfsntfs_compressed_data_handle_initialize( &data_handle, compressed_data_stream, compression_method, valid_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create data handle.", function ); goto on_error; } if( libfdata_stream_initialize( &safe_data_stream, (intptr_t *) data_handle, (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_compressed_data_handle_free, NULL, NULL, (ssize_t (*)(intptr_t *, intptr_t *, int, int, uint8_t *, size_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsntfs_compressed_data_handle_read_segment_data, NULL, (off64_t (*)(intptr_t *, intptr_t *, int, int, off64_t, libcerror_error_t **)) &libfsntfs_compressed_data_handle_seek_segment_offset, LIBFDATA_DATA_HANDLE_FLAG_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create data stream.", function ); goto on_error; } data_handle = NULL; if( libfdata_stream_append_segment( safe_data_stream, &segment_index, 0, 0, valid_data_size, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append data stream segment.", function ); goto on_error; } if( valid_data_size < data_size ) { if( libfdata_stream_append_segment( safe_data_stream, &segment_index, 0, 0, data_size - valid_data_size, LIBFDATA_RANGE_FLAG_IS_SPARSE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append sparse data stream segment.", function ); goto on_error; } } *cluster_block_stream = safe_data_stream; return( 1 ); on_error: if( safe_data_stream != NULL ) { libfdata_stream_free( &safe_data_stream, NULL ); } if( data_handle != NULL ) { libfsntfs_compressed_data_handle_free( &data_handle, NULL ); } return( -1 ); } /* Creates a cluster block stream * Make sure the value cluster_block_stream is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_cluster_block_stream_initialize( libfdata_stream_t **cluster_block_stream, libfsntfs_io_handle_t *io_handle, libfsntfs_mft_attribute_t *data_attribute, libfsntfs_mft_attribute_t *wof_compressed_data_attribute, uint32_t compression_method, libcerror_error_t **error ) { libfdata_stream_t *safe_cluster_block_stream = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; uint8_t *resident_data = NULL; static char *function = "libfsntfs_cluster_block_stream_initialize"; size64_t data_size = 0; size_t resident_data_size = 0; uint16_t data_flags = 0; int result = 0; if( cluster_block_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid cluster block stream.", function ); return( -1 ); } if( wof_compressed_data_attribute == NULL ) { mft_attribute = data_attribute; } else { mft_attribute = wof_compressed_data_attribute; } if( libfsntfs_mft_attribute_get_data_size( mft_attribute, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data size.", function ); goto on_error; } result = libfsntfs_mft_attribute_data_is_resident( mft_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if attribute data is resident.", function ); goto on_error; } else if( result != 0 ) { if( libfsntfs_mft_attribute_get_resident_data( mft_attribute, &resident_data, &resident_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve resident data from attribute.", function ); goto on_error; } } if( libfsntfs_mft_attribute_get_data_flags( mft_attribute, &data_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data flags from attribute.", function ); goto on_error; } if( ( resident_data != NULL ) || ( data_size == 0 ) ) { if( data_size != (size64_t) resident_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: unuspported data size value out of bounds.", function ); goto on_error; } result = libfsntfs_cluster_block_stream_initialize_from_data( &safe_cluster_block_stream, resident_data, resident_data_size, error ); } else if( ( data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) != 0 ) { result = libfsntfs_cluster_block_stream_initialize_from_compressed_data_runs( &safe_cluster_block_stream, io_handle, mft_attribute, data_size, error ); } else { result = libfsntfs_cluster_block_stream_initialize_from_data_runs( &safe_cluster_block_stream, io_handle, mft_attribute, data_size, error ); } if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create cluster block stream.", function ); goto on_error; } if( wof_compressed_data_attribute == NULL ) { *cluster_block_stream = safe_cluster_block_stream; } else { if( libfsntfs_cluster_block_stream_initialize_from_compressed_stream( cluster_block_stream, safe_cluster_block_stream, data_attribute, compression_method, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create cluster block stream.", function ); goto on_error; } } return( 1 ); on_error: if( safe_cluster_block_stream != NULL ) { libfdata_stream_free( &safe_cluster_block_stream, NULL ); } return( -1 ); } ================================================ FILE: libfsntfs/libfsntfs_cluster_block_stream.h ================================================ /* * Cluster block stream functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_CLUSTER_BLOCK_STREAM_H ) #define _LIBFSNTFS_CLUSTER_BLOCK_STREAM_H #include #include #include "libfsntfs_io_handle.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_attribute.h" #if defined( __cplusplus ) extern "C" { #endif int libfsntfs_cluster_block_stream_initialize_from_data( libfdata_stream_t **cluster_block_stream, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_cluster_block_stream_initialize_from_data_runs( libfdata_stream_t **cluster_block_stream, libfsntfs_io_handle_t *io_handle, libfsntfs_mft_attribute_t *data_attribute, size64_t data_size, libcerror_error_t **error ); int libfsntfs_cluster_block_stream_initialize_from_compressed_data_runs( libfdata_stream_t **cluster_block_stream, libfsntfs_io_handle_t *io_handle, libfsntfs_mft_attribute_t *data_attribute, size64_t data_size, libcerror_error_t **error ); int libfsntfs_cluster_block_stream_initialize_from_compressed_stream( libfdata_stream_t **cluster_block_stream, libfdata_stream_t *compressed_data_stream, libfsntfs_mft_attribute_t *data_attribute, uint32_t compression_method, libcerror_error_t **error ); int libfsntfs_cluster_block_stream_initialize( libfdata_stream_t **cluster_block_stream, libfsntfs_io_handle_t *io_handle, libfsntfs_mft_attribute_t *data_attribute, libfsntfs_mft_attribute_t *wof_compressed_data_attribute, uint32_t compression_method, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_CLUSTER_BLOCK_STREAM_H ) */ ================================================ FILE: libfsntfs/libfsntfs_cluster_block_vector.c ================================================ /* * Cluster block vector functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include "libfsntfs_cluster_block.h" #include "libfsntfs_cluster_block_vector.h" #include "libfsntfs_data_run.h" #include "libfsntfs_definitions.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_unused.h" /* Creates a cluster block vector * Make sure the value cluster_block_vector is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_cluster_block_vector_initialize( libfdata_vector_t **cluster_block_vector, libfsntfs_io_handle_t *io_handle, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ) { libfdata_vector_t *safe_cluster_block_vector = NULL; libfsntfs_data_run_t *data_run = NULL; static char *function = "libfsntfs_cluster_block_vector_initialize"; size64_t attribute_data_vcn_size = 0; size64_t calculated_allocated_data_size = 0; size64_t stored_allocated_data_size = 0; off64_t attribute_data_vcn_offset = 0; off64_t calculated_attribute_data_vcn_offset = 0; uint16_t attribute_data_flags = 0; int attribute_index = 0; int data_run_index = 0; int number_of_data_runs = 0; int segment_index = 0; if( cluster_block_vector == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid cluster block vector.", function ); return( -1 ); } if( *cluster_block_vector != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid cluster block vector value already set.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( io_handle->cluster_block_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid IO handle - cluster block size value out of bounds.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_data_flags( mft_attribute, &attribute_data_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute data flags.", function ); goto on_error; } if( ( attribute_data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported compressed attribute data.", function ); goto on_error; } if( libfsntfs_mft_attribute_get_allocated_data_size( mft_attribute, &stored_allocated_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute allocated data size.", function ); goto on_error; } if( libfdata_vector_initialize( &safe_cluster_block_vector, (size64_t) io_handle->cluster_block_size, (intptr_t *) io_handle, NULL, NULL, (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsntfs_cluster_block_vector_read_element_data, NULL, LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create cluster block vector.", function ); goto on_error; } while( mft_attribute != NULL ) { if( libfsntfs_mft_attribute_get_data_vcn_range( mft_attribute, (uint64_t *) &attribute_data_vcn_offset, (uint64_t *) &attribute_data_vcn_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute data VCN range.", function ); goto on_error; } if( attribute_data_vcn_size != 0xffffffffffffffffULL ) { if( (uint64_t) attribute_data_vcn_offset > (uint64_t) ( ( INT64_MAX / io_handle->cluster_block_size ) - 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data first VCN value out of bounds.", function ); goto on_error; } if( attribute_data_vcn_size > (size64_t) ( ( INT64_MAX / io_handle->cluster_block_size ) - 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data last VCN value out of bounds.", function ); goto on_error; } if( attribute_data_vcn_offset > (off64_t) attribute_data_vcn_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data first VCN value exceeds last VCN value.", function ); goto on_error; } attribute_data_vcn_size += 1; attribute_data_vcn_size -= attribute_data_vcn_offset; attribute_data_vcn_offset *= io_handle->cluster_block_size; attribute_data_vcn_size *= io_handle->cluster_block_size; if( ( calculated_attribute_data_vcn_offset != 0 ) && ( calculated_attribute_data_vcn_offset != attribute_data_vcn_offset ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data VCN offset value out of bounds.", function ); goto on_error; } calculated_attribute_data_vcn_offset = attribute_data_vcn_offset + (off64_t) attribute_data_vcn_size; } if( libfsntfs_mft_attribute_get_number_of_data_runs( mft_attribute, &number_of_data_runs, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d number of data runs.", function, attribute_index ); goto on_error; } for( data_run_index = 0; data_run_index < number_of_data_runs; data_run_index++ ) { if( libfsntfs_mft_attribute_get_data_run_by_index( mft_attribute, data_run_index, &data_run, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d data run: %d.", function, attribute_index, data_run_index ); goto on_error; } if( data_run == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing attribute: %d data run: %d.", function, attribute_index, data_run_index ); goto on_error; } if( libfdata_vector_append_segment( safe_cluster_block_vector, &segment_index, 0, data_run->start_offset, data_run->size, data_run->range_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append attribute: %d data run: %d vector segment.", function, attribute_index, data_run_index ); goto on_error; } calculated_allocated_data_size += data_run->size; } attribute_index++; if( libfsntfs_mft_attribute_get_next_attribute( mft_attribute, &mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve next MFT attribute: %d.", function, attribute_index ); goto on_error; } } if( calculated_allocated_data_size != stored_allocated_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: size of data runs: %" PRIu64 " does not match allocated data size: %" PRIu64 ".", function, calculated_allocated_data_size, stored_allocated_data_size ); goto on_error; } *cluster_block_vector = safe_cluster_block_vector; return( 1 ); on_error: if( safe_cluster_block_vector != NULL ) { libfdata_vector_free( &safe_cluster_block_vector, NULL ); } return( -1 ); } /* Reads a cluster block * Callback function for the cluster block vector * Returns 1 if successful or -1 on error */ int libfsntfs_cluster_block_vector_read_element_data( intptr_t *data_handle LIBFSNTFS_ATTRIBUTE_UNUSED, libbfio_handle_t *file_io_handle, libfdata_vector_t *vector, libfdata_cache_t *cache, int element_index LIBFSNTFS_ATTRIBUTE_UNUSED, int element_data_file_index LIBFSNTFS_ATTRIBUTE_UNUSED, off64_t cluster_block_offset, size64_t cluster_block_size, uint32_t range_flags, uint8_t read_flags LIBFSNTFS_ATTRIBUTE_UNUSED, libcerror_error_t **error ) { libfsntfs_cluster_block_t *cluster_block = NULL; static char *function = "libfsntfs_cluster_block_vector_read_element_data"; LIBFSNTFS_UNREFERENCED_PARAMETER( data_handle ) LIBFSNTFS_UNREFERENCED_PARAMETER( element_index ) LIBFSNTFS_UNREFERENCED_PARAMETER( element_data_file_index ) LIBFSNTFS_UNREFERENCED_PARAMETER( read_flags ) if( ( cluster_block_size == 0 ) || ( cluster_block_size > (size64_t) SSIZE_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid cluster block size value out of bounds.", function ); return( -1 ); } if( libfsntfs_cluster_block_initialize( &cluster_block, (size_t) cluster_block_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create cluster block.", function ); goto on_error; } if( ( range_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) != 0 ) { if( libfsntfs_cluster_block_clear( cluster_block, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to clear cluster block.", function ); goto on_error; } } else { if( libfsntfs_cluster_block_read_file_io_handle( cluster_block, file_io_handle, cluster_block_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read cluster block at offset: %" PRIi64 " (0x%08" PRIx64 ").", function, cluster_block_offset, cluster_block_offset ); goto on_error; } } if( libfdata_vector_set_element_value_by_index( vector, (intptr_t *) file_io_handle, cache, element_index, (intptr_t *) cluster_block, (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_cluster_block_free, LIBFDATA_VECTOR_ELEMENT_VALUE_FLAG_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set cluster block as element value.", function ); goto on_error; } return( 1 ); on_error: if( cluster_block != NULL ) { libfsntfs_cluster_block_free( &cluster_block, NULL ); } return( -1 ); } ================================================ FILE: libfsntfs/libfsntfs_cluster_block_vector.h ================================================ /* * Cluster block vector functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_CLUSTER_BLOCK_VECTOR_H ) #define _LIBFSNTFS_CLUSTER_BLOCK_VECTOR_H #include #include #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_attribute.h" #if defined( __cplusplus ) extern "C" { #endif int libfsntfs_cluster_block_vector_initialize( libfdata_vector_t **cluster_block_vector, libfsntfs_io_handle_t *io_handle, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ); int libfsntfs_cluster_block_vector_read_element_data( intptr_t *data_handle, libbfio_handle_t *file_io_handle, libfdata_vector_t *vector, libfdata_cache_t *cache, int element_index, int element_data_file_index, off64_t cluster_block_offset, size64_t cluster_block_size, uint32_t range_flags, uint8_t read_flags, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_CLUSTER_BLOCK_VECTOR_H ) */ ================================================ FILE: libfsntfs/libfsntfs_compressed_block.c ================================================ /* * Compressed block functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_compressed_block.h" #include "libfsntfs_libcerror.h" /* Creates a compressed block * Make sure the value compressed_block is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_compressed_block_initialize( libfsntfs_compressed_block_t **compressed_block, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_compressed_block_initialize"; if( compressed_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid compressed block.", function ); return( -1 ); } if( *compressed_block != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid compressed block value already set.", function ); return( -1 ); } if( ( data_size == 0 ) || ( data_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } *compressed_block = memory_allocate_structure( libfsntfs_compressed_block_t ); if( *compressed_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create compressed block.", function ); goto on_error; } if( memory_set( *compressed_block, 0, sizeof( libfsntfs_compressed_block_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear compressed block.", function ); memory_free( *compressed_block ); *compressed_block = NULL; return( -1 ); } ( *compressed_block )->data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * data_size ); if( ( *compressed_block )->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create data.", function ); goto on_error; } ( *compressed_block )->data_size = data_size; return( 1 ); on_error: if( *compressed_block != NULL ) { memory_free( *compressed_block ); *compressed_block = NULL; } return( -1 ); } /* Frees a compressed block * Returns 1 if successful or -1 on error */ int libfsntfs_compressed_block_free( libfsntfs_compressed_block_t **compressed_block, libcerror_error_t **error ) { static char *function = "libfsntfs_compressed_block_free"; if( compressed_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid compressed block.", function ); return( -1 ); } if( *compressed_block != NULL ) { if( ( *compressed_block )->data != NULL ) { memory_free( ( *compressed_block )->data ); } memory_free( *compressed_block ); *compressed_block = NULL; } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_compressed_block.h ================================================ /* * Compressed block functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_COMPRESSED_BLOCK_H ) #define _LIBFSNTFS_COMPRESSED_BLOCK_H #include #include #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_compressed_block libfsntfs_compressed_block_t; struct libfsntfs_compressed_block { /* The data */ uint8_t *data; /* The data size */ size_t data_size; }; int libfsntfs_compressed_block_initialize( libfsntfs_compressed_block_t **compressed_block, size_t data_size, libcerror_error_t **error ); int libfsntfs_compressed_block_free( libfsntfs_compressed_block_t **compressed_block, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_COMPRESSED_BLOCK_H ) */ ================================================ FILE: libfsntfs/libfsntfs_compressed_block_data_handle.c ================================================ /* * The compressed block data handle functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_compressed_block.h" #include "libfsntfs_compressed_block_data_handle.h" #include "libfsntfs_compressed_block_vector.h" #include "libfsntfs_compression.h" #include "libfsntfs_definitions.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_unused.h" /* Creates compressed block data handle * Make sure the value data_handle is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_compressed_block_data_handle_initialize( libfsntfs_compressed_block_data_handle_t **data_handle, libfsntfs_io_handle_t *io_handle, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_compressed_block_data_handle_initialize"; if( data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data handle.", function ); return( -1 ); } if( *data_handle != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid data handle value already set.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } *data_handle = memory_allocate_structure( libfsntfs_compressed_block_data_handle_t ); if( *data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create data handle.", function ); goto on_error; } if( memory_set( *data_handle, 0, sizeof( libfsntfs_compressed_block_data_handle_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear data handle.", function ); memory_free( *data_handle ); *data_handle = NULL; return( -1 ); } if( libfsntfs_compressed_block_vector_initialize( &( ( *data_handle )->compressed_block_vector ), io_handle, mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create compressed block vector.", function ); goto on_error; } if( libfdata_vector_get_size( ( *data_handle )->compressed_block_vector, &( ( *data_handle )->data_size ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of compressed block vector.", function ); goto on_error; } if( libfcache_cache_initialize( &( ( *data_handle )->compressed_block_cache ), LIBFSNTFS_MAXIMUM_CACHE_ENTRIES_COMPRESSED_BLOCKS, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create compressed block cache.", function ); goto on_error; } return( 1 ); on_error: if( *data_handle != NULL ) { if( ( *data_handle )->compressed_block_vector != NULL ) { libfdata_vector_free( &( ( *data_handle )->compressed_block_vector ), NULL ); } memory_free( *data_handle ); *data_handle = NULL; } return( -1 ); } /* Frees a data handle * Returns 1 if successful or -1 on error */ int libfsntfs_compressed_block_data_handle_free( libfsntfs_compressed_block_data_handle_t **data_handle, libcerror_error_t **error ) { static char *function = "libfsntfs_compressed_block_data_handle_free"; int result = 1; if( data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data handle.", function ); return( -1 ); } if( *data_handle != NULL ) { if( libfcache_cache_free( &( ( *data_handle )->compressed_block_cache ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free compressed_block cache.", function ); result = -1; } if( libfdata_vector_free( &( ( *data_handle )->compressed_block_vector ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free compressed block vector.", function ); result = -1; } memory_free( *data_handle ); *data_handle = NULL; } return( result ); } /* Reads data from the current offset into a compressed block * Callback for the data stream * Returns the number of bytes read or -1 on error */ ssize_t libfsntfs_compressed_block_data_handle_read_segment_data( libfsntfs_compressed_block_data_handle_t *data_handle, libbfio_handle_t *file_io_handle, int segment_index LIBFSNTFS_ATTRIBUTE_UNUSED, int segment_file_index LIBFSNTFS_ATTRIBUTE_UNUSED, uint8_t *segment_data, size_t segment_data_size, uint32_t segment_flags LIBFSNTFS_ATTRIBUTE_UNUSED, uint8_t read_flags LIBFSNTFS_ATTRIBUTE_UNUSED, libcerror_error_t **error ) { libfsntfs_compressed_block_t *compressed_block = NULL; static char *function = "libfsntfs_compressed_block_data_handle_read_segment_data"; size_t read_size = 0; size_t segment_data_offset = 0; ssize_t read_count = 0; off64_t compressed_block_offset = 0; LIBFSNTFS_UNREFERENCED_PARAMETER( segment_index ) LIBFSNTFS_UNREFERENCED_PARAMETER( segment_file_index ) LIBFSNTFS_UNREFERENCED_PARAMETER( segment_flags ) LIBFSNTFS_UNREFERENCED_PARAMETER( read_flags ) if( data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data handle.", function ); return( -1 ); } if( data_handle->current_offset < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data handle - current offset value out of bounds.", function ); return( -1 ); } if( segment_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid segment data.", function ); return( -1 ); } if( segment_data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid segment data size value exceeds maximum.", function ); return( -1 ); } if( ( segment_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) != 0 ) { if( memory_set( segment_data, 0, segment_data_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear segment data.", function ); return( -1 ); } read_count = (ssize_t) segment_data_size; } else { if( (size64_t) data_handle->current_offset >= data_handle->data_size ) { return( 0 ); } while( segment_data_size > 0 ) { if( libfdata_vector_get_element_value_at_offset( data_handle->compressed_block_vector, (intptr_t *) file_io_handle, (libfdata_cache_t *) data_handle->compressed_block_cache, data_handle->current_offset, &compressed_block_offset, (intptr_t **) &compressed_block, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve compressed block at offset: %" PRIi64 " (0x%08" PRIx64 ").", function, data_handle->current_offset, data_handle->current_offset ); return( -1 ); } if( compressed_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid compressed block.", function ); return( -1 ); } if( compressed_block->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid compressed block - missing data.", function ); return( -1 ); } if( ( compressed_block_offset < 0 ) || ( (size64_t) compressed_block_offset >= compressed_block->data_size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid compressed block offset value out of bounds.", function ); return( -1 ); } read_size = compressed_block->data_size - compressed_block_offset; if( read_size > segment_data_size ) { read_size = segment_data_size; } if( memory_copy( &( segment_data[ segment_data_offset ] ), &( ( compressed_block->data )[ compressed_block_offset ] ), read_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy compressed block data.", function ); return( -1 ); } segment_data_offset += read_size; segment_data_size -= read_size; data_handle->current_offset += read_size; if( (size64_t) data_handle->current_offset >= data_handle->data_size ) { break; } } read_count = (ssize_t) segment_data_offset; } return( read_count ); } /* Seeks a certain offset of the data * Callback for the data stream * Returns the offset if seek is successful or -1 on error */ off64_t libfsntfs_compressed_block_data_handle_seek_segment_offset( libfsntfs_compressed_block_data_handle_t *data_handle, intptr_t *file_io_handle LIBFSNTFS_ATTRIBUTE_UNUSED, int segment_index LIBFSNTFS_ATTRIBUTE_UNUSED, int segment_file_index LIBFSNTFS_ATTRIBUTE_UNUSED, off64_t segment_offset, libcerror_error_t **error ) { static char *function = "libfsntfs_compressed_block_data_handle_seek_segment_offset"; LIBFSNTFS_UNREFERENCED_PARAMETER( file_io_handle ) LIBFSNTFS_UNREFERENCED_PARAMETER( segment_index ) LIBFSNTFS_UNREFERENCED_PARAMETER( segment_file_index ) if( data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data handle.", function ); return( -1 ); } if( segment_offset < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid segment offset value out of bounds.", function ); return( -1 ); } data_handle->current_offset = segment_offset; return( segment_offset ); } ================================================ FILE: libfsntfs/libfsntfs_compressed_block_data_handle.h ================================================ /* * The compressed block data handle functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_COMPRESSED_BLOCK_DATA_HANDLE_H ) #define _LIBFSNTFS_COMPRESSED_BLOCK_DATA_HANDLE_H #include #include #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfcache.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_attribute.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_compressed_block_data_handle libfsntfs_compressed_block_data_handle_t; struct libfsntfs_compressed_block_data_handle { /* The current offset */ off64_t current_offset; /* The data size */ size64_t data_size; /* The compressed block vector */ libfdata_vector_t *compressed_block_vector; /* The compressed block cache */ libfcache_cache_t *compressed_block_cache; }; int libfsntfs_compressed_block_data_handle_initialize( libfsntfs_compressed_block_data_handle_t **data_handle, libfsntfs_io_handle_t *io_handle, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ); int libfsntfs_compressed_block_data_handle_free( libfsntfs_compressed_block_data_handle_t **data_handle, libcerror_error_t **error ); ssize_t libfsntfs_compressed_block_data_handle_read_segment_data( libfsntfs_compressed_block_data_handle_t *data_handle, libbfio_handle_t *file_io_handle, int segment_index, int segment_file_index, uint8_t *segment_data, size_t segment_data_size, uint32_t segment_flags, uint8_t read_flags, libcerror_error_t **error ); off64_t libfsntfs_compressed_block_data_handle_seek_segment_offset( libfsntfs_compressed_block_data_handle_t *data_handle, intptr_t *file_io_handle, int segment_index, int segment_file_index, off64_t segment_offset, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_COMPRESSED_BLOCK_DATA_HANDLE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_compressed_block_vector.c ================================================ /* * Compressed block vector functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_compressed_block.h" #include "libfsntfs_compressed_block_vector.h" #include "libfsntfs_compression_unit_data_handle.h" #include "libfsntfs_compression_unit_descriptor.h" #include "libfsntfs_compression.h" #include "libfsntfs_definitions.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_unused.h" /* Creates a compressed block vector * Make sure the value compressed_block_vector is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_compressed_block_vector_initialize( libfdata_vector_t **compressed_block_vector, libfsntfs_io_handle_t *io_handle, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ) { libfdata_vector_t *safe_compressed_block_vector = NULL; libfsntfs_compression_unit_data_handle_t *data_handle = NULL; libfsntfs_compression_unit_descriptor_t *descriptor = NULL; static char *function = "libfsntfs_compressed_block_vector_initialize"; int descriptor_index = 0; int number_of_descriptors = 0; int segment_index = 0; if( compressed_block_vector == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid compressed block vector.", function ); return( -1 ); } if( *compressed_block_vector != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid compressed block vector value already set.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( libfsntfs_compression_unit_data_handle_initialize( &data_handle, io_handle, mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create compression unit data handle.", function ); goto on_error; } if( libfdata_vector_initialize( &safe_compressed_block_vector, (size64_t) data_handle->compression_unit_size, (intptr_t *) data_handle, (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_compression_unit_data_handle_free, NULL, (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsntfs_compressed_block_vector_read_element_data, NULL, LIBFDATA_DATA_HANDLE_FLAG_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create compressed block vector.", function ); goto on_error; } if( libfsntfs_compression_unit_data_handle_get_number_of_descriptors( data_handle, &number_of_descriptors, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of descriptors.", function ); data_handle = NULL; goto on_error; } for( descriptor_index = 0; descriptor_index < number_of_descriptors; descriptor_index++ ) { if( libfsntfs_compression_unit_data_handle_get_descriptor_by_index( data_handle, descriptor_index, &descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve descriptor: %d.", function, descriptor_index ); data_handle = NULL; goto on_error; } if( descriptor == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing descriptor: %d.", function, descriptor_index ); data_handle = NULL; goto on_error; } if( libfdata_vector_append_segment( safe_compressed_block_vector, &segment_index, descriptor_index, descriptor->data_offset, descriptor->compression_unit_size, descriptor->data_range_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append compression unit: %d segment to compressed block vector.", function, descriptor_index ); data_handle = NULL; goto on_error; } } *compressed_block_vector = safe_compressed_block_vector; return( 1 ); on_error: if( safe_compressed_block_vector != NULL ) { libfdata_vector_free( &safe_compressed_block_vector, NULL ); } if( data_handle != NULL ) { libfsntfs_compression_unit_data_handle_free( &data_handle, NULL ); } return( -1 ); } /* Reads a compressed block * Callback function for the compressed block vector * Returns 1 if successful or -1 on error */ int libfsntfs_compressed_block_vector_read_element_data( libfsntfs_compression_unit_data_handle_t *data_handle, libbfio_handle_t *file_io_handle, libfdata_vector_t *vector, libfdata_cache_t *cache, int element_index, int element_data_file_index, off64_t element_data_offset, size64_t compressed_block_size, uint32_t range_flags, uint8_t read_flags LIBFSNTFS_ATTRIBUTE_UNUSED, libcerror_error_t **error ) { libfsntfs_compressed_block_t *compressed_block = NULL; libfsntfs_compression_unit_descriptor_t *compression_unit_descriptor = NULL; uint8_t *compressed_block_data = NULL; uint8_t *compressed_data = NULL; const char *block_type = NULL; static char *function = "libfsntfs_compressed_block_vector_read_element_data"; ssize_t read_count = 0; off64_t data_stream_offset = 0; int result = 0; LIBFSNTFS_UNREFERENCED_PARAMETER( read_flags ) if( ( compressed_block_size == 0 ) || ( compressed_block_size > (size64_t) SSIZE_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid compressed block size value out of bounds.", function ); return( -1 ); } if( libfsntfs_compression_unit_data_handle_get_descriptor_by_index( data_handle, element_data_file_index, &compression_unit_descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve compression unit descriptor: %d.", function, element_data_file_index ); goto on_error; } if( compression_unit_descriptor == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing compression unit descriptor: %d.", function, element_data_file_index ); goto on_error; } if( libfsntfs_compressed_block_initialize( &compressed_block, compressed_block_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create compressed block.", function ); goto on_error; } if( compressed_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing compressed block.", function ); goto on_error; } if( ( range_flags & LIBFDATA_RANGE_FLAG_IS_COMPRESSED ) != 0 ) { compressed_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * (size_t) compressed_block_size ); if( compressed_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create compressed data.", function ); goto on_error; } compressed_block_data = compressed_data; /* Make sure to read from the start of the data stream * otherwise successive reads will fail */ data_stream_offset = 0; block_type = "compressed"; } else { compressed_block_data = compressed_block->data; data_stream_offset = element_data_offset - compression_unit_descriptor->data_offset; block_type = "uncompressed"; } read_count = libfdata_stream_read_buffer_at_offset( compression_unit_descriptor->data_stream, (intptr_t *) file_io_handle, compressed_block_data, compressed_block_size, data_stream_offset, 0, error ); if( read_count != (ssize_t) compressed_block_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read %s block at offset: %" PRIi64 " (0x%08" PRIx64 ").", function, block_type, data_stream_offset, data_stream_offset ); goto on_error; } if( ( range_flags & LIBFDATA_RANGE_FLAG_IS_COMPRESSED ) != 0 ) { result = libfsntfs_decompress_data( compressed_data, (size_t) compressed_block_size, LIBFSNTFS_COMPRESSION_METHOD_LZNT1, compressed_block->data, &( compressed_block->data_size ), error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_COMPRESSION, LIBCERROR_COMPRESSION_ERROR_DECOMPRESS_FAILED, "%s: unable to decompress compressed data.", function ); goto on_error; } memory_free( compressed_data ); compressed_data = NULL; /* If the compressed block data size is 0 or the compressed block was truncated * fill the remainder of the compressed block with 0-byte values */ if( compressed_block->data_size < compressed_block_size ) { if( memory_set( &( compressed_block->data[ compressed_block->data_size ] ), 0, compressed_block_size - compressed_block->data_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear remainder of compressed block.", function ); goto on_error; } compressed_block->data_size = compressed_block_size; } } if( libfdata_vector_set_element_value_by_index( vector, (intptr_t *) file_io_handle, cache, element_index, (intptr_t *) compressed_block, (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_compressed_block_free, LIBFDATA_VECTOR_ELEMENT_VALUE_FLAG_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set cluster block as element value.", function ); goto on_error; } return( 1 ); on_error: if( compressed_data != NULL ) { memory_free( compressed_data ); } if( compressed_block != NULL ) { libfsntfs_compressed_block_free( &compressed_block, NULL ); } return( -1 ); } ================================================ FILE: libfsntfs/libfsntfs_compressed_block_vector.h ================================================ /* * Compressed block vector functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_COMPRESSED_BLOCK_VECTOR_H ) #define _LIBFSNTFS_COMPRESSED_BLOCK_VECTOR_H #include #include #include "libfsntfs_compression_unit_data_handle.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_attribute.h" #if defined( __cplusplus ) extern "C" { #endif int libfsntfs_compressed_block_vector_initialize( libfdata_vector_t **compressed_block_vector, libfsntfs_io_handle_t *io_handle, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ); int libfsntfs_compressed_block_vector_read_element_data( libfsntfs_compression_unit_data_handle_t *data_handle, libbfio_handle_t *file_io_handle, libfdata_vector_t *vector, libfdata_cache_t *cache, int element_index, int element_data_file_index, off64_t element_data_offset, size64_t compressed_block_size, uint32_t range_flags, uint8_t read_flags, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_COMPRESSED_BLOCK_VECTOR_H ) */ ================================================ FILE: libfsntfs/libfsntfs_compressed_data_handle.c ================================================ /* * The compressed data handle functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_compressed_data_handle.h" #include "libfsntfs_compression.h" #include "libfsntfs_definitions.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_unused.h" /* Creates compressed data handle * Make sure the value data_handle is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_compressed_data_handle_initialize( libfsntfs_compressed_data_handle_t **data_handle, libfdata_stream_t *compressed_data_stream, uint32_t compression_method, size64_t uncompressed_data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_compressed_data_handle_initialize"; size_t compression_unit_size = 0; if( data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data handle.", function ); return( -1 ); } if( *data_handle != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid data handle value already set.", function ); return( -1 ); } if( compressed_data_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid compressed data stream.", function ); return( -1 ); } switch( compression_method ) { case 0: compression_method = LIBFSNTFS_COMPRESSION_METHOD_LZXPRESS_HUFFMAN; compression_unit_size = 4096; break; case 1: compression_method = LIBFSNTFS_COMPRESSION_METHOD_LZX; compression_unit_size = 32768; break; case 2: compression_method = LIBFSNTFS_COMPRESSION_METHOD_LZXPRESS_HUFFMAN; compression_unit_size = 8192; break; case 3: compression_method = LIBFSNTFS_COMPRESSION_METHOD_LZXPRESS_HUFFMAN; compression_unit_size = 16384; break; default: libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported compression method: %" PRIu32 ".", function, compression_method ); return( -1 ); } *data_handle = memory_allocate_structure( libfsntfs_compressed_data_handle_t ); if( *data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create data handle.", function ); goto on_error; } if( memory_set( *data_handle, 0, sizeof( libfsntfs_compressed_data_handle_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear data handle.", function ); memory_free( *data_handle ); *data_handle = NULL; return( -1 ); } ( *data_handle )->compressed_segment_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * compression_unit_size ); if( ( *data_handle )->compressed_segment_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create compressed segment data.", function ); goto on_error; } ( *data_handle )->segment_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * compression_unit_size ); if( ( *data_handle )->segment_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create segment data.", function ); goto on_error; } ( *data_handle )->compressed_data_stream = compressed_data_stream; ( *data_handle )->current_compressed_block_index = (uint32_t) -1; ( *data_handle )->uncompressed_data_size = uncompressed_data_size; ( *data_handle )->compression_method = (int) compression_method; ( *data_handle )->compression_unit_size = compression_unit_size; return( 1 ); on_error: if( *data_handle != NULL ) { if( ( *data_handle )->segment_data != NULL ) { memory_free( ( *data_handle )->segment_data ); } if( ( *data_handle )->compressed_segment_data != NULL ) { memory_free( ( *data_handle )->compressed_segment_data ); } memory_free( *data_handle ); *data_handle = NULL; } return( -1 ); } /* Frees data handle * Returns 1 if successful or -1 on error */ int libfsntfs_compressed_data_handle_free( libfsntfs_compressed_data_handle_t **data_handle, libcerror_error_t **error ) { static char *function = "libfsntfs_compressed_data_handle_free"; if( data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data handle.", function ); return( -1 ); } if( *data_handle != NULL ) { if( ( *data_handle )->segment_data != NULL ) { memory_free( ( *data_handle )->segment_data ); } if( ( *data_handle )->compressed_segment_data != NULL ) { memory_free( ( *data_handle )->compressed_segment_data ); } if( ( *data_handle )->compressed_block_offsets != NULL ) { memory_free( ( *data_handle )->compressed_block_offsets ); } if( ( *data_handle )->compressed_data_stream != NULL ) { libfdata_stream_free( &( ( *data_handle )->compressed_data_stream ), NULL ); } memory_free( *data_handle ); *data_handle = NULL; } return( 1 ); } /* Determines the compressed block offsets * Returns 1 if successful or -1 on error */ int libfsntfs_compressed_data_handle_get_compressed_block_offsets( libfsntfs_compressed_data_handle_t *data_handle, libbfio_handle_t *file_io_handle, libcerror_error_t **error ) { uint8_t *chunk_offsets_data = NULL; static char *function = "libfsntfs_compressed_data_handle_get_compressed_block_offsets"; size64_t compressed_data_size = 0; size_t chunk_offset_data_size = 0; size_t chunk_offsets_data_size = 0; size_t data_offset = 0; ssize_t read_count = 0; uint64_t compressed_block_index = 0; uint64_t compressed_block_offset = 0; uint64_t previous_compressed_block_offset = 0; if( data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data handle.", function ); return( -1 ); } if( data_handle->compressed_block_offsets != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid data handle - compressed block offsets value already set.", function ); return( -1 ); } if( libfdata_stream_get_size( data_handle->compressed_data_stream, &compressed_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve compressed data size.", function ); goto on_error; } if( compressed_data_size > (size64_t) UINT32_MAX ) { chunk_offset_data_size = 8; } else { chunk_offset_data_size = 4; } chunk_offsets_data_size = data_handle->uncompressed_data_size / data_handle->compression_unit_size; if( ( data_handle->uncompressed_data_size % data_handle->compression_unit_size ) != 0 ) { chunk_offsets_data_size++; } if( chunk_offsets_data_size > ( (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE / chunk_offset_data_size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid number of chunk offsets data size value exceeds maximum allocation size.", function ); goto on_error; } chunk_offsets_data_size *= chunk_offset_data_size; chunk_offsets_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * chunk_offsets_data_size ); if( chunk_offsets_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create chunk offsets data.", function ); goto on_error; } read_count = libfdata_stream_read_buffer_at_offset( data_handle->compressed_data_stream, (intptr_t *) file_io_handle, chunk_offsets_data, chunk_offsets_data_size, 0, 0, error ); if( read_count != (ssize_t) chunk_offsets_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read chunk offsets data from compressed data stream.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: chunk offsets data:\n", function ); libcnotify_print_data( chunk_offsets_data, chunk_offsets_data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif previous_compressed_block_offset = chunk_offset_data_size; compressed_block_index++; for( data_offset = 0; data_offset < chunk_offsets_data_size; data_offset += chunk_offset_data_size ) { if( chunk_offset_data_size == 8 ) { byte_stream_copy_to_uint64_little_endian( &( chunk_offsets_data[ data_offset ] ), compressed_block_offset ); } else { byte_stream_copy_to_uint32_little_endian( &( chunk_offsets_data[ data_offset ] ), compressed_block_offset ); } if( ( compressed_block_offset <= previous_compressed_block_offset ) || ( compressed_block_offset >= compressed_data_size ) ) { break; } previous_compressed_block_offset = compressed_block_offset; compressed_block_index++; } data_handle->number_of_compressed_blocks = compressed_block_index; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: number of compressed blocks\t: %" PRIu64 "\n", function, data_handle->number_of_compressed_blocks ); } #endif if( (size_t) data_handle->number_of_compressed_blocks > ( (size_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE / sizeof( uint64_t ) ) - 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid number of compressed blocks value exceeds maximum allocation size.", function ); goto on_error; } data_handle->compressed_block_offsets = (uint64_t *) memory_allocate( sizeof( uint64_t ) * ( data_handle->number_of_compressed_blocks + 1 ) ); if( data_handle->compressed_block_offsets == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create compressed block offsets.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: compressed block: % 2d offset\t: %" PRIzd " (0x%08" PRIzx ")\n", function, 0, data_offset, data_offset ); } #endif data_handle->compressed_block_offsets[ 0 ] = data_offset; data_offset = 0; for( compressed_block_index = 1; compressed_block_index < data_handle->number_of_compressed_blocks; compressed_block_index++ ) { if( chunk_offset_data_size == 8 ) { byte_stream_copy_to_uint64_little_endian( &( chunk_offsets_data[ data_offset ] ), compressed_block_offset ); } else { byte_stream_copy_to_uint32_little_endian( &( chunk_offsets_data[ data_offset ] ), compressed_block_offset ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: compressed block: % 2" PRIu64 " offset\t: %" PRIu64 " (0x%08" PRIx64 ")\n", function, compressed_block_index, compressed_block_offset, compressed_block_offset ); } #endif if( ( compressed_block_offset == 0 ) || ( compressed_block_offset >= ( (uint64_t) INT64_MAX - data_handle->compressed_block_offsets[ 0 ] ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid compressed block offset: %d value out of bounds.", function, compressed_block_index ); goto on_error; } data_offset += chunk_offset_data_size; data_handle->compressed_block_offsets[ compressed_block_index ] = data_handle->compressed_block_offsets[ 0 ] + compressed_block_offset; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: compressed block: % 2" PRIu64 " offset\t: %" PRIu64 " (0x%08" PRIx64 ")\n", function, compressed_block_index, compressed_data_size, compressed_data_size ); } #endif data_handle->compressed_block_offsets[ compressed_block_index ] = (uint64_t) compressed_data_size; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "\n" ); } #endif memory_free( chunk_offsets_data ); return( 1 ); on_error: if( data_handle->compressed_block_offsets != NULL ) { memory_free( data_handle->compressed_block_offsets ); data_handle->compressed_block_offsets = NULL; } if( chunk_offsets_data != NULL ) { memory_free( chunk_offsets_data ); } return( -1 ); } /* Reads data from the current offset into a compressed * Callback for the data stream * Returns the number of bytes read or -1 on error */ ssize_t libfsntfs_compressed_data_handle_read_segment_data( libfsntfs_compressed_data_handle_t *data_handle, intptr_t *file_io_handle, int segment_index, int segment_file_index LIBFSNTFS_ATTRIBUTE_UNUSED, uint8_t *segment_data, size_t segment_data_size, uint32_t segment_flags LIBFSNTFS_ATTRIBUTE_UNUSED, uint8_t read_flags LIBFSNTFS_ATTRIBUTE_UNUSED, libcerror_error_t **error ) { uint8_t *read_buffer = NULL; static char *function = "libfsntfs_compressed_data_handle_read_segment_data"; size_t data_offset = 0; size_t read_size = 0; size_t segment_data_offset = 0; ssize_t read_count = 0; off64_t data_stream_offset = 0; off64_t uncompressed_block_offset = 0; uint64_t compressed_block_index = 0; LIBFSNTFS_UNREFERENCED_PARAMETER( file_io_handle ) LIBFSNTFS_UNREFERENCED_PARAMETER( segment_file_index ) LIBFSNTFS_UNREFERENCED_PARAMETER( segment_flags ) LIBFSNTFS_UNREFERENCED_PARAMETER( read_flags ) if( data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data handle.", function ); return( -1 ); } if( segment_index != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid segment index value out of bounds.", function ); return( -1 ); } if( segment_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid segment data.", function ); return( -1 ); } if( segment_data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid segment data size value exceeds maximum.", function ); return( -1 ); } if( data_handle->compressed_block_offsets == NULL ) { if( libfsntfs_compressed_data_handle_get_compressed_block_offsets( data_handle, (libbfio_handle_t *) file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine compressed block offsets.", function ); return( -1 ); } } if( (size64_t) data_handle->current_offset >= data_handle->uncompressed_data_size ) { return( 0 ); } compressed_block_index = (uint64_t) ( data_handle->current_offset / data_handle->compression_unit_size ); data_offset = (size_t) ( data_handle->current_offset % data_handle->compression_unit_size ); while( segment_data_size > 0 ) { if( compressed_block_index >= data_handle->number_of_compressed_blocks ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid compressed block index value out of bounds.", function ); return( -1 ); } if( data_handle->current_compressed_block_index != compressed_block_index ) { data_stream_offset = data_handle->compressed_block_offsets[ compressed_block_index ]; read_size = (size_t) ( data_handle->compressed_block_offsets[ compressed_block_index + 1 ] - data_stream_offset ); data_handle->segment_data_size = data_handle->compression_unit_size; if( data_handle->segment_data_size > ( data_handle->uncompressed_data_size - data_handle->current_offset ) ) { data_handle->segment_data_size = data_handle->uncompressed_data_size - data_handle->current_offset; } if( read_size > data_handle->segment_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid segment data size value out of bounds.", function ); return( -1 ); } if( read_size < data_handle->segment_data_size ) { read_buffer = data_handle->compressed_segment_data; } else { read_buffer = data_handle->segment_data; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: compressed block: % 2" PRIu64 " offset\t: %" PRIu64 " (0x%08" PRIx64 ")\n", function, compressed_block_index, data_stream_offset, data_stream_offset ); libcnotify_printf( "\n" ); } #endif read_count = libfdata_stream_read_buffer_at_offset( data_handle->compressed_data_stream, (intptr_t *) file_io_handle, read_buffer, read_size, data_stream_offset, 0, error ); if( read_count != (ssize_t) read_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read buffer at offset: %" PRIi64 " (0x%08" PRIx64 ") from data stream.", function, data_stream_offset, data_stream_offset ); return( -1 ); } if( read_buffer == data_handle->compressed_segment_data ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: compressed block data:\n", function ); libcnotify_print_data( data_handle->compressed_segment_data, read_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif if( libfsntfs_decompress_data( data_handle->compressed_segment_data, (size_t) read_count, data_handle->compression_method, data_handle->segment_data, &( data_handle->segment_data_size ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ENCRYPTION, LIBCERROR_ENCRYPTION_ERROR_GENERIC, "%s: unable to decompress data.", function ); return( -1 ); } uncompressed_block_offset = ( compressed_block_index + 1 ) * data_handle->compression_unit_size; if( ( (size64_t) uncompressed_block_offset < data_handle->uncompressed_data_size ) && ( data_handle->segment_data_size != data_handle->compression_unit_size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid uncompressed segment data size value out of bounds.", function ); return( -1 ); } } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: uncompressed block data:\n", function ); libcnotify_print_data( data_handle->segment_data, data_handle->segment_data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif data_handle->current_compressed_block_index = compressed_block_index; } if( data_offset >= data_handle->segment_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data offset value out of bounds.", function ); return( -1 ); } read_size = data_handle->segment_data_size - data_offset; if( read_size > segment_data_size ) { read_size = segment_data_size; } if( memory_copy( &( segment_data[ segment_data_offset ] ), &( data_handle->segment_data[ data_offset ] ), read_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy data.", function ); return( -1 ); } data_offset = 0; segment_data_size -= read_size; segment_data_offset += read_size; compressed_block_index++; data_handle->current_offset += read_size; if( (size64_t) data_handle->current_offset >= data_handle->uncompressed_data_size ) { break; } } return( (ssize_t) segment_data_offset ); } /* Seeks a certain offset of the data * Callback for the data stream * Returns the offset if seek is successful or -1 on error */ off64_t libfsntfs_compressed_data_handle_seek_segment_offset( libfsntfs_compressed_data_handle_t *data_handle, intptr_t *file_io_handle LIBFSNTFS_ATTRIBUTE_UNUSED, int segment_index, int segment_file_index LIBFSNTFS_ATTRIBUTE_UNUSED, off64_t segment_offset, libcerror_error_t **error ) { static char *function = "libfsntfs_compressed_data_handle_seek_segment_offset"; LIBFSNTFS_UNREFERENCED_PARAMETER( file_io_handle ) LIBFSNTFS_UNREFERENCED_PARAMETER( segment_file_index ) if( data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data handle.", function ); return( -1 ); } if( segment_index != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid segment index value out of bounds.", function ); return( -1 ); } if( segment_offset < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid segment offset value out of bounds.", function ); return( -1 ); } data_handle->current_offset = segment_offset; return( segment_offset ); } ================================================ FILE: libfsntfs/libfsntfs_compressed_data_handle.h ================================================ /* * The compressed data handle functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_COMPRESSED_DATA_HANDLE_H ) #define _LIBFSNTFS_COMPRESSED_DATA_HANDLE_H #include #include #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfdata.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_compressed_data_handle libfsntfs_compressed_data_handle_t; struct libfsntfs_compressed_data_handle { /* The current offset */ off64_t current_offset; /* The compressed data steam */ libfdata_stream_t *compressed_data_stream; /* The uncompressed data size */ size64_t uncompressed_data_size; /* The compression method */ int compression_method; /* The current compressed block index */ uint32_t current_compressed_block_index; /* The compressed segment data */ uint8_t *compressed_segment_data; /* The (uncompressed) segment data */ uint8_t *segment_data; /* The (uncompressed) segment data size */ size_t segment_data_size; /* The number of compressed blocks */ uint64_t number_of_compressed_blocks; /* The compressed block offsets */ uint64_t *compressed_block_offsets; /* The compression unit size */ size_t compression_unit_size; }; int libfsntfs_compressed_data_handle_initialize( libfsntfs_compressed_data_handle_t **data_handle, libfdata_stream_t *compressed_data_stream, uint32_t compression_method, size64_t uncompressed_data_size, libcerror_error_t **error ); int libfsntfs_compressed_data_handle_free( libfsntfs_compressed_data_handle_t **data_handle, libcerror_error_t **error ); int libfsntfs_compressed_data_handle_get_compressed_block_offsets( libfsntfs_compressed_data_handle_t *data_handle, libbfio_handle_t *file_io_handle, libcerror_error_t **error ); ssize_t libfsntfs_compressed_data_handle_read_segment_data( libfsntfs_compressed_data_handle_t *data_handle, intptr_t *file_io_handle, int segment_index, int segment_file_index, uint8_t *segment_data, size_t segment_data_size, uint32_t segment_flags, uint8_t read_flags, libcerror_error_t **error ); off64_t libfsntfs_compressed_data_handle_seek_segment_offset( libfsntfs_compressed_data_handle_t *data_handle, intptr_t *file_io_handle, int segment_index, int segment_file_index, off64_t segment_offset, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_COMPRESSED_DATA_HANDLE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_compression.c ================================================ /* * Compression functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "libfsntfs_compression.h" #include "libfsntfs_definitions.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfwnt.h" /* Decompresses data using the compression method * Returns 1 on success, 0 on failure or -1 on error */ int libfsntfs_decompress_data( const uint8_t *compressed_data, size_t compressed_data_size, int compression_method, uint8_t *uncompressed_data, size_t *uncompressed_data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_decompress_data"; if( compressed_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid compressed data buffer.", function ); return( -1 ); } if( uncompressed_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid uncompressed data buffer.", function ); return( -1 ); } if( uncompressed_data == compressed_data ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid compressed data buffer equals uncompressed data buffer.", function ); return( -1 ); } if( uncompressed_data_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid uncompressed data size.", function ); return( -1 ); } switch( compression_method ) { case LIBFSNTFS_COMPRESSION_METHOD_LZNT1: if( libfwnt_lznt1_decompress( compressed_data, compressed_data_size, uncompressed_data, uncompressed_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_COMPRESSION, LIBCERROR_COMPRESSION_ERROR_DECOMPRESS_FAILED, "%s: unable to decompress LZNT1 compressed data.", function ); return( -1 ); } break; case LIBFSNTFS_COMPRESSION_METHOD_LZX: if( libfwnt_lzx_decompress( compressed_data, compressed_data_size, uncompressed_data, uncompressed_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_COMPRESSION, LIBCERROR_COMPRESSION_ERROR_DECOMPRESS_FAILED, "%s: unable to decompress LZX compressed data.", function ); return( -1 ); } break; case LIBFSNTFS_COMPRESSION_METHOD_LZXPRESS_HUFFMAN: if( libfwnt_lzxpress_huffman_decompress( compressed_data, compressed_data_size, uncompressed_data, uncompressed_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_COMPRESSION, LIBCERROR_COMPRESSION_ERROR_DECOMPRESS_FAILED, "%s: unable to decompress LZXPRESS Huffman compressed data.", function ); return( -1 ); } break; default: libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported compression method.", function ); return( -1 ); } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_compression.h ================================================ /* * Compression functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_COMPRESSION_H ) #define _LIBFSNTFS_COMPRESSION_H #include #include #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif int libfsntfs_decompress_data( const uint8_t *compressed_data, size_t compressed_data_size, int compression_method, uint8_t *uncompressed_data, size_t *uncompressed_data_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_COMPRESSION_H ) */ ================================================ FILE: libfsntfs/libfsntfs_compression_unit_data_handle.c ================================================ /* * The compression unit data handle functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_compression_unit_data_handle.h" #include "libfsntfs_compression_unit_descriptor.h" #include "libfsntfs_data_run.h" #include "libfsntfs_definitions.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_mft_attribute.h" /* Creates compression unit data handle * Make sure the value data_handle is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_compression_unit_data_handle_initialize( libfsntfs_compression_unit_data_handle_t **data_handle, libfsntfs_io_handle_t *io_handle, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ) { libfsntfs_compression_unit_descriptor_t *descriptor = NULL; libfsntfs_data_run_t *data_run = NULL; libfsntfs_mft_attribute_t *safe_mft_attribute = NULL; static char *function = "libfsntfs_compression_unit_data_handle_initialize"; size64_t attribute_data_vcn_size = 0; size64_t calculated_allocated_data_size = 0; size64_t data_run_size = 0; size64_t data_segment_size = 0; size64_t remaining_compression_unit_size = 0; size64_t stored_allocated_data_size = 0; size_t compression_unit_size = 0; off64_t attribute_data_vcn_offset = 0; off64_t calculated_attribute_data_vcn_offset = 0; off64_t data_offset = 0; off64_t data_run_offset = 0; off64_t data_segment_offset = 0; uint16_t data_flags = 0; int attribute_index = 0; int data_run_index = 0; int descriptor_index = 0; int entry_index = 0; int number_of_data_runs = 0; int total_data_run_index = 0; int total_number_of_data_runs = 0; #if defined( HAVE_DEBUG_OUTPUT ) char *data_segment_type = NULL; #endif if( data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data handle.", function ); return( -1 ); } if( *data_handle != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid data handle value already set.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( io_handle->cluster_block_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid IO handle - cluster block size value out of bounds.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_data_flags( mft_attribute, &data_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute data flags.", function ); goto on_error; } if( ( data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported uncompressed attribute data.", function ); goto on_error; } if( libfsntfs_mft_attribute_get_allocated_data_size( mft_attribute, &stored_allocated_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute allocated data size.", function ); goto on_error; } if( libfsntfs_mft_attribute_get_compression_unit_size( mft_attribute, &compression_unit_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve compression unit size.", function ); goto on_error; } if( ( compression_unit_size == 0 ) || ( compression_unit_size > (size_t) SSIZE_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid compression unit size value out of bounds.", function ); goto on_error; } *data_handle = memory_allocate_structure( libfsntfs_compression_unit_data_handle_t ); if( *data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create data handle.", function ); goto on_error; } if( memory_set( *data_handle, 0, sizeof( libfsntfs_compression_unit_data_handle_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear data handle.", function ); memory_free( *data_handle ); *data_handle = NULL; return( -1 ); } if( libcdata_array_initialize( &( ( *data_handle )->descriptors_array ), 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create descriptors array.", function ); goto on_error; } safe_mft_attribute = mft_attribute; attribute_index = 0; while( safe_mft_attribute != NULL ) { if( libfsntfs_mft_attribute_get_data_vcn_range( safe_mft_attribute, (uint64_t *) &attribute_data_vcn_offset, (uint64_t *) &attribute_data_vcn_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute data VCN range.", function ); goto on_error; } if( attribute_data_vcn_size != 0xffffffffffffffffULL ) { if( (uint64_t) attribute_data_vcn_offset > (uint64_t) ( ( INT64_MAX / io_handle->cluster_block_size ) - 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data first VCN value out of bounds.", function ); goto on_error; } if( attribute_data_vcn_size > (size64_t) ( ( INT64_MAX / io_handle->cluster_block_size ) - 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data last VCN value out of bounds.", function ); goto on_error; } if( attribute_data_vcn_offset > (off64_t) attribute_data_vcn_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data first VCN value out of bounds.", function ); goto on_error; } attribute_data_vcn_size += 1; attribute_data_vcn_size -= attribute_data_vcn_offset; attribute_data_vcn_offset *= io_handle->cluster_block_size; attribute_data_vcn_size *= io_handle->cluster_block_size; if( ( calculated_attribute_data_vcn_offset != 0 ) && ( calculated_attribute_data_vcn_offset != attribute_data_vcn_offset ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data VCN offset value out of bounds.", function ); goto on_error; } calculated_attribute_data_vcn_offset = attribute_data_vcn_offset + (off64_t) attribute_data_vcn_size; } if( libfsntfs_mft_attribute_get_number_of_data_runs( safe_mft_attribute, &number_of_data_runs, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of data runs.", function ); goto on_error; } total_number_of_data_runs += number_of_data_runs; if( libfsntfs_mft_attribute_get_next_attribute( safe_mft_attribute, &safe_mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve next MFT attribute: %d.", function, attribute_index ); goto on_error; } attribute_index++; } safe_mft_attribute = mft_attribute; attribute_index = 0; while( safe_mft_attribute != NULL ) { if( libfsntfs_mft_attribute_get_number_of_data_runs( safe_mft_attribute, &number_of_data_runs, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of data runs.", function ); goto on_error; } for( data_run_index = 0; data_run_index < number_of_data_runs; data_run_index++ ) { if( libfsntfs_mft_attribute_get_data_run_by_index( safe_mft_attribute, data_run_index, &data_run, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data run: %d.", function, data_run_index ); goto on_error; } if( data_run == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing data run: %d.", function, data_run_index ); goto on_error; } data_run_offset = data_run->start_offset; data_run_size = data_run->size; calculated_allocated_data_size += data_run->size; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( ( data_run->range_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) != 0 ) { data_segment_type = "sparse "; } else { data_segment_type = ""; } libcnotify_printf( "%s: %sdata run: %d offset: 0x%08" PRIx64 ", size: %" PRIu64 ".\n", function, data_segment_type, data_run_index, data_run_offset, data_run_size ); libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ while( data_run_size > 0 ) { if( descriptor == NULL ) { if( libfsntfs_compression_unit_descriptor_initialize( &descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create compression unit descriptor.", function ); goto on_error; } descriptor->data_run_offset = data_run_offset; descriptor->data_offset = data_offset; data_segment_offset = 0; if( data_run_size <= compression_unit_size ) { descriptor->compression_unit_size = compression_unit_size; } else { descriptor->compression_unit_size = ( data_run_size / compression_unit_size ) * compression_unit_size; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: uncompressed data run size: %" PRIu64 "\n", function, descriptor->compression_unit_size ); } #endif } remaining_compression_unit_size = descriptor->compression_unit_size; } if( ( data_run->range_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) == 0 ) { descriptor->data_range_flags = data_run->range_flags; } /* Sparse data runs mark the end of a compression unit and they * should be at minimum the size of the remaining data in the compression unit */ else if( remaining_compression_unit_size < compression_unit_size ) { if( ( total_data_run_index == ( total_number_of_data_runs - 1 ) ) && ( data_run_size < (size64_t) remaining_compression_unit_size ) ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: last sparse data run: %d size does not align with compression unit size.\n", function, data_run_index ); } #endif remaining_compression_unit_size = 0; } descriptor->data_range_flags = LIBFDATA_RANGE_FLAG_IS_COMPRESSED; } if( data_run_size < remaining_compression_unit_size ) { data_segment_size = data_run_size; } else { data_segment_size = remaining_compression_unit_size; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( ( data_run->range_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) != 0 ) { data_segment_type = "sparse "; } else { data_segment_type = ""; } libcnotify_printf( "%s: compression unit: %d %sdata segment offset: 0x%08" PRIx64 ", size: %" PRIu64 ".\n", function, descriptor_index, data_segment_type, data_segment_offset, data_segment_size ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ if( libfsntfs_compression_unit_descriptor_append_data_segment( descriptor, data_run_offset, data_segment_size, data_run->range_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append data segment to compressed block descriptor: %d.", function, descriptor_index ); goto on_error; } if( ( data_run->range_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) == 0 ) { data_run_offset += data_segment_size; } data_segment_offset += data_segment_size; data_run_size -= data_segment_size; remaining_compression_unit_size -= data_segment_size; if( remaining_compression_unit_size == 0 ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( libfsntfs_compression_unit_descriptor_print( descriptor, io_handle, descriptor_index, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print the compressed block descriptor: %d.", function, descriptor_index ); goto on_error; } } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ if( libcdata_array_append_entry( ( *data_handle )->descriptors_array, &entry_index, (intptr_t *) descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append compressed block descriptor: %d to array.", function, descriptor_index ); goto on_error; } data_offset += descriptor->compression_unit_size; descriptor = NULL; descriptor_index++; } } total_data_run_index++; } if( libfsntfs_mft_attribute_get_next_attribute( safe_mft_attribute, &safe_mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve next MFT attribute: %d.", function, attribute_index ); goto on_error; } attribute_index++; } if( calculated_allocated_data_size != stored_allocated_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: size of data runs: %" PRIu64 " does not match allocated data size: %" PRIu64 ".", function, calculated_allocated_data_size, stored_allocated_data_size ); goto on_error; } if( remaining_compression_unit_size != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid remaining compression unit size value out of bounds.", function ); goto on_error; } ( *data_handle )->compression_unit_size = compression_unit_size; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "\n" ); } #endif return( 1 ); on_error: if( descriptor != NULL ) { libfsntfs_compression_unit_descriptor_free( &descriptor, NULL ); } if( *data_handle != NULL ) { if( ( *data_handle )->descriptors_array != NULL ) { libcdata_array_free( &( ( *data_handle )->descriptors_array ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_compression_unit_descriptor_free, NULL ); } memory_free( *data_handle ); *data_handle = NULL; } return( -1 ); } /* Frees a data handle * Returns 1 if successful or -1 on error */ int libfsntfs_compression_unit_data_handle_free( libfsntfs_compression_unit_data_handle_t **data_handle, libcerror_error_t **error ) { static char *function = "libfsntfs_compression_unit_data_handle_free"; int result = 1; if( data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data handle.", function ); return( -1 ); } if( *data_handle != NULL ) { if( libcdata_array_free( &( ( *data_handle )->descriptors_array ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_compression_unit_descriptor_free, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free descriptors array.", function ); result = -1; } memory_free( *data_handle ); *data_handle = NULL; } return( result ); } /* Retrieves the number of descriptors * Returns 1 if successful or -1 on error */ int libfsntfs_compression_unit_data_handle_get_number_of_descriptors( libfsntfs_compression_unit_data_handle_t *data_handle, int *number_of_descriptors, libcerror_error_t **error ) { static char *function = "libfsntfs_compression_unit_data_handle_get_number_of_descriptors"; if( data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data handle.", function ); return( -1 ); } if( libcdata_array_get_number_of_entries( data_handle->descriptors_array, number_of_descriptors, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of entries from descriptors array.", function ); return( -1 ); } return( 1 ); } /* Retrieves a specific descriptor * Returns 1 if successful or -1 on error */ int libfsntfs_compression_unit_data_handle_get_descriptor_by_index( libfsntfs_compression_unit_data_handle_t *data_handle, int descriptor_index, libfsntfs_compression_unit_descriptor_t **descriptor, libcerror_error_t **error ) { static char *function = "libfsntfs_compression_unit_data_handle_get_descriptor_by_index"; if( data_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data handle.", function ); return( -1 ); } if( libcdata_array_get_entry_by_index( data_handle->descriptors_array, descriptor_index, (intptr_t **) descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry: %d from descriptors array.", function, descriptor_index ); return( -1 ); } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_compression_unit_data_handle.h ================================================ /* * The compression unit data handle functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_COMPRESSION_UNIT_DATA_HANDLE_H ) #define _LIBFSNTFS_COMPRESSION_UNIT_DATA_HANDLE_H #include #include #include "libfsntfs_compression_unit_descriptor.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_mft_attribute.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_compression_unit_data_handle libfsntfs_compression_unit_data_handle_t; struct libfsntfs_compression_unit_data_handle { /* The compression unit descriptors array */ libcdata_array_t *descriptors_array; /* The compression unit size */ size_t compression_unit_size; }; int libfsntfs_compression_unit_data_handle_initialize( libfsntfs_compression_unit_data_handle_t **data_handle, libfsntfs_io_handle_t *io_handle, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ); int libfsntfs_compression_unit_data_handle_free( libfsntfs_compression_unit_data_handle_t **data_handle, libcerror_error_t **error ); int libfsntfs_compression_unit_data_handle_get_number_of_descriptors( libfsntfs_compression_unit_data_handle_t *data_handle, int *number_of_descriptors, libcerror_error_t **error ); int libfsntfs_compression_unit_data_handle_get_descriptor_by_index( libfsntfs_compression_unit_data_handle_t *data_handle, int descriptor_index, libfsntfs_compression_unit_descriptor_t **descriptor, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_COMPRESSION_UNIT_DATA_HANDLE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_compression_unit_descriptor.c ================================================ /* * Compression unit descriptor functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_cluster_block_data.h" #include "libfsntfs_compression_unit_descriptor.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libfdata.h" /* Creates a compression unit descriptor * Make sure the value compression_unit_descriptor is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_compression_unit_descriptor_initialize( libfsntfs_compression_unit_descriptor_t **compression_unit_descriptor, libcerror_error_t **error ) { static char *function = "libfsntfs_compression_unit_descriptor_initialize"; if( compression_unit_descriptor == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid compression unit descriptor.", function ); return( -1 ); } if( *compression_unit_descriptor != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid compression unit descriptor value already set.", function ); return( -1 ); } *compression_unit_descriptor = memory_allocate_structure( libfsntfs_compression_unit_descriptor_t ); if( *compression_unit_descriptor == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create compression unit descriptor.", function ); goto on_error; } if( memory_set( *compression_unit_descriptor, 0, sizeof( libfsntfs_compression_unit_descriptor_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear compression unit descriptor.", function ); memory_free( *compression_unit_descriptor ); *compression_unit_descriptor = NULL; return( -1 ); } if( libfdata_stream_initialize( &( ( *compression_unit_descriptor )->data_stream ), NULL, NULL, NULL, NULL, (ssize_t (*)(intptr_t *, intptr_t *, int, int, uint8_t *, size_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsntfs_cluster_block_data_read_segment_data, NULL, (off64_t (*)(intptr_t *, intptr_t *, int, int, off64_t, libcerror_error_t **)) &libfsntfs_cluster_block_data_seek_segment_offset, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create data stream.", function ); goto on_error; } return( 1 ); on_error: if( *compression_unit_descriptor != NULL ) { memory_free( *compression_unit_descriptor ); *compression_unit_descriptor = NULL; } return( -1 ); } /* Frees a compression unit descriptor * Returns 1 if successful or -1 on error */ int libfsntfs_compression_unit_descriptor_free( libfsntfs_compression_unit_descriptor_t **compression_unit_descriptor, libcerror_error_t **error ) { static char *function = "libfsntfs_compression_unit_descriptor_free"; int result = 1; if( compression_unit_descriptor == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid compression unit descriptor.", function ); return( -1 ); } if( *compression_unit_descriptor != NULL ) { if( libfdata_stream_free( &( ( *compression_unit_descriptor )->data_stream ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free data stream.", function ); result = -1; } memory_free( *compression_unit_descriptor ); *compression_unit_descriptor = NULL; } return( result ); } /* Appends a data segment * Returns 1 if successful or -1 on error */ int libfsntfs_compression_unit_descriptor_append_data_segment( libfsntfs_compression_unit_descriptor_t *compression_unit_descriptor, off64_t segment_offset, size64_t segment_size, uint32_t segment_flags, libcerror_error_t **error ) { static char *function = "libfsntfs_compression_unit_descriptor_append_data_segment"; int segment_index = 0; if( compression_unit_descriptor == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid compression unit descriptor.", function ); return( -1 ); } if( libfdata_stream_append_segment( compression_unit_descriptor->data_stream, &segment_index, 0, segment_offset, segment_size, segment_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append data run to array.", function ); return( -1 ); } compression_unit_descriptor->data_size += segment_size; return( 1 ); } #if defined( HAVE_DEBUG_OUTPUT ) /* Debug prints the compression unit descriptor * Returns 1 if successful or -1 on error */ int libfsntfs_compression_unit_descriptor_print( libfsntfs_compression_unit_descriptor_t *compression_unit_descriptor, libfsntfs_io_handle_t *io_handle, int compression_unit_descriptor_index, libcerror_error_t **error ) { char *compression_unit_data_type = NULL; static char *function = "libfsntfs_compression_unit_descriptor_print"; size64_t segment_size = 0; off64_t segment_offset = 0; uint32_t segment_flags = 0; int number_of_segments = 0; int segment_file_index = 0; int segment_index = 0; if( compression_unit_descriptor == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid compression unit descriptor.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( ( compression_unit_descriptor->data_range_flags & LIBFDATA_RANGE_FLAG_IS_COMPRESSED ) != 0 ) { compression_unit_data_type = "compressed"; } else if( ( compression_unit_descriptor->data_range_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) != 0 ) { compression_unit_data_type = "sparse"; } else { compression_unit_data_type = "uncompressed"; } libcnotify_printf( "%s: %" PRIu64 " blocks %s compression unit: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").\n", function, compression_unit_descriptor->data_size / io_handle->cluster_block_size, compression_unit_data_type, compression_unit_descriptor_index, compression_unit_descriptor->data_offset, compression_unit_descriptor->data_offset ); if( libfdata_stream_get_number_of_segments( compression_unit_descriptor->data_stream, &number_of_segments, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of segments.", function ); return( -1 ); } for( segment_index = 0; segment_index < number_of_segments; segment_index++ ) { if( libfdata_stream_get_segment_by_index( compression_unit_descriptor->data_stream, segment_index, &segment_file_index, &segment_offset, &segment_size, &segment_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve segment: %d.", function, segment_index ); return( -1 ); } if( ( segment_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) != 0 ) { libcnotify_printf( "%s: segment: %d sparse of size: %" PRIu64 "\n", function, segment_index, segment_size ); } else { libcnotify_printf( "%s: segment: %d at offset: 0x%08" PRIx64 " of size: %" PRIu64 "\n", function, segment_index, segment_offset, segment_size ); } } libcnotify_printf( "\n" ); return( 1 ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ ================================================ FILE: libfsntfs/libfsntfs_compression_unit_descriptor.h ================================================ /* * Compression unit descriptor functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_COMPRESSION_UNIT_DESCRIPTOR_H ) #define _LIBFSNTFS_COMPRESSION_UNIT_DESCRIPTOR_H #include #include #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfdata.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_compression_unit_descriptor libfsntfs_compression_unit_descriptor_t; struct libfsntfs_compression_unit_descriptor { /* The data run offset */ off64_t data_run_offset; /* The data offset */ off64_t data_offset; /* The data size */ size64_t data_size; /* The compression unit size */ size64_t compression_unit_size; /* The data range flags */ uint32_t data_range_flags; /* The data stream */ libfdata_stream_t *data_stream; }; int libfsntfs_compression_unit_descriptor_initialize( libfsntfs_compression_unit_descriptor_t **compression_unit_descriptor, libcerror_error_t **error ); int libfsntfs_compression_unit_descriptor_free( libfsntfs_compression_unit_descriptor_t **compression_unit_descriptor, libcerror_error_t **error ); int libfsntfs_compression_unit_descriptor_append_data_segment( libfsntfs_compression_unit_descriptor_t *compression_unit_descriptor, off64_t segment_offset, size64_t segment_size, uint32_t segment_flags, libcerror_error_t **error ); #if defined( HAVE_DEBUG_OUTPUT ) int libfsntfs_compression_unit_descriptor_print( libfsntfs_compression_unit_descriptor_t *compression_unit_descriptor, libfsntfs_io_handle_t *io_handle, int compression_unit_descriptor_index, libcerror_error_t **error ); #endif /* defined( HAVE_DEBUG_OUTPUT ) */ #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_COMPRESSION_UNIT_DESCRIPTOR_H ) */ ================================================ FILE: libfsntfs/libfsntfs_data_run.c ================================================ /* * Data run functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_data_run.h" #include "libfsntfs_definitions.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" /* Creates a data run * Make sure the value data_run is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_data_run_initialize( libfsntfs_data_run_t **data_run, libcerror_error_t **error ) { static char *function = "libfsntfs_data_run_initialize"; if( data_run == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data run.", function ); return( -1 ); } if( *data_run != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid data run value already set.", function ); return( -1 ); } *data_run = memory_allocate_structure( libfsntfs_data_run_t ); if( *data_run == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create data run.", function ); goto on_error; } if( memory_set( *data_run, 0, sizeof( libfsntfs_data_run_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear data run.", function ); memory_free( *data_run ); *data_run = NULL; return( -1 ); } return( 1 ); on_error: if( *data_run != NULL ) { memory_free( *data_run ); *data_run = NULL; } return( -1 ); } /* Frees a data run * Returns 1 if successful or -1 on error */ int libfsntfs_data_run_free( libfsntfs_data_run_t **data_run, libcerror_error_t **error ) { static char *function = "libfsntfs_data_run_free"; if( data_run == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data run.", function ); return( -1 ); } if( *data_run != NULL ) { memory_free( *data_run ); *data_run = NULL; } return( 1 ); } /* Clones a data run * Returns 1 if successful or -1 on error */ int libfsntfs_data_run_clone( libfsntfs_data_run_t **destination_data_run, libfsntfs_data_run_t *source_data_run, libcerror_error_t **error ) { static char *function = "libfsntfs_data_run_clone"; if( destination_data_run == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data run.", function ); return( -1 ); } if( *destination_data_run != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid destination data run value already set.", function ); return( -1 ); } if( source_data_run == NULL ) { *destination_data_run = source_data_run; return( 1 ); } *destination_data_run = memory_allocate_structure( libfsntfs_data_run_t ); if( *destination_data_run == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create destnation data run.", function ); goto on_error; } if( memory_copy( *destination_data_run, source_data_run, sizeof( libfsntfs_data_run_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to copy source data run to destination.", function ); goto on_error; } return( 1 ); on_error: if( *destination_data_run != NULL ) { memory_free( *destination_data_run ); *destination_data_run = NULL; } return( -1 ); } /* Reads the data run * Returns 1 if successful or -1 on error */ ssize_t libfsntfs_data_run_read_data( libfsntfs_data_run_t *data_run, libfsntfs_io_handle_t *io_handle, const uint8_t *data, size_t data_size, uint64_t last_cluster_block_number, libcerror_error_t **error ) { static char *function = "libfsntfs_data_run_read_data"; size_t data_offset = 0; size_t data_run_data_size = 0; uint64_t number_of_cluster_blocks = 0; int64_t cluster_block_number = 0; uint8_t cluster_block_value_size = 0; uint8_t number_of_blocks_value_size = 0; uint8_t value_index = 0; uint8_t value_size_tuple = 0; if( data_run == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data run.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( ( data_size < 1 ) || ( data_size > (size_t) SSIZE_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } value_size_tuple = data[ 0 ]; number_of_blocks_value_size = value_size_tuple & 0x0f; cluster_block_value_size = ( value_size_tuple >> 4 ) & 0x0f; data_run_data_size = 1 + number_of_blocks_value_size + cluster_block_value_size; if( data_run_data_size > data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: data size value too small.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: data run:\n", function ); libcnotify_print_data( data, data_run_data_size, 0 ); } #endif #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: value sizes\t\t\t\t: %" PRIu8 ", %" PRIu8 "\n", function, number_of_blocks_value_size, cluster_block_value_size ); } #endif /* A number of cluster blocks value size of zero indicates the end of the data runs. */ if( number_of_blocks_value_size == 0 ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "\n%s: end of data runs (number of cluster blocks value size is zero).\n\n", function ); } #endif data_run->start_offset = 0; data_run->size = 0; data_run->range_flags = 0; return( 1 ); } data_offset = 1; /* Determine the number of cluster blocks value */ number_of_cluster_blocks = 0; for( value_index = number_of_blocks_value_size; value_index > 0; value_index-- ) { number_of_cluster_blocks <<= 8; number_of_cluster_blocks |= data[ data_offset + value_index - 1 ]; } data_offset += number_of_blocks_value_size; if( cluster_block_value_size == 0 ) { data_run->cluster_block_number = 0; data_run->start_offset = 0; data_run->range_flags = LIBFDATA_RANGE_FLAG_IS_SPARSE; } else { /* Determine the cluster block number value */ if( ( last_cluster_block_number != 0 ) && ( ( data[ data_offset + cluster_block_value_size - 1 ] & 0x80 ) != 0 ) ) { cluster_block_number = -1; } else { cluster_block_number = 0; } for( value_index = cluster_block_value_size; value_index > 0; value_index-- ) { cluster_block_number = (int64_t) ( (uint64_t) cluster_block_number << 8 ); cluster_block_number |= data[ data_offset + value_index - 1 ]; } data_offset += cluster_block_value_size; data_run->cluster_block_number = last_cluster_block_number + cluster_block_number; data_run->start_offset = (off64_t) ( data_run->cluster_block_number * io_handle->cluster_block_size ); data_run->range_flags = 0; } data_run->size = (size64_t) ( number_of_cluster_blocks * io_handle->cluster_block_size ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: number of cluster blocks\t\t\t: %" PRIu64 " (size: %" PRIu64 ")\n", function, number_of_cluster_blocks, data_run->size ); libcnotify_printf( "%s: cluster block number\t\t\t: %" PRIu64 " (%" PRIi64 ") (offset: 0x%08" PRIx64 ")\n", function, data_run->cluster_block_number, cluster_block_number, data_run->start_offset ); if( ( data_run->range_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) != 0 ) { libcnotify_printf( "\tIs sparse\n" ); } libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ return( (ssize_t) data_offset ); } ================================================ FILE: libfsntfs/libfsntfs_data_run.h ================================================ /* * Data run functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_DATA_RUN_H ) #define _LIBFSNTFS_DATA_RUN_H #include #include #include "libfsntfs_io_handle.h" #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_data_run libfsntfs_data_run_t; struct libfsntfs_data_run { /* The cluster block number */ uint64_t cluster_block_number; /* The start offset */ off64_t start_offset; /* The size */ size64_t size; /* The range flags */ uint32_t range_flags; }; int libfsntfs_data_run_initialize( libfsntfs_data_run_t **data_run, libcerror_error_t **error ); int libfsntfs_data_run_free( libfsntfs_data_run_t **data_run, libcerror_error_t **error ); int libfsntfs_data_run_clone( libfsntfs_data_run_t **destination_data_run, libfsntfs_data_run_t *source_data_run, libcerror_error_t **error ); ssize_t libfsntfs_data_run_read_data( libfsntfs_data_run_t *data_run, libfsntfs_io_handle_t *io_handle, const uint8_t *data, size_t data_size, uint64_t last_cluster_block_number, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_DATA_RUN_H ) */ ================================================ FILE: libfsntfs/libfsntfs_data_stream.c ================================================ /* * Data stream functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_cluster_block_stream.h" #include "libfsntfs_data_stream.h" #include "libfsntfs_definitions.h" #include "libfsntfs_extent.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_types.h" /* Creates a data stream * Make sure the value data_stream is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_data_stream_initialize( libfsntfs_data_stream_t **data_stream, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfsntfs_mft_attribute_t *data_attribute, libcerror_error_t **error ) { libfsntfs_internal_data_stream_t *internal_data_stream = NULL; static char *function = "libfsntfs_data_stream_initialize"; if( data_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data stream.", function ); return( -1 ); } if( *data_stream != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid data stream value already set.", function ); return( -1 ); } if( data_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data attribute.", function ); return( -1 ); } internal_data_stream = memory_allocate_structure( libfsntfs_internal_data_stream_t ); if( internal_data_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create data stream.", function ); goto on_error; } if( memory_set( internal_data_stream, 0, sizeof( libfsntfs_internal_data_stream_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear data stream.", function ); memory_free( internal_data_stream ); return( -1 ); } if( libfsntfs_mft_attribute_get_data_extents_array( data_attribute, io_handle, &( internal_data_stream->extents_array ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine extents array.", function ); goto on_error; } if( libfsntfs_cluster_block_stream_initialize( &( internal_data_stream->data_cluster_block_stream ), io_handle, data_attribute, NULL, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create data cluster block stream.", function ); goto on_error; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_initialize( &( internal_data_stream->read_write_lock ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize read/write lock.", function ); goto on_error; } #endif internal_data_stream->file_io_handle = file_io_handle; internal_data_stream->data_attribute = data_attribute; *data_stream = (libfsntfs_data_stream_t *) internal_data_stream; return( 1 ); on_error: if( internal_data_stream != NULL ) { if( internal_data_stream->data_cluster_block_stream != NULL ) { libfdata_stream_free( &( internal_data_stream->data_cluster_block_stream ), NULL ); } if( internal_data_stream->extents_array != NULL ) { libcdata_array_free( &( internal_data_stream->extents_array ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_extent_free, NULL ); } memory_free( internal_data_stream ); } return( -1 ); } /* Frees a data stream * Returns 1 if successful or -1 on error */ int libfsntfs_data_stream_free( libfsntfs_data_stream_t **data_stream, libcerror_error_t **error ) { libfsntfs_internal_data_stream_t *internal_data_stream = NULL; static char *function = "libfsntfs_data_stream_free"; int result = 1; if( data_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data stream.", function ); return( -1 ); } if( *data_stream != NULL ) { internal_data_stream = (libfsntfs_internal_data_stream_t *) *data_stream; *data_stream = NULL; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_free( &( internal_data_stream->read_write_lock ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free read/write lock.", function ); result = -1; } #endif /* The file_io_handle and data_attribute references are freed elsewhere */ if( libfdata_stream_free( &( internal_data_stream->data_cluster_block_stream ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free data cluster block stream.", function ); result = -1; } if( libcdata_array_free( &( internal_data_stream->extents_array ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_extent_free, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free extents array.", function ); result = -1; } memory_free( internal_data_stream ); } return( result ); } /* Retrieves the size of the UTF-8 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_data_stream_get_utf8_name_size( libfsntfs_data_stream_t *data_stream, size_t *utf8_string_size, libcerror_error_t **error ) { libfsntfs_internal_data_stream_t *internal_data_stream = NULL; static char *function = "libfsntfs_data_stream_get_utf8_name_size"; int result = 1; if( data_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data stream.", function ); return( -1 ); } internal_data_stream = (libfsntfs_internal_data_stream_t *) data_stream; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_attribute_get_utf8_name_size( internal_data_stream->data_attribute, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-8 name from data stream.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the UTF-8 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_data_stream_get_utf8_name( libfsntfs_data_stream_t *data_stream, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { libfsntfs_internal_data_stream_t *internal_data_stream = NULL; static char *function = "libfsntfs_data_stream_get_utf8_name"; int result = 1; if( data_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data stream.", function ); return( -1 ); } internal_data_stream = (libfsntfs_internal_data_stream_t *) data_stream; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_attribute_get_utf8_name( internal_data_stream->data_attribute, utf8_string, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 name from data stream.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the size of the UTF-16 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_data_stream_get_utf16_name_size( libfsntfs_data_stream_t *data_stream, size_t *utf16_string_size, libcerror_error_t **error ) { libfsntfs_internal_data_stream_t *internal_data_stream = NULL; static char *function = "libfsntfs_data_stream_get_utf16_name_size"; int result = 1; if( data_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data stream.", function ); return( -1 ); } internal_data_stream = (libfsntfs_internal_data_stream_t *) data_stream; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_attribute_get_utf16_name_size( internal_data_stream->data_attribute, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-16 name from data stream.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the UTF-16 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_data_stream_get_utf16_name( libfsntfs_data_stream_t *data_stream, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { libfsntfs_internal_data_stream_t *internal_data_stream = NULL; static char *function = "libfsntfs_data_stream_get_utf16_name"; int result = 1; if( data_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data stream.", function ); return( -1 ); } internal_data_stream = (libfsntfs_internal_data_stream_t *) data_stream; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_attribute_get_utf16_name( internal_data_stream->data_attribute, utf16_string, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 name from data stream.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Reads data at the current offset * Returns the number of bytes read or -1 on error */ ssize_t libfsntfs_data_stream_read_buffer( libfsntfs_data_stream_t *data_stream, void *buffer, size_t buffer_size, libcerror_error_t **error ) { libfsntfs_internal_data_stream_t *internal_data_stream = NULL; static char *function = "libfsntfs_data_stream_read_buffer"; ssize_t read_count = 0; if( data_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data stream.", function ); return( -1 ); } internal_data_stream = (libfsntfs_internal_data_stream_t *) data_stream; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif read_count = libfdata_stream_read_buffer( internal_data_stream->data_cluster_block_stream, (intptr_t *) internal_data_stream->file_io_handle, buffer, buffer_size, 0, error ); if( read_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read from data cluster block stream.", function ); read_count = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( read_count ); } /* Reads data at a specific offset * Returns the number of bytes read or -1 on error */ ssize_t libfsntfs_data_stream_read_buffer_at_offset( libfsntfs_data_stream_t *data_stream, void *buffer, size_t buffer_size, off64_t offset, libcerror_error_t **error ) { libfsntfs_internal_data_stream_t *internal_data_stream = NULL; static char *function = "libfsntfs_data_stream_read_buffer_at_offset"; ssize_t read_count = 0; if( data_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data stream.", function ); return( -1 ); } internal_data_stream = (libfsntfs_internal_data_stream_t *) data_stream; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif read_count = libfdata_stream_read_buffer_at_offset( internal_data_stream->data_cluster_block_stream, (intptr_t *) internal_data_stream->file_io_handle, buffer, buffer_size, offset, 0, error ); if( read_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read from data cluster block stream.", function ); read_count = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( read_count ); } /* Seeks a certain offset * Returns the offset if seek is successful or -1 on error */ off64_t libfsntfs_data_stream_seek_offset( libfsntfs_data_stream_t *data_stream, off64_t offset, int whence, libcerror_error_t **error ) { libfsntfs_internal_data_stream_t *internal_data_stream = NULL; static char *function = "libfsntfs_data_stream_seek_offset"; if( data_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data stream.", function ); return( -1 ); } internal_data_stream = (libfsntfs_internal_data_stream_t *) data_stream; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif offset = libfdata_stream_seek_offset( internal_data_stream->data_cluster_block_stream, offset, whence, error ); if( offset == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek offset in data cluster block stream.", function ); offset = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( offset ); } /* Retrieves the current offset * Returns the offset if successful or -1 on error */ int libfsntfs_data_stream_get_offset( libfsntfs_data_stream_t *data_stream, off64_t *offset, libcerror_error_t **error ) { libfsntfs_internal_data_stream_t *internal_data_stream = NULL; static char *function = "libfsntfs_data_stream_get_offset"; int result = 1; if( data_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data stream.", function ); return( -1 ); } internal_data_stream = (libfsntfs_internal_data_stream_t *) data_stream; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfdata_stream_get_offset( internal_data_stream->data_cluster_block_stream, offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve offset from data cluster block stream.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the size * Returns 1 if successful or -1 on error */ int libfsntfs_data_stream_get_size( libfsntfs_data_stream_t *data_stream, size64_t *size, libcerror_error_t **error ) { libfsntfs_internal_data_stream_t *internal_data_stream = NULL; static char *function = "libfsntfs_data_stream_get_size"; int result = 1; if( data_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data stream.", function ); return( -1 ); } internal_data_stream = (libfsntfs_internal_data_stream_t *) data_stream; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfdata_stream_get_size( internal_data_stream->data_cluster_block_stream, size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size from data cluster block stream.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the number of extents (decoded data runs) * Returns 1 if successful or -1 on error */ int libfsntfs_data_stream_get_number_of_extents( libfsntfs_data_stream_t *data_stream, int *number_of_extents, libcerror_error_t **error ) { libfsntfs_internal_data_stream_t *internal_data_stream = NULL; static char *function = "libfsntfs_data_stream_get_number_of_extents"; int result = 1; if( data_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data stream.", function ); return( -1 ); } internal_data_stream = (libfsntfs_internal_data_stream_t *) data_stream; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libcdata_array_get_number_of_entries( internal_data_stream->extents_array, number_of_extents, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of extents.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves a specific extent (decoded data run) * Returns 1 if successful or -1 on error */ int libfsntfs_data_stream_get_extent_by_index( libfsntfs_data_stream_t *data_stream, int extent_index, off64_t *extent_offset, size64_t *extent_size, uint32_t *extent_flags, libcerror_error_t **error ) { libfsntfs_extent_t *data_extent = NULL; libfsntfs_internal_data_stream_t *internal_data_stream = NULL; static char *function = "libfsntfs_data_stream_get_extent_by_index"; int result = 1; if( data_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data stream.", function ); return( -1 ); } internal_data_stream = (libfsntfs_internal_data_stream_t *) data_stream; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libcdata_array_get_entry_by_index( internal_data_stream->extents_array, extent_index, (intptr_t **) &data_extent, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve extent: %d.", function, extent_index ); result = -1; } if( result == 1 ) { if( libfsntfs_extent_get_values( data_extent, extent_offset, extent_size, extent_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve extent: %d values.", function, extent_index ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_data_stream->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } ================================================ FILE: libfsntfs/libfsntfs_data_stream.h ================================================ /* * Data stream functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_DATA_STREAM_H ) #define _LIBFSNTFS_DATA_STREAM_H #include #include #include "libfsntfs_extern.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_types.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_internal_data_stream libfsntfs_internal_data_stream_t; struct libfsntfs_internal_data_stream { /* The file IO handle */ libbfio_handle_t *file_io_handle; /* The $DATA attribute */ libfsntfs_mft_attribute_t *data_attribute; /* The data extents array */ libcdata_array_t *extents_array; /* The $DATA attribute cluster block stream */ libfdata_stream_t *data_cluster_block_stream; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) /* The read/write lock */ libcthreads_read_write_lock_t *read_write_lock; #endif }; int libfsntfs_data_stream_initialize( libfsntfs_data_stream_t **data_stream, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfsntfs_mft_attribute_t *data_attribute, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_data_stream_free( libfsntfs_data_stream_t **data_stream, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_data_stream_get_utf8_name_size( libfsntfs_data_stream_t *data_stream, size_t *utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_data_stream_get_utf8_name( libfsntfs_data_stream_t *data_stream, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_data_stream_get_utf16_name_size( libfsntfs_data_stream_t *data_stream, size_t *utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_data_stream_get_utf16_name( libfsntfs_data_stream_t *data_stream, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ ssize_t libfsntfs_data_stream_read_buffer( libfsntfs_data_stream_t *data_stream, void *buffer, size_t buffer_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ ssize_t libfsntfs_data_stream_read_buffer_at_offset( libfsntfs_data_stream_t *data_stream, void *buffer, size_t buffer_size, off64_t offset, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ off64_t libfsntfs_data_stream_seek_offset( libfsntfs_data_stream_t *data_stream, off64_t offset, int whence, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_data_stream_get_offset( libfsntfs_data_stream_t *data_stream, off64_t *offset, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_data_stream_get_size( libfsntfs_data_stream_t *data_stream, size64_t *size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_data_stream_get_number_of_extents( libfsntfs_data_stream_t *data_stream, int *number_of_extents, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_data_stream_get_extent_by_index( libfsntfs_data_stream_t *data_stream, int extent_index, off64_t *extent_offset, size64_t *extent_size, uint32_t *extent_flags, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_DATA_STREAM_H ) */ ================================================ FILE: libfsntfs/libfsntfs_debug.c ================================================ /* * Debug functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include "libfsntfs_debug.h" #include "libfsntfs_definitions.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libfdatetime.h" #include "libfsntfs_libfguid.h" #include "libfsntfs_libuna.h" #if defined( HAVE_DEBUG_OUTPUT ) /* Prints the MFT attribute data flags */ void libfsntfs_debug_print_mft_attribute_data_flags( uint16_t mft_attribute_data_flags ) { if( ( mft_attribute_data_flags & 0x0001 ) != 0 ) { libcnotify_printf( "\tIs compressed\n" ); } if( ( mft_attribute_data_flags & 0x4000 ) != 0 ) { libcnotify_printf( "\tIs encrypted\n" ); } if( ( mft_attribute_data_flags & 0x8000 ) != 0 ) { libcnotify_printf( "\tIs sparse\n" ); } } /* Prints the MFT entry data flags */ void libfsntfs_debug_print_mft_entry_flags( uint16_t mft_entry_flags ) { if( ( mft_entry_flags & LIBFSNTFS_MFT_ENTRY_FLAG_IN_USE ) != 0 ) { libcnotify_printf( "\tIn use (FILE_RECORD_SEGMENT_IN_USE)\n" ); } if( ( mft_entry_flags & LIBFSNTFS_MFT_ENTRY_FLAG_INDEX_PRESENT ) != 0 ) { libcnotify_printf( "\tHas file name index (FILE_FILE_NAME_INDEX_PRESENT)\n" ); } if( ( mft_entry_flags & 0x0004 ) != 0 ) { libcnotify_printf( "\tUnknown: 0x0004\n" ); } if( ( mft_entry_flags & 0x0008 ) != 0 ) { libcnotify_printf( "\tUnknown: 0x0008\n" ); } } /* Prints the file attribute flags */ void libfsntfs_debug_print_file_attribute_flags( uint32_t file_attribute_flags ) { if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_READ_ONLY ) != 0 ) { libcnotify_printf( "\tIs read-only (FILE_ATTRIBUTE_READ_ONLY)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_HIDDEN ) != 0 ) { libcnotify_printf( "\tIs hidden (FILE_ATTRIBUTE_HIDDEN)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_SYSTEM ) != 0 ) { libcnotify_printf( "\tIs system (FILE_ATTRIBUTE_SYSTEM)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_DIRECTORY ) != 0 ) { libcnotify_printf( "\tIs directory (FILE_ATTRIBUTE_DIRECTORY)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_ARCHIVE ) != 0 ) { libcnotify_printf( "\tShould be archived (FILE_ATTRIBUTE_ARCHIVE)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_DEVICE ) != 0 ) { libcnotify_printf( "\tIs device (FILE_ATTRIBUTE_DEVICE)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_NORMAL ) != 0 ) { libcnotify_printf( "\tIs normal (FILE_ATTRIBUTE_NORMAL)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_TEMPORARY ) != 0 ) { libcnotify_printf( "\tIs temporary (FILE_ATTRIBUTE_TEMPORARY)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_SPARSE_FILE ) != 0 ) { libcnotify_printf( "\tIs a sparse file (FILE_ATTRIBUTE_SPARSE_FILE)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_REPARSE_POINT ) != 0 ) { libcnotify_printf( "\tIs a reparse point or symbolic link (FILE_ATTRIBUTE_FLAG_REPARSE_POINT)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_COMPRESSED ) != 0 ) { libcnotify_printf( "\tIs compressed (FILE_ATTRIBUTE_COMPRESSED)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_OFFLINE ) != 0 ) { libcnotify_printf( "\tIs offline (FILE_ATTRIBUTE_OFFLINE)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_NOT_CONTENT_INDEXED ) != 0 ) { libcnotify_printf( "\tContent should not be indexed (FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_ENCRYPTED ) != 0 ) { libcnotify_printf( "\tIs encrypted (FILE_ATTRIBUTE_ENCRYPTED)\n" ); } if( ( file_attribute_flags & LIBFSNTFS_FILE_ATTRIBUTE_FLAG_VIRTUAL ) != 0 ) { libcnotify_printf( "\tIs virtual (FILE_ATTRIBUTE_VIRTUAL)\n" ); } if( ( file_attribute_flags & 0x10000000UL ) != 0 ) { libcnotify_printf( "\tUnknown (0x10000000)\n" ); } if( ( file_attribute_flags & 0x20000000UL ) != 0 ) { libcnotify_printf( "\tIs index view (0x20000000)\n" ); } } /* Prints the index node flags */ void libfsntfs_debug_print_index_node_flags( uint32_t index_node_flags ) { if( ( index_node_flags & 0x00000001UL ) != 0 ) { libcnotify_printf( "\tIs branch node\n" ); } } /* Prints the index value flags */ void libfsntfs_debug_print_index_value_flags( uint32_t index_value_flags ) { if( ( index_value_flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 ) { libcnotify_printf( "\tIs branch node\n" ); } if( ( index_value_flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_LAST ) != 0 ) { libcnotify_printf( "\tIs last\n" ); } } /* Prints the reparse point type and flags */ void libfsntfs_debug_print_reparse_point_tag( uint32_t tag ) { if( tag == 0x00000000 ) { libcnotify_printf( "\tReserved (IO_REPARSE_TAG_RESERVED_ZERO)\n" ); } if( tag == 0x00000001 ) { libcnotify_printf( "\tReserved (IO_REPARSE_TAG_RESERVED_ONE)\n" ); } if( tag == 0x80000005 ) { libcnotify_printf( "\tHome server drive extender (IO_REPARSE_TAG_DRIVER_EXTENDER)\n" ); } if( tag == 0x80000006 ) { libcnotify_printf( "\tHierarchical Storage Manager (IO_REPARSE_TAG_HSM2)\n" ); } if( tag == 0x80000007 ) { libcnotify_printf( "\tSingle-instance storage (SIS) (IO_REPARSE_TAG_SIS)\n" ); } if( tag == 0x8000000a ) { libcnotify_printf( "\tDistributed File System (DFS) (IO_REPARSE_TAG_DFS)\n" ); } if( tag == 0x8000000b ) { libcnotify_printf( "\tFilter manager test harness (IO_REPARSE_TAG_FILTER_MANAGER)\n" ); } if( tag == 0x80000012 ) { libcnotify_printf( "\tDistributed File System (DFS) (IO_REPARSE_TAG_DFSR)\n" ); } if( tag == 0xa0000003 ) { libcnotify_printf( "\tMount point (IO_REPARSE_TAG_MOUNT_POINT)\n" ); } if( tag == 0xa000000c ) { libcnotify_printf( "\tSymbolic link (IO_REPARSE_TAG_SYMLINK)\n" ); } if( tag == 0xc0000004 ) { libcnotify_printf( "\tHierarchical Storage Manager (IO_REPARSE_TAG_HSM)\n" ); } } /* Prints the volume information flags */ void libfsntfs_debug_print_volume_information_flags( uint16_t volume_information_flags ) { if( ( volume_information_flags & 0x0001 ) != 0 ) { libcnotify_printf( "\tIs dirty (VOLUME_IS_DIRTY)\n" ); } if( ( volume_information_flags & 0x0002 ) != 0 ) { libcnotify_printf( "\t(VOLUME_RESIZE_LOG_FILE)\n" ); } if( ( volume_information_flags & 0x0004 ) != 0 ) { libcnotify_printf( "\t(VOLUME_UPGRADE_ON_MOUNT)\n" ); } if( ( volume_information_flags & 0x0008 ) != 0 ) { libcnotify_printf( "\t(VOLUME_MOUNTED_ON_NT4)\n" ); } if( ( volume_information_flags & 0x0010 ) != 0 ) { libcnotify_printf( "\t(VOLUME_DELETE_USN_UNDERWAY)\n" ); } if( ( volume_information_flags & 0x0020 ) != 0 ) { libcnotify_printf( "\t(VOLUME_REPAIR_OBJECT_ID)\n" ); } if( ( volume_information_flags & 0x4000 ) != 0 ) { libcnotify_printf( "\t(VOLUME_CHKDSK_UNDERWAY)\n" ); } if( ( volume_information_flags & 0x8000 ) != 0 ) { libcnotify_printf( "\t(VOLUME_MODIFIED_BY_CHKDSK)\n" ); } } /* Prints the attribute type */ const char *libfsntfs_debug_print_attribute_type( uint32_t attribute_type ) { switch( attribute_type ) { case LIBFSNTFS_ATTRIBUTE_TYPE_UNUSED: return( "Unused" ); case LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION: return( "$STANDARD_INFORMATION" ); case LIBFSNTFS_ATTRIBUTE_TYPE_ATTRIBUTE_LIST: return( "$ATTRIBUTE_LIST" ); case LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME: return( "$FILE_NAME" ); case LIBFSNTFS_ATTRIBUTE_TYPE_OBJECT_IDENTIFIER: return( "$OBJECT_ID" ); case LIBFSNTFS_ATTRIBUTE_TYPE_SECURITY_DESCRIPTOR: return( "$SECURITY_DESCRIPTOR" ); case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME: return( "$VOLUME_NAME" ); case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_INFORMATION: return( "$VOLUME_INFORMATION" ); case LIBFSNTFS_ATTRIBUTE_TYPE_DATA: return( "$DATA" ); case LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ROOT: return( "$INDEX_ROOT" ); case LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ALLOCATION: return( "$INDEX_ALLOCATION" ); case LIBFSNTFS_ATTRIBUTE_TYPE_BITMAP: return( "$BITMAP" ); case LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT: return( "$REPARSE_POINT" ); case LIBFSNTFS_ATTRIBUTE_TYPE_EXTENDED_INFORMATION: return( "$EA_INFORMATION" ); case LIBFSNTFS_ATTRIBUTE_TYPE_EXTENDED: return( "$EA" ); case LIBFSNTFS_ATTRIBUTE_TYPE_PROPERTY_SET: return( "$PROPERTY_SET" ); case LIBFSNTFS_ATTRIBUTE_TYPE_LOGGED_UTILITY_STREAM: return( "$LOGGED_UTILITY_STREAM" ); } return( "Unknown" ); } /* Prints the collation type */ const char *libfsntfs_debug_print_collation_type( uint32_t collation_type ) { switch( collation_type ) { case 0x00000000UL: return( "COLLATION_BINARY" ); case 0x00000001UL: return( "COLLATION_FILENAME" ); case 0x00000002UL: return( "COLLATION_UNICODE_STRING" ); case 0x00000010UL: return( "COLLATION_NTOFS_ULONG" ); case 0x00000011UL: return( "COLLATION_NTOFS_SID" ); case 0x00000012UL: return( "COLLATION_NTOFS_SECURITY_HASH" ); case 0x00000013UL: return( "COLLATION_NTOFS_ULONGS" ); } return( "Unknown" ); } /* Prints the compression method */ const char *libfsntfs_debug_print_compression_method( uint32_t compression_method ) { switch( compression_method ) { case 0: return( "XPRESS4K" ); case 1: return( "LZX" ); case 2: return( "XPRESS8K" ); case 3: return( "XPRESS16K" ); } return( "Unknown" ); } /* Prints the file name attribute name space */ const char *libfsntfs_debug_print_file_name_attribute_name_space( uint8_t name_space ) { switch( name_space ) { case LIBFSNTFS_FILE_NAME_SPACE_POSIX: return( "POSIX" ); case LIBFSNTFS_FILE_NAME_SPACE_WINDOWS: return( "Windows" ); case LIBFSNTFS_FILE_NAME_SPACE_DOS: return( "DOS" ); case LIBFSNTFS_FILE_NAME_SPACE_DOS_WINDOWS: return( "DOS and Windows" ); } return( "UNKNOWN" ); } /* Prints a FILETIME value * Returns 1 if successful or -1 on error */ int libfsntfs_debug_print_filetime_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 ) { char date_time_string[ 32 ]; libfdatetime_filetime_t *filetime = NULL; static char *function = "libfsntfs_debug_print_filetime_value"; if( libfdatetime_filetime_initialize( &filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create filetime.", function ); goto on_error; } if( libfdatetime_filetime_copy_from_byte_stream( filetime, byte_stream, byte_stream_size, byte_order, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy byte stream to filetime.", function ); goto on_error; } if( libfdatetime_filetime_copy_to_utf8_string( filetime, (uint8_t *) date_time_string, 32, string_format_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy filetime to string.", function ); goto on_error; } libcnotify_printf( "%s: %s: %s UTC\n", function_name, value_name, date_time_string ); if( libfdatetime_filetime_free( &filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free filetime.", function ); goto on_error; } return( 1 ); on_error: if( filetime != NULL ) { libfdatetime_filetime_free( &filetime, NULL ); } return( -1 ); } /* Prints a GUID/UUID value * Returns 1 if successful or -1 on error */ int libfsntfs_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 ) { system_character_t guid_string[ 48 ]; libfguid_identifier_t *guid = NULL; static char *function = "libfsntfs_debug_print_guid_value"; if( libfguid_identifier_initialize( &guid, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create GUID.", function ); goto on_error; } if( libfguid_identifier_copy_from_byte_stream( guid, byte_stream, byte_stream_size, byte_order, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy byte stream to GUID.", function ); goto on_error; } if( libfguid_identifier_copy_to_utf8_string( guid, (uint8_t *) guid_string, 48, string_format_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy GUID to string.", function ); goto on_error; } libcnotify_printf( "%s: %s: %s\n", function_name, value_name, guid_string ); if( libfguid_identifier_free( &guid, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free GUID.", function ); goto on_error; } return( 1 ); on_error: if( guid != NULL ) { libfguid_identifier_free( &guid, NULL ); } return( -1 ); } /* Prints an UTF-16 string value * Returns 1 if successful or -1 on error */ int libfsntfs_debug_print_utf16_string_value( const char *function_name, const char *value_name, const uint8_t *byte_stream, size_t byte_stream_size, int byte_order, libcerror_error_t **error ) { system_character_t *string = NULL; static char *function = "libfsntfs_debug_print_utf16_string_value"; size_t string_size = 0; int result = 0; if( ( byte_stream == NULL ) || ( byte_stream_size == 0 ) ) { libcnotify_printf( "%s: %s:\n", function_name, value_name ); return( 1 ); } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libuna_utf16_string_size_from_utf16_stream( byte_stream, byte_stream_size, byte_order, &string_size, error ); #else result = libuna_utf8_string_size_from_utf16_stream( byte_stream, byte_stream_size, byte_order, &string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine size of string.", function ); goto on_error; } if( string_size > ( (size_t) SSIZE_MAX / sizeof( system_character_t ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid string size value exceeds maximum.", function ); goto on_error; } libcnotify_printf( "%s: %s:", function_name, value_name ); if( string_size > 0 ) { string = system_string_allocate( string_size ); if( string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libuna_utf16_string_copy_from_utf16_stream( (libuna_utf16_character_t *) string, string_size, byte_stream, byte_stream_size, byte_order, error ); #else result = libuna_utf8_string_copy_from_utf16_stream( (libuna_utf8_character_t *) string, string_size, byte_stream, byte_stream_size, byte_order, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set string.", function ); goto on_error; } libcnotify_printf( " %s", string ); memory_free( string ); } libcnotify_printf( "\n" ); return( 1 ); on_error: if( string != NULL ) { memory_free( string ); } return( -1 ); } /* Prints the read offsets * Returns 1 if successful or -1 on error */ int libfsntfs_debug_print_read_offsets( libbfio_handle_t *file_io_handle, libcerror_error_t **error ) { static char *function = "libfsntfs_debug_print_read_offsets"; size64_t size = 0; off64_t offset = 0; int number_of_offsets = 0; int offset_iterator = 0; if( file_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file IO handle.", function ); return( -1 ); } if( libbfio_handle_get_number_of_offsets_read( file_io_handle, &number_of_offsets, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of offsets read.", function ); return( -1 ); } libcnotify_printf( "Offsets read:\n" ); for( offset_iterator = 0; offset_iterator < number_of_offsets; offset_iterator++ ) { if( libbfio_handle_get_offset_read( file_io_handle, offset_iterator, &offset, &size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve offset: %d.", function, ( offset_iterator + 1 ) ); return( -1 ); } libcnotify_printf( "%08" PRIi64 " ( 0x%08" PRIx64 " ) - %08" PRIi64 " ( 0x%08" PRIx64 " ) size: %" PRIu64 "\n", offset, offset, offset + (off64_t) size, offset + (off64_t) size, size ); } libcnotify_printf( "\n" ); return( 1 ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ ================================================ FILE: libfsntfs/libfsntfs_debug.h ================================================ /* * Debug functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_DEBUG_H ) #define _LIBFSNTFS_DEBUG_H #include #include #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif #if defined( HAVE_DEBUG_OUTPUT ) void libfsntfs_debug_print_mft_attribute_data_flags( uint16_t mft_attribute_data_flags ); void libfsntfs_debug_print_mft_entry_flags( uint16_t mft_entry_flags ); void libfsntfs_debug_print_file_attribute_flags( uint32_t file_attribute_flags ); void libfsntfs_debug_print_index_node_flags( uint32_t index_node_flags ); void libfsntfs_debug_print_index_value_flags( uint32_t index_value_flags ); void libfsntfs_debug_print_reparse_point_tag( uint32_t tag ); void libfsntfs_debug_print_volume_information_flags( uint16_t volume_information_flags ); const char *libfsntfs_debug_print_attribute_type( uint32_t attribute_type ); const char *libfsntfs_debug_print_file_name_attribute_name_space( uint8_t name_space ); const char *libfsntfs_debug_print_attribute_type( uint32_t attribute_type ); const char *libfsntfs_debug_print_collation_type( uint32_t collation_type ); const char *libfsntfs_debug_print_compression_method( uint32_t compression_method ); int libfsntfs_debug_print_filetime_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 ); int libfsntfs_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 ); int libfsntfs_debug_print_utf16_string_value( const char *function_name, const char *value_name, const uint8_t *byte_stream, size_t byte_stream_size, int byte_order, libcerror_error_t **error ); int libfsntfs_debug_print_read_offsets( libbfio_handle_t *file_io_handle, libcerror_error_t **error ); #endif /* defined( HAVE_DEBUG_OUTPUT ) */ #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_DEBUG_H ) */ ================================================ FILE: libfsntfs/libfsntfs_definitions.h.in ================================================ /* * The internal definitions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_INTERNAL_DEFINITIONS_H ) #define _LIBFSNTFS_INTERNAL_DEFINITIONS_H #include #include #include "libfsntfs_libfdata.h" #define LIBFSNTFS_ENDIAN_BIG _BYTE_STREAM_ENDIAN_BIG #define LIBFSNTFS_ENDIAN_LITTLE _BYTE_STREAM_ENDIAN_LITTLE /* Define HAVE_LOCAL_LIBFSNTFS for local use of libfsntfs */ #if !defined( HAVE_LOCAL_LIBFSNTFS ) #include /* The definitions in are copied here * for local use of libfsntfs */ #else #define LIBFSNTFS_VERSION @VERSION@ /* The version string */ #define LIBFSNTFS_VERSION_STRING "@VERSION@" /* The file access * bit 1 set to 1 for read access * bit 2 set to 1 for write access * bit 3-8 not used */ enum LIBFSNTFS_ACCESS_FLAGS { LIBFSNTFS_ACCESS_FLAG_READ = 0x01, /* Reserved: not supported yet */ LIBFSNTFS_ACCESS_FLAG_WRITE = 0x02 }; /* The file access macros */ #define LIBFSNTFS_OPEN_READ ( LIBFSNTFS_ACCESS_FLAG_READ ) /* Reserved: not supported yet */ #define LIBFSNTFS_OPEN_WRITE ( LIBFSNTFS_ACCESS_FLAG_WRITE ) /* Reserved: not supported yet */ #define LIBFSNTFS_OPEN_READ_WRITE ( LIBFSNTFS_ACCESS_FLAG_READ | LIBFSNTFS_ACCESS_FLAG_WRITE ) /* The path segment separator */ #define LIBFSNTFS_SEPARATOR '\\' /* The file attribute flags */ enum LIBFSNTFS_FILE_ATTRIBUTE_FLAGS { LIBFSNTFS_FILE_ATTRIBUTE_FLAG_READ_ONLY = 0x00000001UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_HIDDEN = 0x00000002UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_SYSTEM = 0x00000004UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_DIRECTORY = 0x00000010UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_ARCHIVE = 0x00000020UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_DEVICE = 0x00000040UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_NORMAL = 0x00000080UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_TEMPORARY = 0x00000100UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_SPARSE_FILE = 0x00000200UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_REPARSE_POINT = 0x00000400UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_COMPRESSED = 0x00000800UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_OFFLINE = 0x00001000UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_NOT_CONTENT_INDEXED = 0x00002000UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_ENCRYPTED = 0x00004000UL, LIBFSNTFS_FILE_ATTRIBUTE_FLAG_VIRTUAL = 0x00010000UL }; /* The attribute types */ enum LIBFSNTFS_ATTRIBUTE_TYPES { LIBFSNTFS_ATTRIBUTE_TYPE_UNUSED = 0x00000000UL, LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION = 0x00000010UL, LIBFSNTFS_ATTRIBUTE_TYPE_ATTRIBUTE_LIST = 0x00000020UL, LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME = 0x00000030UL, LIBFSNTFS_ATTRIBUTE_TYPE_OBJECT_IDENTIFIER = 0x00000040UL, LIBFSNTFS_ATTRIBUTE_TYPE_SECURITY_DESCRIPTOR = 0x00000050UL, LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME = 0x00000060UL, LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_INFORMATION = 0x00000070UL, LIBFSNTFS_ATTRIBUTE_TYPE_DATA = 0x00000080UL, LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ROOT = 0x00000090UL, LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ALLOCATION = 0x000000a0UL, LIBFSNTFS_ATTRIBUTE_TYPE_BITMAP = 0x000000b0UL, LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT = 0x000000c0UL, LIBFSNTFS_ATTRIBUTE_TYPE_EXTENDED_INFORMATION = 0x000000d0UL, LIBFSNTFS_ATTRIBUTE_TYPE_EXTENDED = 0x000000e0UL, LIBFSNTFS_ATTRIBUTE_TYPE_PROPERTY_SET = 0x000000f0UL, LIBFSNTFS_ATTRIBUTE_TYPE_LOGGED_UTILITY_STREAM = 0x00000100UL, LIBFSNTFS_ATTRIBUTE_TYPE_END_OF_ATTRIBUTES = 0xffffffffUL }; /* The extent flag definitions */ enum LIBFSNTFS_EXTENT_FLAGS { /* The extent is sparse */ LIBFSNTFS_EXTENT_FLAG_IS_SPARSE = 0x00000001UL, /* The extent is compressed */ LIBFSNTFS_EXTENT_FLAG_IS_COMPRESSED = 0x00000002UL }; #endif /* !defined( HAVE_LOCAL_LIBFSNTFS ) */ /* The attribute flags */ enum LIBFSNTFS_ATTRIBUTE_FLAGS { LIBFSNTFS_ATTRIBUTE_FLAG_SPARSE = 0x8000 }; #define LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK 0x00ff /* The MFT entry flags */ enum LIBFSNTFS_MFT_ENTRY_FLAGS { LIBFSNTFS_MFT_ENTRY_FLAG_IN_USE = 0x0001, LIBFSNTFS_MFT_ENTRY_FLAG_INDEX_PRESENT = 0x0002, }; /* The predefined MFT entry index values */ enum LIBFSNTFS_MFT_ENTRY_INDEXES { LIBFSNTFS_MFT_ENTRY_INDEX_MFT = 0, LIBFSNTFS_MFT_ENTRY_INDEX_MFT_MIRROR = 1, LIBFSNTFS_MFT_ENTRY_INDEX_VOLUME = 3, LIBFSNTFS_MFT_ENTRY_INDEX_ROOT_DIRECTORY = 5, LIBFSNTFS_MFT_ENTRY_INDEX_BITMAP = 6, LIBFSNTFS_MFT_ENTRY_INDEX_SECURE = 9, LIBFSNTFS_MFT_ENTRY_INDEX_UPPERCASE = 10, }; /* The index node flags */ enum LIBFSNTFS_INDEX_NODE_FLAGS { LIBFSNTFS_INDEX_NODE_FLAG_HAS_ALLOCATION_ATTRIBUTE = 0x00000001UL, }; /* The index value flags */ enum LIBFSNTFS_INDEX_VALUE_FLAGS { LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE = 0x00000001UL, LIBFSNTFS_INDEX_VALUE_FLAG_IS_LAST = 0x00000002UL }; /* The file name attribute (name string) name space values */ enum LIBFSNTFS_FILE_NAME_SPACES { LIBFSNTFS_FILE_NAME_SPACE_POSIX = 0x00, LIBFSNTFS_FILE_NAME_SPACE_WINDOWS = 0x01, LIBFSNTFS_FILE_NAME_SPACE_DOS = 0x02, LIBFSNTFS_FILE_NAME_SPACE_DOS_WINDOWS = 0x03 }; /* The file entry flags */ enum LIBFSNTFS_FILE_ENTRY_FLAGS { /* The file entry is based on MFT metadata only */ LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY = 0x01 }; /* The compression methods */ enum LIBFSNTFS_COMPRESSION_METHODS { LIBFSNTFS_COMPRESSION_METHOD_NONE = 0, LIBFSNTFS_COMPRESSION_METHOD_LZNT1 = 1, LIBFSNTFS_COMPRESSION_METHOD_LZXPRESS_HUFFMAN = 2, LIBFSNTFS_COMPRESSION_METHOD_LZX = 3 }; /* Flag to indicate the MFT entry is based on MFT metadata only */ #define LIBFSNTFS_MFT_ENTRY_FLAG_MFT_ONLY LIBFDATA_RANGE_FLAG_USER_DEFINED_1 /* Flag to indicate the index value in the list is stored in the $INDEX_ROOT */ #define LIBFSNTFS_INDEX_VALUE_LIST_FLAG_STORED_IN_ROOT LIBFDATA_RANGE_FLAG_USER_DEFINED_1 #define LIBFSNTFS_DIRECTORY_ENTRIES_TREE_MAXIMUM_NUMBER_OF_SUB_NODES 257 #define LIBFSNTFS_INDEX_TREE_MAXIMUM_NUMBER_OF_SUB_NODES 257 #define LIBFSNTFS_MAXIMUM_CACHE_ENTRIES_COMPRESSED_BLOCKS 2 #define LIBFSNTFS_MAXIMUM_CACHE_ENTRIES_INDEX_NODES 128 #define LIBFSNTFS_MAXIMUM_CACHE_ENTRIES_MFT_ENTRIES 32 #define LIBFSNTFS_MAXIMUM_RECURSION_DEPTH 256 #endif /* !defined( _LIBFSNTFS_INTERNAL_DEFINITIONS_H ) */ ================================================ FILE: libfsntfs/libfsntfs_directory_entries_tree.c ================================================ /* * Directory entries tree functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_definitions.h" #include "libfsntfs_directory_entries_tree.h" #include "libfsntfs_directory_entry.h" #include "libfsntfs_file_name_values.h" #include "libfsntfs_index.h" #include "libfsntfs_index_value.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libfcache.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_mft_entry.h" #include "libfsntfs_name.h" #include "libfsntfs_standard_information_values.h" #include "libfsntfs_unused.h" /* Creates a directory entries tree * Make sure the value directory_entries_tree is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entries_tree_initialize( libfsntfs_directory_entries_tree_t **directory_entries_tree, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entries_tree_initialize"; if( directory_entries_tree == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree.", function ); return( -1 ); } if( *directory_entries_tree != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid directory entries tree value already set.", function ); return( -1 ); } *directory_entries_tree = memory_allocate_structure( libfsntfs_directory_entries_tree_t ); if( *directory_entries_tree == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create directory entries tree.", function ); goto on_error; } if( memory_set( *directory_entries_tree, 0, sizeof( libfsntfs_directory_entries_tree_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear directory entries tree.", function ); goto on_error; } return( 1 ); on_error: if( *directory_entries_tree != NULL ) { memory_free( *directory_entries_tree ); *directory_entries_tree = NULL; } return( -1 ); } /* Frees a directory entries tree * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entries_tree_free( libfsntfs_directory_entries_tree_t **directory_entries_tree, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entries_tree_free"; int result = 1; if( directory_entries_tree == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree.", function ); return( -1 ); } if( *directory_entries_tree != NULL ) { if( ( *directory_entries_tree )->i30_index != NULL ) { if( libfsntfs_index_free( &( ( *directory_entries_tree )->i30_index ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free $I30 index.", function ); result = -1; } } if( ( *directory_entries_tree )->short_names_tree != NULL ) { if( libcdata_btree_free( &( ( *directory_entries_tree )->short_names_tree ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_directory_entry_free, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free short names tree.", function ); result = -1; } } if( ( *directory_entries_tree )->entries_list != NULL ) { if( libfdata_list_free( &( ( *directory_entries_tree )->entries_list ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free entries list.", function ); result = -1; } } if( ( *directory_entries_tree )->entries_cache != NULL ) { if( libfcache_cache_free( &( ( *directory_entries_tree )->entries_cache ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free entries cache.", function ); result = -1; } } memory_free( *directory_entries_tree ); *directory_entries_tree = NULL; } return( result ); } /* Inserts an index value into the directory entries tree * Returns 1 if a directory entry was inserted, 0 if not or -1 on error */ int libfsntfs_directory_entries_tree_insert_index_value( libfsntfs_directory_entries_tree_t *directory_entries_tree, int index_value_entry, libfsntfs_index_value_t *index_value, uint32_t index_value_flags, libcerror_error_t **error ) { libcdata_tree_node_t *upper_node = NULL; libfsntfs_directory_entry_t *directory_entry = NULL; libfsntfs_directory_entry_t *existing_directory_entry = NULL; libfsntfs_file_name_values_t *file_name_values = NULL; static char *function = "libfsntfs_directory_entries_tree_insert_index_value"; uint8_t name_space = 0; int element_file_index = 0; int element_index = 0; int result = 0; int value_index = 0; if( directory_entries_tree == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree.", function ); return( -1 ); } if( index_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index value.", function ); return( -1 ); } if( libfsntfs_file_name_values_initialize( &file_name_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file name values.", function ); goto on_error; } if( libfsntfs_file_name_values_read_data( file_name_values, index_value->key_data, (size_t) index_value->key_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read file name values.", function ); goto on_error; } if( file_name_values->name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid file name values - missing name.", function ); goto on_error; } /* Ignore the file name with the . as its name */ if( ( file_name_values->name_size == 2 ) && ( file_name_values->name[ 0 ] == 0x2e ) && ( file_name_values->name[ 1 ] == 0x00 ) ) { if( libfsntfs_file_name_values_free( &file_name_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file name values.", function ); goto on_error; } return( 0 ); } name_space = file_name_values->name_space; if( name_space == LIBFSNTFS_FILE_NAME_SPACE_DOS ) { if( libfsntfs_directory_entry_initialize( &directory_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create directory entry.", function ); goto on_error; } directory_entry->file_reference = index_value->file_reference; directory_entry->short_file_name_values = file_name_values; file_name_values = NULL; result = libcdata_btree_insert_value( directory_entries_tree->short_names_tree, &value_index, (intptr_t *) directory_entry, (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_directory_entry_compare_by_file_reference, &upper_node, (intptr_t **) &existing_directory_entry, error ) ; if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to insert directory entry into tree.", function ); goto on_error; } else if( result == 0 ) { if( existing_directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing existing directory entry.", function ); goto on_error; } if( name_space == LIBFSNTFS_FILE_NAME_SPACE_DOS ) { if( existing_directory_entry->short_file_name_values != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: short file name of existing directory entry already set.", function ); goto on_error; } existing_directory_entry->short_file_name_values = directory_entry->short_file_name_values; directory_entry->short_file_name_values = NULL; } else { if( existing_directory_entry->file_name_values != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: file name of existing directory entry already set.", function ); goto on_error; } existing_directory_entry->file_name_values = directory_entry->file_name_values; directory_entry->file_name_values = NULL; } if( libfsntfs_directory_entry_free( &directory_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free directory entry.", function ); goto on_error; } } } if( name_space != LIBFSNTFS_FILE_NAME_SPACE_DOS ) { /* The element file index value contains the index value entry + 1 */ element_file_index = index_value_entry + 1; if( libfdata_list_append_element( directory_entries_tree->entries_list, &element_index, element_file_index, index_value->offset, (size64_t) index_value->size, index_value_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append index value to entries list.", function ); goto on_error; } } if( file_name_values != NULL ) { if( libfsntfs_file_name_values_free( &file_name_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file name values.", function ); goto on_error; } } return( result ); on_error: if( directory_entry != NULL ) { libfsntfs_directory_entry_free( &directory_entry, NULL ); } if( file_name_values != NULL ) { libfsntfs_file_name_values_free( &file_name_values, NULL ); } return( -1 ); } /* Reads the directory entries tree from an index node * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entries_tree_read_from_index_node( libfsntfs_directory_entries_tree_t *directory_entries_tree, libbfio_handle_t *file_io_handle, libfsntfs_index_node_t *index_node, int recursion_depth, libcerror_error_t **error ) { libfcache_cache_t *sub_node_cache = NULL; libfsntfs_index_node_t *sub_node = NULL; libfsntfs_index_value_t *index_value = NULL; static char *function = "libfsntfs_directory_entries_tree_read_from_index_node"; off64_t index_entry_offset = 0; uint32_t index_value_flags = 0; int index_value_entry = 0; int is_allocated = 0; int number_of_index_values = 0; int result = 0; if( directory_entries_tree == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree.", function ); return( -1 ); } if( directory_entries_tree->i30_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree - missing $I30 index.", function ); return( -1 ); } if( directory_entries_tree->i30_index->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree - invalid $I30 index - missing IO handle.", function ); return( -1 ); } if( ( recursion_depth < 0 ) || ( recursion_depth > LIBFSNTFS_MAXIMUM_RECURSION_DEPTH ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid recursion depth value out of bounds.", function ); return( -1 ); } if( libfsntfs_index_node_get_number_of_values( index_node, &number_of_index_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of values from index node.", function ); goto on_error; } /* Use a local cache to prevent cache invalidation of index node * when reading sub nodes. */ if( libfcache_cache_initialize( &sub_node_cache, 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create sub node cache.", function ); goto on_error; } for( index_value_entry = 0; index_value_entry < number_of_index_values; index_value_entry++ ) { if( libfsntfs_index_node_get_value_by_index( index_node, index_value_entry, &index_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve value: %d from index node.", function, index_value_entry ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: index value: %03d file reference: %" PRIu64 "-%" PRIu64 "\n", function, index_value_entry, index_value->file_reference & 0xffffffffffffUL, index_value->file_reference >> 48 ); libcnotify_printf( "\n" ); } #endif if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 ) { if( index_value->sub_node_vcn > (uint64_t) INT_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: node index value: %d sub node VCN value out of bounds.", function, index_value_entry ); goto on_error; } is_allocated = libfsntfs_index_sub_node_is_allocated( directory_entries_tree->i30_index, (int) index_value->sub_node_vcn, error ); if( is_allocated == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if sub node with VCN: %d is allocated.", function, (int) index_value->sub_node_vcn ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: index value: %03d sub node VCN: %" PRIu64 " (%s).\n", function, index_value_entry, index_value->sub_node_vcn, is_allocated != 0 ? "allocated" : "unallocated" ); libcnotify_printf( "\n" ); } #endif if( is_allocated == 0 ) { continue; } index_entry_offset = (off64_t) ( index_value->sub_node_vcn * directory_entries_tree->i30_index->io_handle->cluster_block_size ); if( libfsntfs_index_get_sub_node( directory_entries_tree->i30_index, file_io_handle, sub_node_cache, index_entry_offset, (int) index_value->sub_node_vcn, &sub_node, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve sub node with VCN: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").", function, (int) index_value->sub_node_vcn, index_entry_offset, index_entry_offset ); goto on_error; } if( libfsntfs_directory_entries_tree_read_from_index_node( directory_entries_tree, file_io_handle, sub_node, recursion_depth + 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read directory entries tree from index entry with VCN: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").", function, (int) index_value->sub_node_vcn, index_entry_offset, index_entry_offset ); goto on_error; } } if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_LAST ) != 0 ) { break; } index_value_flags = 0; if( index_node == directory_entries_tree->i30_index->root_node ) { index_value_flags = LIBFSNTFS_INDEX_VALUE_LIST_FLAG_STORED_IN_ROOT; } /* Add the index values containing data in a depth first manner since * this will preserve the sorted by file name order of the directory entries */ result = libfsntfs_directory_entries_tree_insert_index_value( directory_entries_tree, index_value_entry, index_value, index_value_flags, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to insert index value into directory entries tree.", function ); goto on_error; } } if( libfcache_cache_free( &sub_node_cache, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free sub node cache.", function ); goto on_error; } return( 1 ); on_error: if( sub_node_cache != NULL ) { libfcache_cache_free( &sub_node_cache, NULL ); } return( -1 ); } /* Reads the directory entries tree from the $I30 index * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entries_tree_read_from_i30_index( libfsntfs_directory_entries_tree_t *directory_entries_tree, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfsntfs_mft_entry_t *mft_entry, uint8_t flags, libcerror_error_t **error ) { libfsntfs_mft_attribute_t *mft_attribute = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; static char *function = "libfsntfs_directory_entries_tree_read_from_i30_index"; uint32_t attribute_type = 0; uint32_t collation_type = 0; int result = 0; if( directory_entries_tree == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree.", function ); return( -1 ); } if( directory_entries_tree->i30_index != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid directory entries tree - $I30 index value already set.", function ); return( -1 ); } if( directory_entries_tree->short_names_tree != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid directory entries tree - short names tree value already set.", function ); return( -1 ); } if( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) != 0 ) { return( 1 ); } if( libfsntfs_index_initialize( &( directory_entries_tree->i30_index ), io_handle, (uint8_t *) "$I30", 5, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create $I30 index.", function ); goto on_error; } result = libfsntfs_index_read( directory_entries_tree->i30_index, file_io_handle, mft_entry, flags, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read $I30 index.", function ); goto on_error; } else if( result != 0 ) { if( libfsntfs_index_get_attribute_type( directory_entries_tree->i30_index, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type from index.", function ); goto on_error; } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported index attribute type.", function ); goto on_error; } if( libfsntfs_index_get_collation_type( directory_entries_tree->i30_index, &collation_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve collation type from index.", function ); goto on_error; } if( collation_type != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported index collation type.", function ); goto on_error; } if( libfdata_list_initialize( &( directory_entries_tree->entries_list ), (intptr_t *) directory_entries_tree, NULL, NULL, (int (*)(intptr_t *, intptr_t *, libfdata_list_element_t *, libfdata_cache_t *, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsntfs_directory_entries_tree_read_element_data, NULL, LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create entries list.", function ); goto on_error; } if( libfcache_cache_initialize( &( directory_entries_tree->entries_cache ), 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create entries cache.", function ); goto on_error; } if( libcdata_btree_initialize( &( directory_entries_tree->short_names_tree ), LIBFSNTFS_INDEX_TREE_MAXIMUM_NUMBER_OF_SUB_NODES, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create short names B-tree.", function ); goto on_error; } if( libfsntfs_directory_entries_tree_read_from_index_node( directory_entries_tree, file_io_handle, directory_entries_tree->i30_index->root_node, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read directory entries tree from root node.", function ); goto on_error; } directory_entries_tree->use_case_folding = 0; result = libfsntfs_mft_entry_get_standard_information_attribute( mft_entry, &mft_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve $STANDARD_INFORMATION attribute from MFT entry.", function ); goto on_error; } else if( result != 0 ) { if( libfsntfs_standard_information_values_initialize( &standard_information_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create standard information values.", function ); goto on_error; } if( libfsntfs_standard_information_values_read_from_mft_attribute( standard_information_values, mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read standard information values from MFT attribute.", function ); goto on_error; } if( standard_information_values->is_case_sensitive == 0 ) { directory_entries_tree->use_case_folding = 1; } if( libfsntfs_standard_information_values_free( &standard_information_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free standard information values.", function ); goto on_error; } } } return( 1 ); on_error: if( standard_information_values != NULL ) { libfsntfs_standard_information_values_free( &standard_information_values, NULL ); } if( directory_entries_tree->short_names_tree != NULL ) { libcdata_btree_free( &( directory_entries_tree->short_names_tree ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_directory_entry_free, NULL ); } if( directory_entries_tree->entries_cache != NULL ) { libfcache_cache_free( &( directory_entries_tree->entries_cache ), NULL ); } if( directory_entries_tree->entries_list != NULL ) { libfdata_list_free( &( directory_entries_tree->entries_list ), NULL ); } if( directory_entries_tree->i30_index != NULL ) { libfsntfs_index_free( &( directory_entries_tree->i30_index ), NULL ); } return( -1 ); } /* Retrieves the number of entries * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entries_tree_get_number_of_entries( libfsntfs_directory_entries_tree_t *directory_entries_tree, int *number_of_entries, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entries_tree_get_number_of_entries"; if( directory_entries_tree == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree.", function ); return( -1 ); } if( directory_entries_tree->entries_list == NULL ) { if( number_of_entries == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid number of entries.", function ); return( -1 ); } *number_of_entries = 0; } else { if( libfdata_list_get_number_of_elements( directory_entries_tree->entries_list, number_of_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of elements from entries list.", function ); return( -1 ); } } return( 1 ); } /* Retrieves a specific entry * This function creates a new directory entry * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entries_tree_get_entry_by_index( libfsntfs_directory_entries_tree_t *directory_entries_tree, libbfio_handle_t *file_io_handle, int entry_index, libfsntfs_directory_entry_t **directory_entry, libcerror_error_t **error ) { libfsntfs_directory_entry_t *safe_directory_entry = NULL; static char *function = "libfsntfs_directory_entries_tree_get_entry_by_index"; if( directory_entries_tree == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree.", function ); return( -1 ); } if( libfdata_list_get_element_value_by_index( directory_entries_tree->entries_list, (intptr_t *) file_io_handle, (libfdata_cache_t *) directory_entries_tree->entries_cache, entry_index, (intptr_t **) &safe_directory_entry, LIBFDATA_READ_FLAG_IGNORE_CACHE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve element: %d from entries list.", function, entry_index ); return( -1 ); } if( libfsntfs_directory_entry_clone( directory_entry, safe_directory_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create directory entry.", function ); return( -1 ); } return( 1 ); } /* Retrieves the directory entry from an index node for an UTF-8 encoded name * This function creates a new directory entry * Returns 1 if successful, 0 if no such directory entry or -1 on error */ int libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name( libfsntfs_directory_entries_tree_t *directory_entries_tree, libbfio_handle_t *file_io_handle, libfsntfs_index_node_t *index_node, const uint8_t *utf8_string, size_t utf8_string_length, libfsntfs_directory_entry_t **directory_entry, int recursion_depth, libcerror_error_t **error ) { libcdata_tree_node_t *upper_node = NULL; libfsntfs_directory_entry_t *existing_directory_entry = NULL; libfsntfs_directory_entry_t *safe_directory_entry = NULL; libfsntfs_file_name_values_t *file_name_values = NULL; libfsntfs_index_node_t *sub_node = NULL; libfsntfs_index_value_t *index_value = NULL; static char *function = "libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name"; off64_t index_entry_offset = 0; int compare_result = 0; int index_value_entry = 0; int is_allocated = 0; int number_of_index_values = 0; int result = 0; if( directory_entries_tree == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree.", function ); return( -1 ); } if( directory_entries_tree->i30_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree - missing $I30 index.", function ); return( -1 ); } if( directory_entries_tree->i30_index->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree - invalid $I30 index - missing IO handle.", function ); return( -1 ); } if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( ( recursion_depth < 0 ) || ( recursion_depth > LIBFSNTFS_MAXIMUM_RECURSION_DEPTH ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid recursion depth value out of bounds.", function ); return( -1 ); } if( libfsntfs_index_node_get_number_of_values( index_node, &number_of_index_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of values from index node.", function ); goto on_error; } for( index_value_entry = 0; index_value_entry < number_of_index_values; index_value_entry++ ) { if( libfsntfs_index_node_get_value_by_index( index_node, index_value_entry, &index_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve value: %d from index node.", function, index_value_entry ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: index value: %03d file reference: %" PRIu64 "-%" PRIu64 "\n", function, index_value_entry, index_value->file_reference & 0xffffffffffffUL, index_value->file_reference >> 48 ); libcnotify_printf( "\n" ); } #endif if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 ) { if( index_value->sub_node_vcn > (uint64_t) INT_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: node index value: %d sub node VCN value out of bounds.", function, index_value_entry ); goto on_error; } is_allocated = libfsntfs_index_sub_node_is_allocated( directory_entries_tree->i30_index, (int) index_value->sub_node_vcn, error ); if( is_allocated == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if sub node with VCN: %d is allocated.", function, (int) index_value->sub_node_vcn ); goto on_error; } else if( is_allocated == 0 ) { continue; } } if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_LAST ) != 0 ) { break; } if( libfsntfs_file_name_values_initialize( &file_name_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file name values.", function ); goto on_error; } if( libfsntfs_file_name_values_read_data( file_name_values, index_value->key_data, (size_t) index_value->key_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read file name values.", function ); goto on_error; } compare_result = libfsntfs_name_compare_with_utf8_string( file_name_values->name, file_name_values->name_size, utf8_string, utf8_string_length, directory_entries_tree->use_case_folding, error ); if( compare_result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GENERIC, "%s: unable to compare file name values with UTF-8 string.", function ); goto on_error; } if( compare_result != LIBUNA_COMPARE_EQUAL ) { if( libfsntfs_file_name_values_free( &file_name_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file name values.", function ); goto on_error; } } if( compare_result == LIBUNA_COMPARE_LESS ) { if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 ) { break; } } else if( compare_result == LIBUNA_COMPARE_EQUAL ) { break; } } if( compare_result == LIBUNA_COMPARE_EQUAL ) { if( libfsntfs_directory_entry_initialize( &safe_directory_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create directory entry.", function ); goto on_error; } safe_directory_entry->file_reference = index_value->file_reference; safe_directory_entry->file_name_values = file_name_values; file_name_values = NULL; if( safe_directory_entry->file_name_values->name_space == LIBFSNTFS_FILE_NAME_SPACE_WINDOWS ) { result = libcdata_btree_get_value_by_value( directory_entries_tree->short_names_tree, (intptr_t *) directory_entry, (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_directory_entry_compare_by_file_reference, &upper_node, (intptr_t **) &existing_directory_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve directory entry from tree.", function ); goto on_error; } else if( result != 0 ) { /* TODO add debug compare of long and short names */ if( existing_directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing existing directory entry.", function ); goto on_error; } if( libfsntfs_file_name_values_clone( &( safe_directory_entry->short_file_name_values ), existing_directory_entry->short_file_name_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to clone short file name values.", function ); goto on_error; } } } *directory_entry = safe_directory_entry; result = 1; } else if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 ) { index_entry_offset = (off64_t) ( index_value->sub_node_vcn * directory_entries_tree->i30_index->io_handle->cluster_block_size ); if( libfsntfs_index_get_sub_node( directory_entries_tree->i30_index, file_io_handle, directory_entries_tree->i30_index->index_node_cache, index_entry_offset, (int) index_value->sub_node_vcn, &sub_node, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve sub node with VCN: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").", function, (int) index_value->sub_node_vcn, index_entry_offset, index_entry_offset ); goto on_error; } result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name( directory_entries_tree, file_io_handle, sub_node, utf8_string, utf8_string_length, directory_entry, recursion_depth + 1, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to retrieve directory entry by UTF-8 string from index entry with VCN: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").", function, (int) index_value->sub_node_vcn, index_entry_offset, index_entry_offset ); goto on_error; } } return( result ); on_error: if( safe_directory_entry != NULL ) { libfsntfs_directory_entry_free( &safe_directory_entry, NULL ); } if( file_name_values != NULL ) { libfsntfs_file_name_values_free( &file_name_values, NULL ); } return( -1 ); } /* Retrieves the directory entry for an UTF-8 encoded name * This function creates a new directory entry * Returns 1 if successful, 0 if no such directory entry or -1 on error */ int libfsntfs_directory_entries_tree_get_entry_by_utf8_name( libfsntfs_directory_entries_tree_t *directory_entries_tree, libbfio_handle_t *file_io_handle, const uint8_t *utf8_string, size_t utf8_string_length, libfsntfs_directory_entry_t **directory_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entries_tree_get_entry_by_utf8_name"; int result = 0; if( directory_entries_tree == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree.", function ); return( -1 ); } if( directory_entries_tree->i30_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree - missing $I30 index.", function ); return( -1 ); } result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name( directory_entries_tree, file_io_handle, directory_entries_tree->i30_index->root_node, utf8_string, utf8_string_length, directory_entry, 0, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve directory entry by UTF-8 string.", function ); return( -1 ); } return( result ); } /* Retrieves the directory entry from an index node for an UTF-16 encoded name * This function creates a new directory entry * Returns 1 if successful, 0 if no such directory entry or -1 on error */ int libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name( libfsntfs_directory_entries_tree_t *directory_entries_tree, libbfio_handle_t *file_io_handle, libfsntfs_index_node_t *index_node, const uint16_t *utf16_string, size_t utf16_string_length, libfsntfs_directory_entry_t **directory_entry, int recursion_depth, libcerror_error_t **error ) { libcdata_tree_node_t *upper_node = NULL; libfsntfs_directory_entry_t *existing_directory_entry = NULL; libfsntfs_directory_entry_t *safe_directory_entry = NULL; libfsntfs_file_name_values_t *file_name_values = NULL; libfsntfs_index_node_t *sub_node = NULL; libfsntfs_index_value_t *index_value = NULL; static char *function = "libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name"; off64_t index_entry_offset = 0; int compare_result = 0; int index_value_entry = 0; int is_allocated = 0; int number_of_index_values = 0; int result = 0; if( directory_entries_tree == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree.", function ); return( -1 ); } if( directory_entries_tree->i30_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree - missing $I30 index.", function ); return( -1 ); } if( directory_entries_tree->i30_index->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree - invalid $I30 index - missing IO handle.", function ); return( -1 ); } if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( ( recursion_depth < 0 ) || ( recursion_depth > LIBFSNTFS_MAXIMUM_RECURSION_DEPTH ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid recursion depth value out of bounds.", function ); return( -1 ); } if( libfsntfs_index_node_get_number_of_values( index_node, &number_of_index_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of values from index node.", function ); goto on_error; } for( index_value_entry = 0; index_value_entry < number_of_index_values; index_value_entry++ ) { if( libfsntfs_index_node_get_value_by_index( index_node, index_value_entry, &index_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve value: %d from index node.", function, index_value_entry ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: index value: %03d file reference: %" PRIu64 "-%" PRIu64 "\n", function, index_value_entry, index_value->file_reference & 0xffffffffffffUL, index_value->file_reference >> 48 ); libcnotify_printf( "\n" ); } #endif if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 ) { if( index_value->sub_node_vcn > (uint64_t) INT_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: node index value: %d sub node VCN value out of bounds.", function, index_value_entry ); goto on_error; } is_allocated = libfsntfs_index_sub_node_is_allocated( directory_entries_tree->i30_index, (int) index_value->sub_node_vcn, error ); if( is_allocated == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if sub node with VCN: %d is allocated.", function, (int) index_value->sub_node_vcn ); goto on_error; } else if( is_allocated == 0 ) { continue; } } if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_LAST ) != 0 ) { break; } if( libfsntfs_file_name_values_initialize( &file_name_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file name values.", function ); goto on_error; } if( libfsntfs_file_name_values_read_data( file_name_values, index_value->key_data, (size_t) index_value->key_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read file name values.", function ); goto on_error; } compare_result = libfsntfs_name_compare_with_utf16_string( file_name_values->name, file_name_values->name_size, utf16_string, utf16_string_length, directory_entries_tree->use_case_folding, error ); if( compare_result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GENERIC, "%s: unable to compare file name values with UTF-16 string.", function ); goto on_error; } if( compare_result != LIBUNA_COMPARE_EQUAL ) { if( libfsntfs_file_name_values_free( &file_name_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file name values.", function ); goto on_error; } } if( compare_result == LIBUNA_COMPARE_LESS ) { if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 ) { break; } } else if( compare_result == LIBUNA_COMPARE_EQUAL ) { break; } } if( compare_result == LIBUNA_COMPARE_EQUAL ) { if( libfsntfs_directory_entry_initialize( &safe_directory_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create directory entry.", function ); goto on_error; } safe_directory_entry->file_reference = index_value->file_reference; safe_directory_entry->file_name_values = file_name_values; file_name_values = NULL; if( safe_directory_entry->file_name_values->name_space == LIBFSNTFS_FILE_NAME_SPACE_WINDOWS ) { result = libcdata_btree_get_value_by_value( directory_entries_tree->short_names_tree, (intptr_t *) directory_entry, (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_directory_entry_compare_by_file_reference, &upper_node, (intptr_t **) &existing_directory_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve directory entry from tree.", function ); goto on_error; } else if( result != 0 ) { /* TODO add debug compare of long and short names */ if( existing_directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing existing directory entry.", function ); goto on_error; } if( libfsntfs_file_name_values_clone( &( safe_directory_entry->short_file_name_values ), existing_directory_entry->short_file_name_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to clone short file name values.", function ); goto on_error; } } } *directory_entry = safe_directory_entry; result = 1; } else if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 ) { index_entry_offset = (off64_t) ( index_value->sub_node_vcn * directory_entries_tree->i30_index->io_handle->cluster_block_size ); if( libfsntfs_index_get_sub_node( directory_entries_tree->i30_index, file_io_handle, directory_entries_tree->i30_index->index_node_cache, index_entry_offset, (int) index_value->sub_node_vcn, &sub_node, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve sub node with VCN: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").", function, (int) index_value->sub_node_vcn, index_entry_offset, index_entry_offset ); goto on_error; } result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name( directory_entries_tree, file_io_handle, sub_node, utf16_string, utf16_string_length, directory_entry, recursion_depth + 1, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to retrieve directory entry by UTF-16 string from index entry with VCN: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").", function, (int) index_value->sub_node_vcn, index_entry_offset, index_entry_offset ); goto on_error; } } return( result ); on_error: if( safe_directory_entry != NULL ) { libfsntfs_directory_entry_free( &safe_directory_entry, NULL ); } if( file_name_values != NULL ) { libfsntfs_file_name_values_free( &file_name_values, NULL ); } return( -1 ); } /* Retrieves the directory entry for an UTF-16 encoded name * This function creates a new directory entry * Returns 1 if successful, 0 if no such directory entry or -1 on error */ int libfsntfs_directory_entries_tree_get_entry_by_utf16_name( libfsntfs_directory_entries_tree_t *directory_entries_tree, libbfio_handle_t *file_io_handle, const uint16_t *utf16_string, size_t utf16_string_length, libfsntfs_directory_entry_t **directory_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entries_tree_get_entry_by_utf16_name"; int result = 0; if( directory_entries_tree == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree.", function ); return( -1 ); } if( directory_entries_tree->i30_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree - missing $I30 index.", function ); return( -1 ); } result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name( directory_entries_tree, file_io_handle, directory_entries_tree->i30_index->root_node, utf16_string, utf16_string_length, directory_entry, 0, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve directory entry by UTF-16 string.", function ); return( -1 ); } return( result ); } /* Reads a directory entry * Callback function for the entries list * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entries_tree_read_element_data( libfsntfs_directory_entries_tree_t *directory_entries_tree, libbfio_handle_t *file_io_handle, libfdata_list_element_t *element, libfdata_cache_t *cache, int element_file_index, off64_t index_value_offset, size64_t element_size LIBFSNTFS_ATTRIBUTE_UNUSED, uint32_t index_value_flags, uint8_t read_flags LIBFSNTFS_ATTRIBUTE_UNUSED, libcerror_error_t **error ) { libcdata_tree_node_t *upper_node = NULL; libfsntfs_directory_entry_t *directory_entry = NULL; libfsntfs_directory_entry_t *existing_directory_entry = NULL; libfsntfs_index_node_t *sub_node = NULL; libfsntfs_index_value_t *index_value = NULL; static char *function = "libfsntfs_directory_entries_tree_read_element_data"; off64_t index_entry_offset = 0; off64_t sub_node_vcn = 0; int index_value_entry = 0; int is_allocated = 0; int result = 0; LIBFSNTFS_UNREFERENCED_PARAMETER( element_size ) LIBFSNTFS_UNREFERENCED_PARAMETER( read_flags ) if( directory_entries_tree == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree.", function ); return( -1 ); } if( directory_entries_tree->i30_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree - missing $I30 index.", function ); return( -1 ); } if( directory_entries_tree->i30_index->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entries tree - invalid $I30 index - missing IO handle.", function ); return( -1 ); } if( libfdata_list_element_get_element_index( element, &index_value_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve element index.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading index value: %03d at offset: %" PRIi64 " (0x%08" PRIx64 ").\n", function, index_value_entry, index_value_offset, index_value_offset ); } #endif /* The element file index value contains the index value entry + 1 */ element_file_index -= 1; if( ( index_value_flags & LIBFSNTFS_INDEX_VALUE_LIST_FLAG_STORED_IN_ROOT ) != 0 ) { if( libfsntfs_index_node_get_value_by_index( directory_entries_tree->i30_index->root_node, element_file_index, &index_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve index value: %d from root node.", function, element_file_index ); goto on_error; } } else { sub_node_vcn = index_value_offset / directory_entries_tree->i30_index->io_handle->cluster_block_size; index_entry_offset = (off64_t) ( sub_node_vcn * directory_entries_tree->i30_index->io_handle->cluster_block_size ); is_allocated = libfsntfs_index_sub_node_is_allocated( directory_entries_tree->i30_index, (int) sub_node_vcn, error ); if( is_allocated == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if sub node with VCN: %d is allocated.", function, (int) sub_node_vcn ); goto on_error; } else if( is_allocated == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported unallocated sub node with VCN: %d.", function, (int) sub_node_vcn ); goto on_error; } if( libfsntfs_index_get_sub_node( directory_entries_tree->i30_index, file_io_handle, directory_entries_tree->i30_index->index_node_cache, index_entry_offset, (int) sub_node_vcn, &sub_node, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve sub node with VCN: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").", function, (int) sub_node_vcn, index_entry_offset, index_entry_offset ); goto on_error; } if( libfsntfs_index_node_get_value_by_index( sub_node, element_file_index, &index_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve index value: %d from sub node.", function, element_file_index ); goto on_error; } } if( libfsntfs_directory_entry_initialize( &directory_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create directory entry.", function ); goto on_error; } if( libfsntfs_file_name_values_initialize( &( directory_entry->file_name_values ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file name values.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: index value: %03d file reference: %" PRIu64 "-%" PRIu64 "\n", function, index_value_entry, index_value->file_reference & 0xffffffffffffUL, index_value->file_reference >> 48 ); libcnotify_printf( "\n" ); } #endif directory_entry->file_reference = index_value->file_reference; if( libfsntfs_file_name_values_read_data( directory_entry->file_name_values, index_value->key_data, (size_t) index_value->key_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read file name values.", function ); goto on_error; } if( directory_entry->file_name_values->name_space == LIBFSNTFS_FILE_NAME_SPACE_WINDOWS ) { result = libcdata_btree_get_value_by_value( directory_entries_tree->short_names_tree, (intptr_t *) directory_entry, (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_directory_entry_compare_by_file_reference, &upper_node, (intptr_t **) &existing_directory_entry, error ) ; if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve directory entry from tree.", function ); goto on_error; } else if( result != 0 ) { /* TODO add debug compare of long and short names */ if( existing_directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing existing directory entry.", function ); goto on_error; } if( libfsntfs_file_name_values_clone( &( directory_entry->short_file_name_values ), existing_directory_entry->short_file_name_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to clone short file name values.", function ); goto on_error; } } } if( libfdata_list_element_set_element_value( element, (intptr_t *) file_io_handle, cache, (intptr_t *) directory_entry, (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_directory_entry_free, LIBFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set index value as element value.", function ); goto on_error; } return( 1 ); on_error: if( directory_entry != NULL ) { libfsntfs_directory_entry_free( &directory_entry, NULL ); } return( -1 ); } ================================================ FILE: libfsntfs/libfsntfs_directory_entries_tree.h ================================================ /* * Directory entries tree functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_DIRECTORY_ENTRIES_TREE_H ) #define _LIBFSNTFS_DIRECTORY_ENTRIES_TREE_H #include #include #include "libfsntfs_directory_entry.h" #include "libfsntfs_index.h" #include "libfsntfs_index_node.h" #include "libfsntfs_index_value.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfcache.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_entry.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_directory_entries_tree libfsntfs_directory_entries_tree_t; struct libfsntfs_directory_entries_tree { /* The $I30 index */ libfsntfs_index_t *i30_index; /* The short names B-tree */ libcdata_btree_t *short_names_tree; /* The entries list */ libfdata_list_t *entries_list; /* The entries cache */ libfcache_cache_t *entries_cache; /* Value to indicate case folding should be used */ uint8_t use_case_folding; }; int libfsntfs_directory_entries_tree_initialize( libfsntfs_directory_entries_tree_t **directory_entries_tree, libcerror_error_t **error ); int libfsntfs_directory_entries_tree_free( libfsntfs_directory_entries_tree_t **directory_entries_tree, libcerror_error_t **error ); int libfsntfs_directory_entries_tree_insert_index_value( libfsntfs_directory_entries_tree_t *directory_entries_tree, int index_value_entry, libfsntfs_index_value_t *index_value, uint32_t index_value_flags, libcerror_error_t **error ); int libfsntfs_directory_entries_tree_read_from_index_node( libfsntfs_directory_entries_tree_t *directory_entries_tree, libbfio_handle_t *file_io_handle, libfsntfs_index_node_t *index_node, int recursion_depth, libcerror_error_t **error ); int libfsntfs_directory_entries_tree_read_from_i30_index( libfsntfs_directory_entries_tree_t *directory_entries_tree, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfsntfs_mft_entry_t *mft_entry, uint8_t flags, libcerror_error_t **error ); int libfsntfs_directory_entries_tree_get_number_of_entries( libfsntfs_directory_entries_tree_t *directory_entries_tree, int *number_of_entries, libcerror_error_t **error ); int libfsntfs_directory_entries_tree_get_entry_by_index( libfsntfs_directory_entries_tree_t *directory_entries_tree, libbfio_handle_t *file_io_handle, int entry_index, libfsntfs_directory_entry_t **directory_entry, libcerror_error_t **error ); int libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name( libfsntfs_directory_entries_tree_t *directory_entries_tree, libbfio_handle_t *file_io_handle, libfsntfs_index_node_t *index_node, const uint8_t *utf8_string, size_t utf8_string_length, libfsntfs_directory_entry_t **directory_entry, int recursion_depth, libcerror_error_t **error ); int libfsntfs_directory_entries_tree_get_entry_by_utf8_name( libfsntfs_directory_entries_tree_t *directory_entries_tree, libbfio_handle_t *file_io_handle, const uint8_t *utf8_string, size_t utf8_string_length, libfsntfs_directory_entry_t **directory_entry, libcerror_error_t **error ); int libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name( libfsntfs_directory_entries_tree_t *directory_entries_tree, libbfio_handle_t *file_io_handle, libfsntfs_index_node_t *index_node, const uint16_t *utf16_string, size_t utf16_string_length, libfsntfs_directory_entry_t **directory_entry, int recursion_depth, libcerror_error_t **error ); int libfsntfs_directory_entries_tree_get_entry_by_utf16_name( libfsntfs_directory_entries_tree_t *directory_entries_tree, libbfio_handle_t *file_io_handle, const uint16_t *utf16_string, size_t utf16_string_length, libfsntfs_directory_entry_t **directory_entry, libcerror_error_t **error ); int libfsntfs_directory_entries_tree_read_element_data( libfsntfs_directory_entries_tree_t *directory_entries_tree, libbfio_handle_t *file_io_handle, libfdata_list_element_t *element, libfdata_cache_t *cache, int element_file_index, off64_t index_value_offset, size64_t element_size, uint32_t index_value_flags, uint8_t read_flags, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_DIRECTORY_ENTRIES_TREE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_directory_entry.c ================================================ /* * Directory entry functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_directory_entry.h" #include "libfsntfs_file_name_values.h" #include "libfsntfs_index_value.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" /* Creates a directory entry * Make sure the value directory_entry is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entry_initialize( libfsntfs_directory_entry_t **directory_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entry_initialize"; if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( *directory_entry != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid directory entry value already set.", function ); return( -1 ); } *directory_entry = memory_allocate_structure( libfsntfs_directory_entry_t ); if( *directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create directory entry.", function ); goto on_error; } if( memory_set( *directory_entry, 0, sizeof( libfsntfs_directory_entry_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear directory entry.", function ); memory_free( *directory_entry ); *directory_entry = NULL; return( -1 ); } return( 1 ); on_error: if( *directory_entry != NULL ) { memory_free( *directory_entry ); *directory_entry = NULL; } return( -1 ); } /* Frees a directory entry * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entry_free( libfsntfs_directory_entry_t **directory_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entry_free"; int result = 1; if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( *directory_entry != NULL ) { if( ( *directory_entry )->file_name_values != NULL ) { if( libfsntfs_file_name_values_free( &( ( *directory_entry )->file_name_values ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file name values.", function ); result = -1; } } if( ( *directory_entry )->short_file_name_values != NULL ) { if( libfsntfs_file_name_values_free( &( ( *directory_entry )->short_file_name_values ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free short file name values.", function ); result = -1; } } memory_free( *directory_entry ); *directory_entry = NULL; } return( result ); } /* Clones a directory entry * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entry_clone( libfsntfs_directory_entry_t **destination_directory_entry, libfsntfs_directory_entry_t *source_directory_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entry_clone"; if( destination_directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( *destination_directory_entry != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid destination directory entry value already set.", function ); return( -1 ); } if( source_directory_entry == NULL ) { *destination_directory_entry = source_directory_entry; return( 1 ); } if( libfsntfs_directory_entry_initialize( destination_directory_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create destination directory entry.", function ); goto on_error; } if( libfsntfs_file_name_values_clone( &( ( *destination_directory_entry )->file_name_values ), source_directory_entry->file_name_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create destination file name values.", function ); goto on_error; } if( libfsntfs_file_name_values_clone( &( ( *destination_directory_entry )->short_file_name_values ), source_directory_entry->short_file_name_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create destination short file name values.", function ); goto on_error; } ( *destination_directory_entry )->file_reference = source_directory_entry->file_reference; return( 1 ); on_error: if( *destination_directory_entry != NULL ) { libfsntfs_directory_entry_free( destination_directory_entry, NULL ); } return( -1 ); } /* Compares 2 directory entries by file reference * Returns LIBCDATA_COMPARE_LESS, LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error */ int libfsntfs_directory_entry_compare_by_file_reference( libfsntfs_directory_entry_t *first_directory_entry, libfsntfs_directory_entry_t *second_directory_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entry_compare_by_file_reference"; uint64_t first_mft_entry_index = 0; uint64_t second_mft_entry_index = 0; uint16_t first_sequence_number = 0; uint16_t second_sequence_number = 0; if( first_directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid first directory entry.", function ); return( -1 ); } if( second_directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid second directory entry.", function ); return( -1 ); } first_mft_entry_index = first_directory_entry->file_reference & 0xffffffffffffUL; second_mft_entry_index = second_directory_entry->file_reference & 0xffffffffffffUL; if( first_mft_entry_index < second_mft_entry_index ) { return( LIBCDATA_COMPARE_LESS ); } else if( first_mft_entry_index > second_mft_entry_index ) { return( LIBCDATA_COMPARE_GREATER ); } first_sequence_number = (uint16_t) ( first_directory_entry->file_reference >> 48 ); second_sequence_number = (uint16_t) ( second_directory_entry->file_reference >> 48 ); if( first_sequence_number < second_sequence_number ) { return( LIBCDATA_COMPARE_LESS ); } else if( first_sequence_number > second_sequence_number ) { return( LIBCDATA_COMPARE_GREATER ); } return( LIBCDATA_COMPARE_EQUAL ); } /* Retrieves the MFT entry index * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entry_get_mft_entry_index( libfsntfs_directory_entry_t *directory_entry, uint64_t *mft_entry_index, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entry_get_mft_entry_index"; if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( mft_entry_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry index.", function ); return( -1 ); } if( ( directory_entry->file_reference & 0xffffffffffffUL ) > (uint64_t) INT_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid MFT entry index value out of bounds.", function ); return( -1 ); } *mft_entry_index = (int) ( directory_entry->file_reference & 0xffffffffffffUL ); return( 1 ); } /* Retrieves the file reference * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entry_get_file_reference( libfsntfs_directory_entry_t *directory_entry, uint64_t *file_reference, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entry_get_file_reference"; if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( file_reference == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file reference.", function ); return( -1 ); } *file_reference = directory_entry->file_reference; return( 1 ); } /* Retrieves the parent file reference * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entry_get_parent_file_reference( libfsntfs_directory_entry_t *directory_entry, uint64_t *parent_file_reference, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entry_get_parent_file_reference"; if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_parent_file_reference( directory_entry->file_name_values, parent_file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve parent reference from file name values.", function ); return( -1 ); } return( 1 ); } /* Retrieves the creation date and time * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entry_get_creation_time( libfsntfs_directory_entry_t *directory_entry, uint64_t *filetime, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entry_get_creation_time"; if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_creation_time( directory_entry->file_name_values, filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve creation time from file name values.", function ); return( -1 ); } return( 1 ); } /* Retrieves the modification date and time * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entry_get_modification_time( libfsntfs_directory_entry_t *directory_entry, uint64_t *filetime, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entry_get_modification_time"; if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_modification_time( directory_entry->file_name_values, filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve modification time from file name values.", function ); return( -1 ); } return( 1 ); } /* Retrieves the access date and time * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entry_get_access_time( libfsntfs_directory_entry_t *directory_entry, uint64_t *filetime, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entry_get_access_time"; if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_access_time( directory_entry->file_name_values, filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve access time from file name values.", function ); return( -1 ); } return( 1 ); } /* Retrieves the entry modification date and time * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entry_get_entry_modification_time( libfsntfs_directory_entry_t *directory_entry, uint64_t *filetime, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entry_get_entry_modification_time"; if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_entry_modification_time( directory_entry->file_name_values, filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry modification time from file name values.", function ); return( -1 ); } return( 1 ); } /* Retrieves the size * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entry_get_size( libfsntfs_directory_entry_t *directory_entry, uint64_t *size, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entry_get_entry_size"; if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_size( directory_entry->file_name_values, size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size from file name values.", function ); return( -1 ); } return( 1 ); } /* Retrieves the file attribute flags * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entry_get_file_attribute_flags( libfsntfs_directory_entry_t *directory_entry, uint32_t *file_attribute_flags, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entry_get_entry_file_attribute_flags"; if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_file_attribute_flags( directory_entry->file_name_values, file_attribute_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file attribute flags from file name values.", function ); return( -1 ); } return( 1 ); } /* Retrieves the size of the UTF-8 encoded name * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entry_get_utf8_name_size( libfsntfs_directory_entry_t *directory_entry, size_t *utf8_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entry_get_utf8_name_size"; if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_utf8_name_size( directory_entry->file_name_values, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-8 name from file name values.", function ); return( -1 ); } return( 1 ); } /* Retrieves the UTF-8 encoded name * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entry_get_utf8_name( libfsntfs_directory_entry_t *directory_entry, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entry_get_utf8_name"; if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_utf8_name( directory_entry->file_name_values, utf8_string, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 name from file name values.", function ); return( -1 ); } return( 1 ); } /* Retrieves the size of the UTF-16 encoded name * This function uses UCS-2 (with surrogates) to support characters outside Unicode * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entry_get_utf16_name_size( libfsntfs_directory_entry_t *directory_entry, size_t *utf16_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entry_get_utf16_name_size"; if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_utf16_name_size( directory_entry->file_name_values, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-16 name from file name values.", function ); return( -1 ); } return( 1 ); } /* Retrieves the UTF-16 encoded name * This function uses UCS-2 (with surrogates) to support characters outside Unicode * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_directory_entry_get_utf16_name( libfsntfs_directory_entry_t *directory_entry, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_directory_entry_get_utf16_name"; if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_utf16_name( directory_entry->file_name_values, utf16_string, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 name from file name values.", function ); return( -1 ); } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_directory_entry.h ================================================ /* * Directory entry functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_DIRECTORY_ENTRY_H ) #define _LIBFSNTFS_DIRECTORY_ENTRY_H #include #include #include "libfsntfs_file_name_values.h" #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_directory_entry libfsntfs_directory_entry_t; struct libfsntfs_directory_entry { /* The file reference */ uint64_t file_reference; /* The file name */ libfsntfs_file_name_values_t *file_name_values; /* The short file name */ libfsntfs_file_name_values_t *short_file_name_values; }; int libfsntfs_directory_entry_initialize( libfsntfs_directory_entry_t **directory_entry, libcerror_error_t **error ); int libfsntfs_directory_entry_free( libfsntfs_directory_entry_t **directory_entry, libcerror_error_t **error ); int libfsntfs_directory_entry_clone( libfsntfs_directory_entry_t **destination_directory_entry, libfsntfs_directory_entry_t *source_directory_entry, libcerror_error_t **error ); int libfsntfs_directory_entry_compare_by_file_reference( libfsntfs_directory_entry_t *first_directory_entry, libfsntfs_directory_entry_t *second_directory_entry, libcerror_error_t **error ); int libfsntfs_directory_entry_get_mft_entry_index( libfsntfs_directory_entry_t *directory_entry, uint64_t *mft_entry_index, libcerror_error_t **error ); int libfsntfs_directory_entry_get_file_reference( libfsntfs_directory_entry_t *directory_entry, uint64_t *file_reference, libcerror_error_t **error ); int libfsntfs_directory_entry_get_parent_file_reference( libfsntfs_directory_entry_t *directory_entry, uint64_t *parent_file_reference, libcerror_error_t **error ); int libfsntfs_directory_entry_get_creation_time( libfsntfs_directory_entry_t *directory_entry, uint64_t *filetime, libcerror_error_t **error ); int libfsntfs_directory_entry_get_modification_time( libfsntfs_directory_entry_t *directory_entry, uint64_t *filetime, libcerror_error_t **error ); int libfsntfs_directory_entry_get_access_time( libfsntfs_directory_entry_t *directory_entry, uint64_t *filetime, libcerror_error_t **error ); int libfsntfs_directory_entry_get_entry_modification_time( libfsntfs_directory_entry_t *directory_entry, uint64_t *filetime, libcerror_error_t **error ); int libfsntfs_directory_entry_get_size( libfsntfs_directory_entry_t *directory_entry, uint64_t *size, libcerror_error_t **error ); int libfsntfs_directory_entry_get_file_attribute_flags( libfsntfs_directory_entry_t *directory_entry, uint32_t *file_attribute_flags, libcerror_error_t **error ); int libfsntfs_directory_entry_get_utf8_name_size( libfsntfs_directory_entry_t *directory_entry, size_t *utf8_string_size, libcerror_error_t **error ); int libfsntfs_directory_entry_get_utf8_name( libfsntfs_directory_entry_t *directory_entry, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); int libfsntfs_directory_entry_get_utf16_name_size( libfsntfs_directory_entry_t *directory_entry, size_t *utf16_string_size, libcerror_error_t **error ); int libfsntfs_directory_entry_get_utf16_name( libfsntfs_directory_entry_t *directory_entry, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_DIRECTORY_ENTRY_H ) */ ================================================ FILE: libfsntfs/libfsntfs_error.c ================================================ /* * Error functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_error.h" #include "libfsntfs_libcerror.h" #if !defined( HAVE_LOCAL_LIBFSNTFS ) /* Free an error and its elements */ void libfsntfs_error_free( libfsntfs_error_t **error ) { libcerror_error_free( (libcerror_error_t **) error ); } /* Prints a descriptive string of the error to the stream * Returns the number of printed characters if successful or -1 on error */ int libfsntfs_error_fprint( libfsntfs_error_t *error, FILE *stream ) { int print_count = 0; print_count = libcerror_error_fprint( (libcerror_error_t *) error, stream ); return( print_count ); } /* Prints a descriptive string of the error to the string * The end-of-string character is not included in the return value * Returns the number of printed characters if successful or -1 on error */ int libfsntfs_error_sprint( libfsntfs_error_t *error, char *string, size_t size ) { int print_count = 0; print_count = libcerror_error_sprint( (libcerror_error_t *) error, string, size ); return( print_count ); } /* Prints a backtrace of the error to the stream * Returns the number of printed characters if successful or -1 on error */ int libfsntfs_error_backtrace_fprint( libfsntfs_error_t *error, FILE *stream ) { int print_count = 0; print_count = libcerror_error_backtrace_fprint( (libcerror_error_t *) error, stream ); return( print_count ); } /* Prints a backtrace of the error to the string * The end-of-string character is not included in the return value * Returns the number of printed characters if successful or -1 on error */ int libfsntfs_error_backtrace_sprint( libfsntfs_error_t *error, char *string, size_t size ) { int print_count = 0; print_count = libcerror_error_backtrace_sprint( (libcerror_error_t *) error, string, size ); return( print_count ); } #endif /* !defined( HAVE_LOCAL_LIBFSNTFS ) */ ================================================ FILE: libfsntfs/libfsntfs_error.h ================================================ /* * Error functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_INTERNAL_ERROR_H ) #define _LIBFSNTFS_INTERNAL_ERROR_H #include #include #include #if !defined( HAVE_LOCAL_LIBFSNTFS ) #include #endif #include "libfsntfs_extern.h" #if defined( __cplusplus ) extern "C" { #endif #if !defined( HAVE_LOCAL_LIBFSNTFS ) LIBFSNTFS_EXTERN \ void libfsntfs_error_free( libfsntfs_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_error_fprint( libfsntfs_error_t *error, FILE *stream ); LIBFSNTFS_EXTERN \ int libfsntfs_error_sprint( libfsntfs_error_t *error, char *string, size_t size ); LIBFSNTFS_EXTERN \ int libfsntfs_error_backtrace_fprint( libfsntfs_error_t *error, FILE *stream ); LIBFSNTFS_EXTERN \ int libfsntfs_error_backtrace_sprint( libfsntfs_error_t *error, char *string, size_t size ); #endif /* !defined( HAVE_LOCAL_LIBFSNTFS ) */ #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_INTERNAL_ERROR_H ) */ ================================================ FILE: libfsntfs/libfsntfs_extent.c ================================================ /* * Extent functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_extent.h" #include "libfsntfs_libcerror.h" /* Creates a extent * Make sure the value extent is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_extent_initialize( libfsntfs_extent_t **extent, libcerror_error_t **error ) { static char *function = "libfsntfs_extent_initialize"; if( extent == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid extent.", function ); return( -1 ); } if( *extent != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid extent value already set.", function ); return( -1 ); } *extent = memory_allocate_structure( libfsntfs_extent_t ); if( *extent == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create extent.", function ); goto on_error; } if( memory_set( *extent, 0, sizeof( libfsntfs_extent_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear extent.", function ); memory_free( *extent ); *extent = NULL; return( -1 ); } return( 1 ); on_error: if( *extent != NULL ) { memory_free( *extent ); *extent = NULL; } return( -1 ); } /* Frees a extent * Returns 1 if successful or -1 on error */ int libfsntfs_extent_free( libfsntfs_extent_t **extent, libcerror_error_t **error ) { static char *function = "libfsntfs_extent_free"; if( extent == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid extent.", function ); return( -1 ); } if( *extent != NULL ) { memory_free( *extent ); *extent = NULL; } return( 1 ); } /* Retrieves the extent values * Returns 1 if successful or -1 on error */ int libfsntfs_extent_get_values( libfsntfs_extent_t *extent, off64_t *extent_offset, size64_t *extent_size, uint32_t *extent_flags, libcerror_error_t **error ) { static char *function = "libfsntfs_extent_get_values"; if( extent == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid extent.", function ); return( -1 ); } if( extent_offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid extent offset.", function ); return( -1 ); } if( extent_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid extent size.", function ); return( -1 ); } if( extent_flags == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid extent flags.", function ); return( -1 ); } *extent_offset = extent->start_offset; *extent_size = extent->size; *extent_flags = extent->range_flags; return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_extent.h ================================================ /* * Extent functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_EXTENT_H ) #define _LIBFSNTFS_EXTENT_H #include #include #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_extent libfsntfs_extent_t; struct libfsntfs_extent { /* The start offset */ off64_t start_offset; /* The size */ size64_t size; /* The range flags */ uint32_t range_flags; }; int libfsntfs_extent_initialize( libfsntfs_extent_t **extent, libcerror_error_t **error ); int libfsntfs_extent_free( libfsntfs_extent_t **extent, libcerror_error_t **error ); int libfsntfs_extent_get_values( libfsntfs_extent_t *extent, off64_t *extent_offset, size64_t *extent_size, uint32_t *extent_flags, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_EXTENT_H ) */ ================================================ FILE: libfsntfs/libfsntfs_extern.h ================================================ /* * The internal extern definition * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_INTERNAL_EXTERN_H ) #define _LIBFSNTFS_INTERNAL_EXTERN_H #include /* Define HAVE_LOCAL_LIBFSNTFS for local use of libfsntfs */ #if !defined( HAVE_LOCAL_LIBFSNTFS ) #include #if defined( __CYGWIN__ ) || defined( __MINGW32__ ) #define LIBFSNTFS_EXTERN_VARIABLE extern #else #define LIBFSNTFS_EXTERN_VARIABLE LIBFSNTFS_EXTERN #endif #else #define LIBFSNTFS_EXTERN /* extern */ #define LIBFSNTFS_EXTERN_VARIABLE extern #endif /* !defined( HAVE_LOCAL_LIBFSNTFS ) */ #endif /* !defined( _LIBFSNTFS_INTERNAL_EXTERN_H ) */ ================================================ FILE: libfsntfs/libfsntfs_file_entry.c ================================================ /* * File entry functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_attribute.h" #include "libfsntfs_cluster_block_stream.h" #include "libfsntfs_data_stream.h" #include "libfsntfs_definitions.h" #include "libfsntfs_directory_entries_tree.h" #include "libfsntfs_directory_entry.h" #include "libfsntfs_extent.h" #include "libfsntfs_file_entry.h" #include "libfsntfs_file_name_attribute.h" #include "libfsntfs_file_name_values.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_entry.h" #include "libfsntfs_path_hint.h" #include "libfsntfs_reparse_point_attribute.h" #include "libfsntfs_security_descriptor_values.h" #include "libfsntfs_standard_information_values.h" #include "libfsntfs_types.h" /* Creates a file entry * Make sure the value file_entry is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_file_entry_initialize( libfsntfs_file_entry_t **file_entry, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfsntfs_file_system_t *file_system, uint64_t mft_entry_index, libfsntfs_directory_entry_t *directory_entry, uint8_t flags, libcerror_error_t **error ) { libfsntfs_attribute_t *reparse_point_attribute = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; libfsntfs_mft_attribute_t *data_extents_attribute = NULL; libfsntfs_mft_attribute_t *wof_compressed_data_attribute = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; static char *function = "libfsntfs_file_entry_initialize"; uint64_t base_record_file_reference = 0; uint32_t compression_method = 0; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( *file_entry != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file entry value already set.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } internal_file_entry = memory_allocate_structure( libfsntfs_internal_file_entry_t ); if( internal_file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file entry.", function ); goto on_error; } if( memory_set( internal_file_entry, 0, sizeof( libfsntfs_internal_file_entry_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear file entry.", function ); memory_free( internal_file_entry ); return( -1 ); } if( libfsntfs_file_system_get_mft_entry_by_index_no_cache( file_system, file_io_handle, mft_entry_index, &mft_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: %" PRIu64 ".", function, mft_entry_index ); goto on_error; } if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing MFT entry: %" PRIu64 ".", function, mft_entry_index ); return( -1 ); } if( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) == 0 ) { result = libfsntfs_mft_entry_get_base_record_file_reference( mft_entry, &base_record_file_reference, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve base record file reference.", function ); goto on_error; } if( ( result == 1 ) && ( base_record_file_reference == 0 ) ) { if( mft_entry->has_i30_index != 0 ) { if( libfsntfs_directory_entries_tree_initialize( &( internal_file_entry->directory_entries_tree ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create directory entries tree.", function ); goto on_error; } if( libfsntfs_directory_entries_tree_read_from_i30_index( internal_file_entry->directory_entries_tree, io_handle, file_io_handle, mft_entry, flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read MFT entry: %" PRIu32 " directory entries tree.", function, mft_entry->index ); goto on_error; } } if( mft_entry->data_attribute != NULL ) { if( mft_entry->wof_compressed_data_attribute != NULL ) { result = libfsntfs_internal_file_entry_get_reparse_point_attribute( internal_file_entry, mft_entry, &reparse_point_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve reparse point attribute.", function ); goto on_error; } else if( result != 0 ) { if( libfsntfs_reparse_point_attribute_get_compression_method( reparse_point_attribute, &compression_method, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve compression method from $REPARSE_POINT attribute.", function ); goto on_error; } wof_compressed_data_attribute = mft_entry->wof_compressed_data_attribute; } } if( wof_compressed_data_attribute == NULL ) { data_extents_attribute = mft_entry->data_attribute; } else { data_extents_attribute = wof_compressed_data_attribute; } if( libfsntfs_mft_attribute_get_data_extents_array( data_extents_attribute, io_handle, &( internal_file_entry->extents_array ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create extents array.", function ); goto on_error; } if( libfsntfs_cluster_block_stream_initialize( &( internal_file_entry->data_cluster_block_stream ), io_handle, mft_entry->data_attribute, wof_compressed_data_attribute, compression_method, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create data cluster block stream.", function ); goto on_error; } } } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_initialize( &( internal_file_entry->read_write_lock ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize read/write lock.", function ); goto on_error; } #endif internal_file_entry->io_handle = io_handle; internal_file_entry->file_io_handle = file_io_handle; internal_file_entry->file_system = file_system; internal_file_entry->mft_entry = mft_entry; internal_file_entry->directory_entry = directory_entry; internal_file_entry->data_attribute = mft_entry->data_attribute; internal_file_entry->flags = flags; *file_entry = (libfsntfs_file_entry_t *) internal_file_entry; return( 1 ); on_error: if( mft_entry != NULL ) { libfsntfs_mft_entry_free( &mft_entry, NULL ); } if( internal_file_entry != NULL ) { if( internal_file_entry->data_cluster_block_stream != NULL ) { libfdata_stream_free( &( internal_file_entry->data_cluster_block_stream ), NULL ); } if( internal_file_entry->directory_entries_tree != NULL ) { libfsntfs_directory_entries_tree_free( &( internal_file_entry->directory_entries_tree ), NULL ); } if( internal_file_entry->extents_array != NULL ) { libcdata_array_free( &( internal_file_entry->extents_array ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_extent_free, NULL ); } memory_free( internal_file_entry ); } return( -1 ); } /* Frees a file entry * Returns 1 if successful or -1 on error */ int libfsntfs_file_entry_free( libfsntfs_file_entry_t **file_entry, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_free"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( *file_entry != NULL ) { internal_file_entry = (libfsntfs_internal_file_entry_t *) *file_entry; *file_entry = NULL; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_free( &( internal_file_entry->read_write_lock ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free read/write lock.", function ); result = -1; } #endif /* The file_io_handle, io_handle and file_system references are freed elsewhere */ if( internal_file_entry->data_cluster_block_stream != NULL ) { if( libfdata_stream_free( &( internal_file_entry->data_cluster_block_stream ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free data cluster block stream.", function ); result = -1; } } /* The reparse_point_attribute, security_descriptor_attribute and standard_information_attribute references are managed by the attributes_array */ if( internal_file_entry->attributes_array != NULL ) { if( libcdata_array_free( &( internal_file_entry->attributes_array ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_internal_attribute_free, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free attributes array.", function ); result = -1; } } if( libcdata_array_free( &( internal_file_entry->extents_array ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_extent_free, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free extents array.", function ); result = -1; } if( internal_file_entry->security_descriptor_values != NULL ) { if( libfsntfs_security_descriptor_values_free( &( internal_file_entry->security_descriptor_values ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free security descriptor values.", function ); result = -1; } } if( internal_file_entry->directory_entries_tree != NULL ) { if( libfsntfs_directory_entries_tree_free( &( internal_file_entry->directory_entries_tree ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free directory entries tree.", function ); result = -1; } } if( internal_file_entry->directory_entry != NULL ) { if( libfsntfs_directory_entry_free( &( internal_file_entry->directory_entry ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free directory entry.", function ); result = -1; } } if( internal_file_entry->mft_entry != NULL ) { if( libfsntfs_mft_entry_free( &( internal_file_entry->mft_entry ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free MFT entry.", function ); result = -1; } } memory_free( internal_file_entry ); } return( result ); } /* Determines if the file entry is empty * Returns 1 if empty, 0 if not or -1 on error */ int libfsntfs_file_entry_is_empty( libfsntfs_file_entry_t *file_entry, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_is_empty"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif result = libfsntfs_mft_entry_is_empty( internal_file_entry->mft_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if MFT entry is empty.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Determines if the file entry is allocated (MFT entry in use flag is set) * Returns 1 if allocated, 0 if not or -1 on error */ int libfsntfs_file_entry_is_allocated( libfsntfs_file_entry_t *file_entry, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_is_allocated"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif result = libfsntfs_mft_entry_is_allocated( internal_file_entry->mft_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if MFT entry is allocated.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Determines if the file entry is corrupted * Returns 1 if corrupted, 0 if not or -1 on error */ int libfsntfs_file_entry_is_corrupted( libfsntfs_file_entry_t *file_entry, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_is_corrupted"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif result = libfsntfs_mft_entry_is_corrupted( internal_file_entry->mft_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if MFT entry is corrupted.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves a specific attribute * Returns 1 if successful or -1 on error */ int libfsntfs_internal_file_entry_get_attribute_by_index( libfsntfs_internal_file_entry_t *internal_file_entry, libfsntfs_mft_entry_t *mft_entry, int attribute_index, libfsntfs_attribute_t **attribute, libcerror_error_t **error ) { libfsntfs_attribute_t *safe_attribute = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; static char *function = "libfsntfs_internal_file_entry_get_attribute_by_index"; uint32_t attribute_type = 0; int number_of_attributes = 0; if( internal_file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( internal_file_entry->attributes_array == NULL ) { if( libfsntfs_mft_entry_get_number_of_attributes( mft_entry, &number_of_attributes, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of attributes.", function ); goto on_error; } if( libcdata_array_initialize( &( internal_file_entry->attributes_array ), number_of_attributes, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create attributes array.", function ); goto on_error; } } if( libcdata_array_get_entry_by_index( internal_file_entry->attributes_array, attribute_index, (intptr_t **) attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d from array.", function, attribute_index ); goto on_error; } if( *attribute == NULL ) { if( libfsntfs_mft_entry_get_attribute_by_index( mft_entry, attribute_index, &mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d from MFT entry.", function, attribute_index ); goto on_error; } if( libfsntfs_mft_attribute_get_type( mft_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d type.", function, attribute_index ); goto on_error; } if( libfsntfs_attribute_initialize( &safe_attribute, mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create attribute: %d.", function, attribute_index ); goto on_error; } if( attribute_type == LIBFSNTFS_ATTRIBUTE_TYPE_ATTRIBUTE_LIST ) { ( (libfsntfs_internal_attribute_t *) safe_attribute )->value = (intptr_t *) mft_entry->attribute_list; } else { if( libfsntfs_internal_attribute_read_value( (libfsntfs_internal_attribute_t *) safe_attribute, internal_file_entry->io_handle, internal_file_entry->file_io_handle, internal_file_entry->flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read value of attribute: %d.", function, attribute_index ); goto on_error; } } if( libcdata_array_set_entry_by_index( internal_file_entry->attributes_array, attribute_index, (intptr_t *) safe_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set atribute: %d in array.", function, attribute_index ); goto on_error; } *attribute = safe_attribute; } return( 1 ); on_error: if( safe_attribute != NULL ) { libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &safe_attribute, NULL ); } return( -1 ); } /* Retrieves the $REPARSE_POINT attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_internal_file_entry_get_reparse_point_attribute( libfsntfs_internal_file_entry_t *internal_file_entry, libfsntfs_mft_entry_t *mft_entry, libfsntfs_attribute_t **attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_internal_file_entry_get_reparse_point_attribute"; if( internal_file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing MFT entry.", function ); return( -1 ); } if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( mft_entry->reparse_point_attribute_index == -1 ) { return( 0 ); } if( internal_file_entry->reparse_point_attribute == NULL ) { if( libfsntfs_internal_file_entry_get_attribute_by_index( internal_file_entry, mft_entry, mft_entry->reparse_point_attribute_index, &( internal_file_entry->reparse_point_attribute ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d.", function, mft_entry->reparse_point_attribute_index ); return( -1 ); } } *attribute = internal_file_entry->reparse_point_attribute; return( 1 ); } /* Retrieves the $SECURITY_DESCRIPTOR attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_internal_file_entry_get_security_descriptor_attribute( libfsntfs_internal_file_entry_t *internal_file_entry, libfsntfs_attribute_t **attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_internal_file_entry_get_security_descriptor_attribute"; if( internal_file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( internal_file_entry->mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid file entry - missing MFT entry.", function ); return( -1 ); } if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( internal_file_entry->mft_entry->security_descriptor_attribute_index == -1 ) { return( 0 ); } if( internal_file_entry->security_descriptor_attribute == NULL ) { if( libfsntfs_internal_file_entry_get_attribute_by_index( internal_file_entry, internal_file_entry->mft_entry, internal_file_entry->mft_entry->security_descriptor_attribute_index, &( internal_file_entry->security_descriptor_attribute ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d.", function, internal_file_entry->mft_entry->security_descriptor_attribute_index ); return( -1 ); } } *attribute = internal_file_entry->security_descriptor_attribute; return( 1 ); } /* Retrieves the $STANDARD_INFORMATION attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_internal_file_entry_get_standard_information_attribute( libfsntfs_internal_file_entry_t *internal_file_entry, libfsntfs_attribute_t **attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_internal_file_entry_get_standard_information_attribute"; if( internal_file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( internal_file_entry->mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid file entry - missing MFT entry.", function ); return( -1 ); } if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( internal_file_entry->mft_entry->standard_information_attribute_index == -1 ) { return( 0 ); } if( internal_file_entry->standard_information_attribute == NULL ) { if( libfsntfs_internal_file_entry_get_attribute_by_index( internal_file_entry, internal_file_entry->mft_entry, internal_file_entry->mft_entry->standard_information_attribute_index, &( internal_file_entry->standard_information_attribute ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d.", function, internal_file_entry->mft_entry->standard_information_attribute_index ); return( -1 ); } } *attribute = internal_file_entry->standard_information_attribute; return( 1 ); } /* Retrieves the file reference * This value is retrieved from the MFT entry * Returns 1 if successful or -1 on error */ int libfsntfs_file_entry_get_file_reference( libfsntfs_file_entry_t *file_entry, uint64_t *file_reference, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_file_reference"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( file_reference == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file reference.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_entry_get_file_reference( internal_file_entry->mft_entry, file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file reference from MFT entry.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the base record file reference * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_base_record_file_reference( libfsntfs_file_entry_t *file_entry, uint64_t *file_reference, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_base_record_file_reference"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif result = libfsntfs_mft_entry_get_base_record_file_reference( internal_file_entry->mft_entry, file_reference, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve base record file reference from MFT entry.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the parent file reference * This value is retrieved from the directory entry $FILE_NAME attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_parent_file_reference( libfsntfs_file_entry_t *file_entry, uint64_t *parent_file_reference, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_parent_file_reference"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_file_entry->directory_entry != NULL ) { result = libfsntfs_directory_entry_get_parent_file_reference( internal_file_entry->directory_entry, parent_file_reference, error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve parent reference from directory entry.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the parent file reference for a specific $FILE_NAME attribute * Returns 1 if successful or -1 on error */ int libfsntfs_file_entry_get_parent_file_reference_by_attribute_index( libfsntfs_file_entry_t *file_entry, int attribute_index, uint64_t *parent_file_reference, libcerror_error_t **error ) { libfsntfs_attribute_t *attribute = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_parent_file_reference_by_attribute_index"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_internal_file_entry_get_attribute_by_index( internal_file_entry, internal_file_entry->mft_entry, attribute_index, &attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d.", function, attribute_index ); result = -1; } else if( libfsntfs_file_name_attribute_get_parent_file_reference( attribute, parent_file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve parent reference from $FILE_NAME attribute.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the journal sequence number * Returns 1 if successful or -1 on error */ int libfsntfs_file_entry_get_journal_sequence_number( libfsntfs_file_entry_t *file_entry, uint64_t *journal_sequence_number, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_journal_sequence_number"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_entry_get_journal_sequence_number( internal_file_entry->mft_entry, journal_sequence_number, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve journal sequence number from MFT entry.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the creation date and time * This value is retrieved from the $STANDARD_INFORMATION attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_creation_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libcerror_error_t **error ) { libfsntfs_attribute_t *standard_information_attribute = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; static char *function = "libfsntfs_file_entry_get_creation_time"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif result = libfsntfs_internal_file_entry_get_standard_information_attribute( internal_file_entry, &standard_information_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve standard information attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_internal_attribute_get_value( (libfsntfs_internal_attribute_t *) standard_information_attribute, (intptr_t **) &standard_information_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve value from standard information attribute.", function ); result = -1; } else if( libfsntfs_standard_information_values_get_creation_time( standard_information_values, filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve creation time from standard information attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the (file) modification (last written) date and time * This value is retrieved from the $STANDARD_INFORMATION attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_modification_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libcerror_error_t **error ) { libfsntfs_attribute_t *standard_information_attribute = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; static char *function = "libfsntfs_file_entry_get_modification_time"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif result = libfsntfs_internal_file_entry_get_standard_information_attribute( internal_file_entry, &standard_information_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve standard information attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_internal_attribute_get_value( (libfsntfs_internal_attribute_t *) standard_information_attribute, (intptr_t **) &standard_information_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve standard information attribute value.", function ); result = -1; } else if( libfsntfs_standard_information_values_get_modification_time( standard_information_values, filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve modification time from standard information attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the access date and time * This value is retrieved from the $STANDARD_INFORMATION attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_access_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libcerror_error_t **error ) { libfsntfs_attribute_t *standard_information_attribute = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; static char *function = "libfsntfs_file_entry_get_access_time"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif result = libfsntfs_internal_file_entry_get_standard_information_attribute( internal_file_entry, &standard_information_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve standard information attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_internal_attribute_get_value( (libfsntfs_internal_attribute_t *) standard_information_attribute, (intptr_t **) &standard_information_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve standard information attribute value.", function ); result = -1; } else if( libfsntfs_standard_information_values_get_access_time( standard_information_values, filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve access time from standard information attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the (file system entry) modification date and time * This value is retrieved from the $STANDARD_INFORMATION attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_entry_modification_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libcerror_error_t **error ) { libfsntfs_attribute_t *standard_information_attribute = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; static char *function = "libfsntfs_file_entry_get_entry_modification_time"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif result = libfsntfs_internal_file_entry_get_standard_information_attribute( internal_file_entry, &standard_information_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve standard information attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_internal_attribute_get_value( (libfsntfs_internal_attribute_t *) standard_information_attribute, (intptr_t **) &standard_information_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve standard information attribute value.", function ); result = -1; } else if( libfsntfs_standard_information_values_get_entry_modification_time( standard_information_values, filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry modification time from standard information attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the file attribute flags * This value is retrieved from the $STANDARD_INFORMATION attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_file_attribute_flags( libfsntfs_file_entry_t *file_entry, uint32_t *file_attribute_flags, libcerror_error_t **error ) { libfsntfs_attribute_t *standard_information_attribute = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; static char *function = "libfsntfs_file_entry_get_file_attribute_flags"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif result = libfsntfs_internal_file_entry_get_standard_information_attribute( internal_file_entry, &standard_information_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve standard information attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_internal_attribute_get_value( (libfsntfs_internal_attribute_t *) standard_information_attribute, (intptr_t **) &standard_information_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve standard information attribute value.", function ); result = -1; } else if( libfsntfs_standard_information_values_get_file_attribute_flags( standard_information_values, file_attribute_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file attribute flags from standard information attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the file reference * This value is retrieved from the $I30 $FILE_NAME directory entry * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_i30_file_reference( libfsntfs_file_entry_t *file_entry, uint64_t *file_reference, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_i30_file_reference"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( file_reference == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file reference.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_file_entry->directory_entry != NULL ) { result = libfsntfs_directory_entry_get_file_reference( internal_file_entry->directory_entry, file_reference, error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file reference from directory entry.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the creation date and time * This value is retrieved from the $I30 $FILE_NAME directory entry * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_i30_creation_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_i30_creation_time"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_file_entry->directory_entry != NULL ) { result = libfsntfs_directory_entry_get_creation_time( internal_file_entry->directory_entry, filetime, error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve creation time from directory entry.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the modification date and time * This value is retrieved from the $I30 $FILE_NAME directory entry * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_i30_modification_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_i30_modification_time"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_file_entry->directory_entry != NULL ) { result = libfsntfs_directory_entry_get_modification_time( internal_file_entry->directory_entry, filetime, error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve modification time from directory entry.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the access date and time * This value is retrieved from the $I30 $FILE_NAME directory entry * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_i30_access_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_i30_access_time"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_file_entry->directory_entry != NULL ) { result = libfsntfs_directory_entry_get_access_time( internal_file_entry->directory_entry, filetime, error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve access time from directory entry.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the entry modification date and time * This value is retrieved from the $I30 $FILE_NAME directory entry * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_i30_entry_modification_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_i30_entry_modification_time"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_file_entry->directory_entry != NULL ) { result = libfsntfs_directory_entry_get_entry_modification_time( internal_file_entry->directory_entry, filetime, error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry modification time from directory entry.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the size * This value is retrieved from the $I30 $FILE_NAME directory entry * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_i30_size( libfsntfs_file_entry_t *file_entry, uint64_t *size, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_i30_size"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_file_entry->directory_entry != NULL ) { result = libfsntfs_directory_entry_get_size( internal_file_entry->directory_entry, size, error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size from directory entry.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the file attribute flags * This value is retrieved from the $I30 $FILE_NAME directory entry * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_i30_file_attribute_flags( libfsntfs_file_entry_t *file_entry, uint32_t *file_attribute_flags, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_i30_file_attribute_flags"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_file_entry->directory_entry != NULL ) { result = libfsntfs_directory_entry_get_file_attribute_flags( internal_file_entry->directory_entry, file_attribute_flags, error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file attribute flags from directory entry.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the size of the UTF-8 encoded name * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode * The returned size includes the end of string character * This value is retrieved from the directory entry $FILE_NAME attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_utf8_name_size( libfsntfs_file_entry_t *file_entry, size_t *utf8_string_size, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_utf8_name_size"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_file_entry->directory_entry != NULL ) { result = libfsntfs_directory_entry_get_utf8_name_size( internal_file_entry->directory_entry, utf8_string_size, error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-8 name from directory entry.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the UTF-8 encoded name * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode * The size should include the end of string character * This value is retrieved from the directory entry $FILE_NAME attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_utf8_name( libfsntfs_file_entry_t *file_entry, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_utf8_name"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_file_entry->directory_entry != NULL ) { result = libfsntfs_directory_entry_get_utf8_name( internal_file_entry->directory_entry, utf8_string, utf8_string_size, error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 name from directory entry.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the size of the UTF-16 encoded name * This function uses UCS-2 (with surrogates) to support characters outside Unicode * The returned size includes the end of string character * This value is retrieved from the directory entry $FILE_NAME attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_utf16_name_size( libfsntfs_file_entry_t *file_entry, size_t *utf16_string_size, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_utf16_name_size"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_file_entry->directory_entry != NULL ) { result = libfsntfs_directory_entry_get_utf16_name_size( internal_file_entry->directory_entry, utf16_string_size, error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-16 name from directory.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the UTF-16 encoded name * This function uses UCS-2 (with surrogates) to support characters outside Unicode * The size should include the end of string character * This value is retrieved from the directory entry $FILE_NAME attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_utf16_name( libfsntfs_file_entry_t *file_entry, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_utf16_name"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_file_entry->directory_entry != NULL ) { result = libfsntfs_directory_entry_get_utf16_name( internal_file_entry->directory_entry, utf16_string, utf16_string_size, error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 name from directory entry.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the $FILE_NAME attribute index * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_name_attribute_index( libfsntfs_file_entry_t *file_entry, int *attribute_index, libcerror_error_t **error ) { uint8_t lookup_name_root[ 2 ] = { '.', 0 }; libfsntfs_attribute_t *attribute = NULL; libfsntfs_file_name_values_t *file_name_values = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; uint8_t *lookup_name = NULL; static char *function = "libfsntfs_file_entry_get_name_attribute_index"; size_t lookup_name_size = 0; uint64_t lookup_parent_file_reference = 0; uint32_t attribute_type = 0; uint8_t lookup_name_space = 0; int number_of_attributes = 0; int safe_attribute_index = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( attribute_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute index", function ); return( -1 ); } /* TODO add thread lock suport */ if( internal_file_entry->directory_entry == NULL ) { lookup_name = lookup_name_root; lookup_name_size = 2; lookup_name_space = LIBFSNTFS_FILE_NAME_SPACE_DOS_WINDOWS; } else { if( internal_file_entry->directory_entry->file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid file entry - invalid directory entry - missing file name values.", function ); return( -1 ); } lookup_name = internal_file_entry->directory_entry->file_name_values->name; lookup_name_size = internal_file_entry->directory_entry->file_name_values->name_size; lookup_name_space = internal_file_entry->directory_entry->file_name_values->name_space; lookup_parent_file_reference = internal_file_entry->directory_entry->file_name_values->parent_file_reference; } if( libfsntfs_mft_entry_get_number_of_attributes( internal_file_entry->mft_entry, &number_of_attributes, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of attributes.", function ); return( -1 ); } for( safe_attribute_index = 0; safe_attribute_index < number_of_attributes; safe_attribute_index++ ) { if( libfsntfs_internal_file_entry_get_attribute_by_index( internal_file_entry, internal_file_entry->mft_entry, safe_attribute_index, &attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d.", function, safe_attribute_index ); return( -1 ); } if( libfsntfs_attribute_get_type( attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d type.", function, safe_attribute_index ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ) { continue; } if( libfsntfs_internal_attribute_get_value( (libfsntfs_internal_attribute_t *) attribute, (intptr_t **) &file_name_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d value.", function, safe_attribute_index ); return( -1 ); } if( ( lookup_parent_file_reference == file_name_values->parent_file_reference ) && ( lookup_name_space == file_name_values->name_space ) && ( lookup_name_size == file_name_values->name_size ) && ( memory_compare( lookup_name, file_name_values->name, file_name_values->name_size ) == 0 ) ) { *attribute_index = safe_attribute_index; return( 1 ); } } return( 0 ); } /* Retrieves the size of the UTF-8 encoded name for a specific $FILE_NAME attribute * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_file_entry_get_utf8_name_size_by_attribute_index( libfsntfs_file_entry_t *file_entry, int attribute_index, size_t *utf8_string_size, libcerror_error_t **error ) { libfsntfs_attribute_t *attribute = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_utf8_name_size_by_attribute_index"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif if( libfsntfs_internal_file_entry_get_attribute_by_index( internal_file_entry, internal_file_entry->mft_entry, attribute_index, &attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d.", function, attribute_index ); result = -1; } else if( libfsntfs_file_name_attribute_get_utf8_name_size( attribute, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-8 name from $FILE_NAME attribute.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the UTF-8 encoded name for a specific $FILE_NAME attribute * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_file_entry_get_utf8_name_by_attribute_index( libfsntfs_file_entry_t *file_entry, int attribute_index, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { libfsntfs_attribute_t *attribute = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_utf8_name_by_attribute_index"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif if( libfsntfs_internal_file_entry_get_attribute_by_index( internal_file_entry, internal_file_entry->mft_entry, attribute_index, &attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d.", function, attribute_index ); result = -1; } else if( libfsntfs_file_name_attribute_get_utf8_name( attribute, utf8_string, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 name from $FILE_NAME attribute.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the size of the UTF-16 encoded name for a specific $FILE_NAME attribute * This function uses UCS-2 (with surrogates) to support characters outside Unicode * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_file_entry_get_utf16_name_size_by_attribute_index( libfsntfs_file_entry_t *file_entry, int attribute_index, size_t *utf16_string_size, libcerror_error_t **error ) { libfsntfs_attribute_t *attribute = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_utf16_name_size_by_attribute_index"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif if( libfsntfs_internal_file_entry_get_attribute_by_index( internal_file_entry, internal_file_entry->mft_entry, attribute_index, &attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d.", function, attribute_index ); result = -1; } else if( libfsntfs_file_name_attribute_get_utf16_name_size( attribute, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-16 name from $FILE_NAME attribute.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the UTF-16 encoded name for a specific $FILE_NAME attribute * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_file_entry_get_utf16_name_by_attribute_index( libfsntfs_file_entry_t *file_entry, int attribute_index, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { libfsntfs_attribute_t *attribute = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_utf16_name_by_attribute_index"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif if( libfsntfs_internal_file_entry_get_attribute_by_index( internal_file_entry, internal_file_entry->mft_entry, attribute_index, &attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d.", function, attribute_index ); result = -1; } else if( libfsntfs_file_name_attribute_get_utf16_name( attribute, utf16_string, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 name from $FILE_NAME attribute.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the path hint for a specific $FILE_NAME attribute * Returns 1 if successful or -1 on error */ int libfsntfs_internal_file_entry_get_path_hint( libfsntfs_internal_file_entry_t *internal_file_entry, int attribute_index, libfsntfs_path_hint_t **path_hint, libcerror_error_t **error ) { libfsntfs_attribute_t *attribute = NULL; libfsntfs_file_name_values_t *file_name_values = NULL; libfsntfs_path_hint_t *parent_path_hint = NULL; libfsntfs_path_hint_t *safe_path_hint = NULL; uint8_t *parent_path = NULL; static char *function = "libfsntfs_internal_file_entry_get_path_hint"; size_t name_size = 0; size_t parent_path_size = 0; uint64_t file_reference = 0; uint64_t mft_entry_index = 0; uint64_t parent_file_reference = 0; uint64_t parent_mft_entry_index = 0; int result = 0; if( internal_file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( path_hint == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path hint.", function ); return( -1 ); } /* TODO cache path hint in attribute */ if( libfsntfs_internal_file_entry_get_attribute_by_index( internal_file_entry, internal_file_entry->mft_entry, attribute_index, &attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d.", function, attribute_index ); goto on_error; } if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing attribute?: %d.", function, attribute_index ); goto on_error; } if( ( (libfsntfs_internal_attribute_t *) attribute )->path_hint == NULL ) { if( libfsntfs_mft_entry_get_file_reference( internal_file_entry->mft_entry, &file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file reference from MFT entry.", function ); goto on_error; } mft_entry_index = file_reference & 0xffffffffffffUL; if( libfsntfs_file_name_attribute_get_parent_file_reference( attribute, &parent_file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve parent reference from $FILE_NAME attribute.", function ); result = -1; } parent_mft_entry_index = parent_file_reference & 0xffffffffffffUL; parent_path = NULL; parent_path_size = 0; if( ( mft_entry_index != LIBFSNTFS_MFT_ENTRY_INDEX_ROOT_DIRECTORY ) && ( parent_mft_entry_index == LIBFSNTFS_MFT_ENTRY_INDEX_ROOT_DIRECTORY ) ) { parent_path = (uint8_t *) ""; parent_path_size = 1; } else if( ( parent_mft_entry_index != 0 ) && ( parent_mft_entry_index != mft_entry_index ) ) { result = libfsntfs_file_system_get_path_hint( internal_file_entry->file_system, internal_file_entry->file_io_handle, parent_file_reference, &parent_path_hint, 0, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve path hint for MFT entry: %" PRIu64 ".", function, parent_mft_entry_index ); goto on_error; } else if( result == 0 ) { parent_path = (uint8_t *) "$Orphan"; parent_path_size = 8; } else { parent_path = parent_path_hint->path; parent_path_size = parent_path_hint->path_size; } } if( libfsntfs_file_name_attribute_get_utf8_name_size( attribute, &name_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-8 name from $FILE_NAME attribute.", function ); goto on_error; } if( libfsntfs_path_hint_initialize( &safe_path_hint, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create path hint.", function ); goto on_error; } safe_path_hint->file_reference = file_reference; safe_path_hint->path_size = parent_path_size + name_size; safe_path_hint->path = (uint8_t *) memory_allocate( sizeof( uint8_t ) * safe_path_hint->path_size ); if( safe_path_hint->path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create path.", function ); goto on_error; } if( ( parent_path != NULL ) && ( parent_path_size > 0 ) ) { if( memory_copy( safe_path_hint->path, parent_path, parent_path_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy parent path to path.", function ); goto on_error; } safe_path_hint->path[ parent_path_size - 1 ] = '\\'; } if( name_size > 0 ) { if( libfsntfs_file_name_attribute_get_utf8_name( attribute, &( safe_path_hint->path[ parent_path_size ] ), name_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 name from $FILE_NAME attribute.", function ); goto on_error; } } if( mft_entry_index == LIBFSNTFS_MFT_ENTRY_INDEX_ROOT_DIRECTORY ) { safe_path_hint->path[ 0 ] = '\\'; } ( (libfsntfs_internal_attribute_t *) attribute )->path_hint = safe_path_hint; } *path_hint = ( (libfsntfs_internal_attribute_t *) attribute )->path_hint; return( 1 ); on_error: if( safe_path_hint != NULL ) { libfsntfs_path_hint_free( &safe_path_hint, NULL ); } if( file_name_values != NULL ) { libfsntfs_file_name_values_free( &file_name_values, NULL ); } return( -1 ); } /* Retrieves the size of the UTF-8 encoded path hint for a specific $FILE_NAME attribute * The returned size includes the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_utf8_path_hint_size( libfsntfs_file_entry_t *file_entry, int attribute_index, size_t *utf8_string_size, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; libfsntfs_path_hint_t *path_hint = NULL; static char *function = "libfsntfs_file_entry_get_utf8_path_hint_size"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_internal_file_entry_get_path_hint( internal_file_entry, attribute_index, &path_hint, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve path hint.", function ); result = -1; } else { if( libfsntfs_path_hint_get_utf8_path_size( path_hint, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-8 path hint.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the UTF-8 encoded path hint * The size should include the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_utf8_path_hint( libfsntfs_file_entry_t *file_entry, int attribute_index, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; libfsntfs_path_hint_t *path_hint = NULL; static char *function = "libfsntfs_file_entry_get_utf8_path_hint"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_internal_file_entry_get_path_hint( internal_file_entry, attribute_index, &path_hint, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve path hint.", function ); result = -1; } else { if( libfsntfs_path_hint_get_utf8_path( path_hint, utf8_string, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 path hint.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the size of the UTF-16 encoded path hint for a specific $FILE_NAME attribute * The returned size includes the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_utf16_path_hint_size( libfsntfs_file_entry_t *file_entry, int attribute_index, size_t *utf16_string_size, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; libfsntfs_path_hint_t *path_hint = NULL; static char *function = "libfsntfs_file_entry_get_utf16_path_hint_size"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_internal_file_entry_get_path_hint( internal_file_entry, attribute_index, &path_hint, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve path hint.", function ); result = -1; } else { if( libfsntfs_path_hint_get_utf16_path_size( path_hint, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-16 path hint.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the UTF-16 encoded path hint * The size should include the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_utf16_path_hint( libfsntfs_file_entry_t *file_entry, int attribute_index, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; libfsntfs_path_hint_t *path_hint = NULL; static char *function = "libfsntfs_file_entry_get_utf16_path_hint"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_internal_file_entry_get_path_hint( internal_file_entry, attribute_index, &path_hint, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve path hint.", function ); result = -1; } else { if( libfsntfs_path_hint_get_utf16_path( path_hint, utf16_string, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 path hint.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the size of the UTF-8 encoded symbolic link target * The returned size includes the end of string character * This value is retrieved from a symbolic link $REPARSE_POINT attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_utf8_symbolic_link_target_size( libfsntfs_file_entry_t *file_entry, size_t *utf8_string_size, libcerror_error_t **error ) { libfsntfs_attribute_t *reparse_point_attribute = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_utf8_symbolic_link_target_size"; uint32_t reparse_point_tag = 0; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_file_entry_get_reparse_point_attribute( internal_file_entry, internal_file_entry->mft_entry, &reparse_point_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve reparse point attribute.", function ); result = -1; } else if( result != 0 ) { result = libfsntfs_reparse_point_attribute_get_tag( reparse_point_attribute, &reparse_point_tag, error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-8 substitute name from reparse point attribute.", function ); result = -1; } if( reparse_point_tag == 0xa000000c ) { result = libfsntfs_reparse_point_attribute_get_utf8_substitute_name_size( reparse_point_attribute, utf8_string_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-8 substitute name from reparse point attribute.", function ); result = -1; } } else { result = 0; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the UTF-8 encoded symbolic link target * The size should include the end of string character * This value is retrieved from a symbolic link $REPARSE_POINT attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_utf8_symbolic_link_target( libfsntfs_file_entry_t *file_entry, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { libfsntfs_attribute_t *reparse_point_attribute = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_utf8_symbolic_link_target"; uint32_t reparse_point_tag = 0; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_file_entry_get_reparse_point_attribute( internal_file_entry, internal_file_entry->mft_entry, &reparse_point_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve reparse point attribute.", function ); result = -1; } else if( result != 0 ) { result = libfsntfs_reparse_point_attribute_get_tag( reparse_point_attribute, &reparse_point_tag, error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-8 substitute name from reparse point attribute.", function ); result = -1; } if( reparse_point_tag == 0xa000000c ) { result = libfsntfs_reparse_point_attribute_get_utf8_substitute_name( reparse_point_attribute, utf8_string, utf8_string_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 substitute name from reparse point attribute.", function ); result = -1; } } else { result = 0; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the size of the UTF-16 encoded symbolic link target * The returned size includes the end of string character * This value is retrieved from a symbolic link $REPARSE_POINT attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_utf16_symbolic_link_target_size( libfsntfs_file_entry_t *file_entry, size_t *utf16_string_size, libcerror_error_t **error ) { libfsntfs_attribute_t *reparse_point_attribute = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_utf16_symbolic_link_target_size"; uint32_t reparse_point_tag = 0; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_file_entry_get_reparse_point_attribute( internal_file_entry, internal_file_entry->mft_entry, &reparse_point_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve reparse point attribute.", function ); result = -1; } else if( result != 0 ) { result = libfsntfs_reparse_point_attribute_get_tag( reparse_point_attribute, &reparse_point_tag, error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-8 substitute name from reparse point attribute.", function ); result = -1; } if( reparse_point_tag == 0xa000000c ) { result = libfsntfs_reparse_point_attribute_get_utf16_substitute_name_size( reparse_point_attribute, utf16_string_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-16 substitute name from reparse point attribute.", function ); result = -1; } } else { result = 0; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the UTF-16 encoded symbolic link target * The size should include the end of string character * This value is retrieved from a symbolic link $REPARSE_POINT attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_utf16_symbolic_link_target( libfsntfs_file_entry_t *file_entry, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { libfsntfs_attribute_t *reparse_point_attribute = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_utf16_symbolic_link_target"; uint32_t reparse_point_tag = 0; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_file_entry_get_reparse_point_attribute( internal_file_entry, internal_file_entry->mft_entry, &reparse_point_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve reparse point attribute.", function ); result = -1; } else if( result != 0 ) { result = libfsntfs_reparse_point_attribute_get_tag( reparse_point_attribute, &reparse_point_tag, error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-8 substitute name from reparse point attribute.", function ); result = -1; } if( reparse_point_tag == 0xa000000c ) { result = libfsntfs_reparse_point_attribute_get_utf16_substitute_name( reparse_point_attribute, utf16_string, utf16_string_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 substitute name from reparse point attribute.", function ); result = -1; } } else { result = 0; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the security descriptor (data) size * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_security_descriptor_size( libfsntfs_file_entry_t *file_entry, size_t *data_size, libcerror_error_t **error ) { libfsntfs_attribute_t *security_descriptor_attribute = NULL; libfsntfs_attribute_t *standard_information_attribute = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; libfsntfs_security_descriptor_values_t *security_descriptor_values = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; static char *function = "libfsntfs_file_entry_get_security_descriptor_size"; uint32_t security_descriptor_identifier = 0; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; /* TODO add thread lock suport */ result = libfsntfs_internal_file_entry_get_security_descriptor_attribute( internal_file_entry, &security_descriptor_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security descriptor attribute.", function ); return( -1 ); } else if( result != 0 ) { if( libfsntfs_internal_attribute_get_value( (libfsntfs_internal_attribute_t *) security_descriptor_attribute, (intptr_t **) &security_descriptor_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security descriptor attribute value.", function ); goto on_error; } } else { result = libfsntfs_internal_file_entry_get_standard_information_attribute( internal_file_entry, &standard_information_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve standard information attribute.", function ); return( -1 ); } else if( result == 0 ) { return( 0 ); } if( internal_file_entry->security_descriptor_values == NULL ) { if( libfsntfs_internal_attribute_get_value( (libfsntfs_internal_attribute_t *) standard_information_attribute, (intptr_t **) &standard_information_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve standard information attribute value.", function ); goto on_error; } if( libfsntfs_standard_information_values_get_security_descriptor_identifier( standard_information_values, &security_descriptor_identifier, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security descriptor identifier from standard information attribute.", function ); goto on_error; } result = libfsntfs_file_system_get_security_descriptor_values_by_identifier( internal_file_entry->file_system, internal_file_entry->file_io_handle, security_descriptor_identifier, &( internal_file_entry->security_descriptor_values ), error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security descriptor from index for identifier: %" PRIu32 ".", function, security_descriptor_identifier ); goto on_error; } else if( result == 0 ) { return( 0 ); } /* file_entry takes over management of security_descriptor_values */ } security_descriptor_values = internal_file_entry->security_descriptor_values; } result = libfsntfs_security_descriptor_values_get_data_size( security_descriptor_values, data_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security descriptor data size.", function ); goto on_error; } return( result ); on_error: if( internal_file_entry->security_descriptor_values != NULL ) { libfsntfs_security_descriptor_values_free( &( internal_file_entry->security_descriptor_values ), NULL ); } return( -1 ); } /* Retrieves the security descriptor (data) * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_entry_get_security_descriptor( libfsntfs_file_entry_t *file_entry, uint8_t *data, size_t data_size, libcerror_error_t **error ) { libfsntfs_attribute_t *security_descriptor_attribute = NULL; libfsntfs_attribute_t *standard_information_attribute = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; libfsntfs_security_descriptor_values_t *security_descriptor_values = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; static char *function = "libfsntfs_file_entry_get_security_descriptor"; uint32_t security_descriptor_identifier = 0; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; /* TODO add thread lock suport */ result = libfsntfs_internal_file_entry_get_security_descriptor_attribute( internal_file_entry, &security_descriptor_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security descriptor attribute.", function ); return( -1 ); } else if( result != 0 ) { if( libfsntfs_internal_attribute_get_value( (libfsntfs_internal_attribute_t *) security_descriptor_attribute, (intptr_t **) &security_descriptor_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security descriptor attribute value.", function ); goto on_error; } } else { result = libfsntfs_internal_file_entry_get_standard_information_attribute( internal_file_entry, &standard_information_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve standard information attribute.", function ); return( -1 ); } else if( result == 0 ) { return( 0 ); } if( internal_file_entry->security_descriptor_values == NULL ) { if( libfsntfs_internal_attribute_get_value( (libfsntfs_internal_attribute_t *) standard_information_attribute, (intptr_t **) &standard_information_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve standard information attribute value.", function ); goto on_error; } if( libfsntfs_standard_information_values_get_security_descriptor_identifier( standard_information_values, &security_descriptor_identifier, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security descriptor identifier from standard information attribute.", function ); goto on_error; } result = libfsntfs_file_system_get_security_descriptor_values_by_identifier( internal_file_entry->file_system, internal_file_entry->file_io_handle, security_descriptor_identifier, &( internal_file_entry->security_descriptor_values ), error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security descriptor from index for identifier: %" PRIu32 ".", function, security_descriptor_identifier ); goto on_error; } else if( result == 0 ) { return( 0 ); } /* file_entry takes over management of security_descriptor_values */ } security_descriptor_values = internal_file_entry->security_descriptor_values; } result = libfsntfs_security_descriptor_values_get_data( security_descriptor_values, data, data_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security descriptor data.", function ); goto on_error; } return( result ); on_error: if( internal_file_entry->security_descriptor_values != NULL ) { libfsntfs_security_descriptor_values_free( &( internal_file_entry->security_descriptor_values ), NULL ); } return( -1 ); } /* Retrieves the number of attributes * Returns 1 if successful or -1 on error */ int libfsntfs_file_entry_get_number_of_attributes( libfsntfs_file_entry_t *file_entry, int *number_of_attributes, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_number_of_attributes"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_entry_get_number_of_attributes( internal_file_entry->mft_entry, number_of_attributes, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of attributes.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the attribute for the specific index * Returns 1 if successful or -1 on error */ int libfsntfs_file_entry_get_attribute_by_index( libfsntfs_file_entry_t *file_entry, int attribute_index, libfsntfs_attribute_t **attribute, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_attribute_by_index"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( *attribute != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid attribute value already set.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif if( libfsntfs_internal_file_entry_get_attribute_by_index( internal_file_entry, internal_file_entry->mft_entry, attribute_index, attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d.", function, attribute_index ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Determines if the file entry has a $I30 entry * Returns 1 if the file entry has a $I30 entry, 0 if not or -1 on error */ int libfsntfs_file_entry_has_i30_entry( libfsntfs_file_entry_t *file_entry, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_has_i30_entry"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( internal_file_entry->directory_entry != NULL ) { result = 1; } return( result ); } /* Determines if the file entry has the directory entries ($I30) index * Returns 1 if the file entry has a directory entries index, 0 if not or -1 on error */ int libfsntfs_file_entry_has_directory_entries_index( libfsntfs_file_entry_t *file_entry, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_has_directory_entries_index"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif result = libfsntfs_mft_entry_has_directory_entries_index( internal_file_entry->mft_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if MFT entry has an directory entries index.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Determines if the file entry has a default data stream (nameless $DATA attribute) * Returns 1 if the file entry has a default data stream, 0 if not or -1 on error */ int libfsntfs_file_entry_has_default_data_stream( libfsntfs_file_entry_t *file_entry, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_has_default_data_stream"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( internal_file_entry->mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid file entry - missing MFT entry.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_file_entry->mft_entry->data_attribute != NULL ) { result = 1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Determines if the file entry is a symbolic link * Returns 1 if the file entry is a symbolic link, 0 if not or -1 on error */ int libfsntfs_file_entry_is_symbolic_link( libfsntfs_file_entry_t *file_entry, libcerror_error_t **error ) { libfsntfs_attribute_t *reparse_point_attribute = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_is_symbolic_link"; uint32_t reparse_point_tag = 0; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif result = libfsntfs_internal_file_entry_get_reparse_point_attribute( internal_file_entry, internal_file_entry->mft_entry, &reparse_point_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve reparse point attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_reparse_point_attribute_get_tag( reparse_point_attribute, &reparse_point_tag, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve tag from reparse point attribute.", function ); result = -1; } if( reparse_point_tag == 0xa000000cUL ) { result = 1; } else { result = 0; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the number of alternate data streams * Returns 1 if successful or -1 on error */ int libfsntfs_file_entry_get_number_of_alternate_data_streams( libfsntfs_file_entry_t *file_entry, int *number_of_alternate_data_streams, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_number_of_alternate_data_streams"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_entry_get_number_of_alternate_data_attributes( internal_file_entry->mft_entry, number_of_alternate_data_streams, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of alternate data attributes.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the alternate data stream for the specific index * Returns 1 if successful or -1 on error */ int libfsntfs_file_entry_get_alternate_data_stream_by_index( libfsntfs_file_entry_t *file_entry, int alternate_data_stream_index, libfsntfs_data_stream_t **alternate_data_stream, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; libfsntfs_mft_attribute_t *data_attribute = NULL; static char *function = "libfsntfs_file_entry_get_alternate_data_stream_by_index"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( alternate_data_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid alternate data stream.", function ); return( -1 ); } if( *alternate_data_stream != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid alternate data stream value already set.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_mft_entry_get_alternate_data_attribute_by_index( internal_file_entry->mft_entry, alternate_data_stream_index, &data_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve alternate data attribute: %d.", function, alternate_data_stream_index ); result = -1; } if( result == 1 ) { if( libfsntfs_data_stream_initialize( alternate_data_stream, internal_file_entry->io_handle, internal_file_entry->file_io_handle, data_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create alternate data stream: %d.", function, alternate_data_stream_index ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Determines if there is an alternate data stream for an UTF-8 encoded name * Returns 1 if available, 0 if not or -1 on error */ int libfsntfs_file_entry_has_alternate_data_stream_by_utf8_name( libfsntfs_file_entry_t *file_entry, const uint8_t *utf8_string, size_t utf8_string_length, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; libfsntfs_mft_attribute_t *data_attribute = NULL; static char *function = "libfsntfs_file_entry_has_alternate_data_stream_by_utf8_name"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif result = libfsntfs_mft_entry_get_alternate_data_attribute_by_utf8_name( internal_file_entry->mft_entry, utf8_string, utf8_string_length, &data_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve alternate data attribute.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Determines if there is an alternate data stream for an UTF-8 encoded name * Returns 1 if available, 0 if not or -1 on error */ int libfsntfs_file_entry_has_alternate_data_stream_by_utf16_name( libfsntfs_file_entry_t *file_entry, const uint16_t *utf16_string, size_t utf16_string_length, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; libfsntfs_mft_attribute_t *data_attribute = NULL; static char *function = "libfsntfs_file_entry_has_alternate_data_stream_by_utf16_name"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif result = libfsntfs_mft_entry_get_alternate_data_attribute_by_utf16_name( internal_file_entry->mft_entry, utf16_string, utf16_string_length, &data_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve alternate data attribute.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the alternate data stream for an UTF-8 encoded name * Returns 1 if successful, 0 if no such file entry or -1 on error */ int libfsntfs_file_entry_get_alternate_data_stream_by_utf8_name( libfsntfs_file_entry_t *file_entry, const uint8_t *utf8_string, size_t utf8_string_length, libfsntfs_data_stream_t **alternate_data_stream, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; libfsntfs_mft_attribute_t *data_attribute = NULL; static char *function = "libfsntfs_file_entry_get_alternate_data_stream_by_utf8_name"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( alternate_data_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid alternate data stream.", function ); return( -1 ); } if( *alternate_data_stream != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid alternate data stream value already set.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif result = libfsntfs_mft_entry_get_alternate_data_attribute_by_utf8_name( internal_file_entry->mft_entry, utf8_string, utf8_string_length, &data_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve alternate data attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_data_stream_initialize( alternate_data_stream, internal_file_entry->io_handle, internal_file_entry->file_io_handle, data_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create alternate data stream.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the alternate data stream for an UTF-16 encoded name * Returns 1 if successful, 0 if no such file entry or -1 on error */ int libfsntfs_file_entry_get_alternate_data_stream_by_utf16_name( libfsntfs_file_entry_t *file_entry, const uint16_t *utf16_string, size_t utf16_string_length, libfsntfs_data_stream_t **alternate_data_stream, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; libfsntfs_mft_attribute_t *data_attribute = NULL; static char *function = "libfsntfs_file_entry_get_alternate_data_stream_by_utf16_name"; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( alternate_data_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid alternate data stream.", function ); return( -1 ); } if( *alternate_data_stream != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid alternate data stream value already set.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif result = libfsntfs_mft_entry_get_alternate_data_attribute_by_utf16_name( internal_file_entry->mft_entry, utf16_string, utf16_string_length, &data_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve alternate data attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_data_stream_initialize( alternate_data_stream, internal_file_entry->io_handle, internal_file_entry->file_io_handle, data_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create alternate data stream.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the number of sub file entries * Returns 1 if successful or -1 on error */ int libfsntfs_file_entry_get_number_of_sub_file_entries( libfsntfs_file_entry_t *file_entry, int *number_of_sub_file_entries, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_number_of_sub_file_entries"; int result = 1; int safe_number_of_sub_file_entries = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( number_of_sub_file_entries == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid number of sub file entries.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_file_entry->directory_entries_tree != NULL ) { if( libfsntfs_directory_entries_tree_get_number_of_entries( internal_file_entry->directory_entries_tree, &safe_number_of_sub_file_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of entries from directory entries tree.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif if( result == 1 ) { *number_of_sub_file_entries = safe_number_of_sub_file_entries; } return( result ); } /* Retrieves the sub file entry for the specific index * Returns 1 if successful or -1 on error */ int libfsntfs_file_entry_get_sub_file_entry_by_index( libfsntfs_file_entry_t *file_entry, int sub_file_entry_index, libfsntfs_file_entry_t **sub_file_entry, libcerror_error_t **error ) { libfsntfs_directory_entry_t *sub_directory_entry = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_sub_file_entry_by_index"; uint64_t mft_entry_index = 0; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( sub_file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid sub file entry.", function ); return( -1 ); } if( *sub_file_entry != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid sub file entry value already set.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_directory_entries_tree_get_entry_by_index( internal_file_entry->directory_entries_tree, internal_file_entry->file_io_handle, sub_file_entry_index, &sub_directory_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry: %d from directory entries tree.", function, sub_file_entry_index ); result = -1; } else { if( libfsntfs_directory_entry_get_mft_entry_index( sub_directory_entry, &mft_entry_index, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry index.", function ); result = -1; } /* sub_file_entry takes over management of sub_directory_entry */ else if( libfsntfs_file_entry_initialize( sub_file_entry, internal_file_entry->io_handle, internal_file_entry->file_io_handle, internal_file_entry->file_system, mft_entry_index, sub_directory_entry, internal_file_entry->flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create sub file entry: %d with MFT entry: %" PRIu64 ".", function, sub_file_entry_index, mft_entry_index ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); result = -1; } #endif if( result == -1 ) { if( sub_directory_entry != NULL ) { libfsntfs_directory_entry_free( &sub_directory_entry, NULL ); } } return( result ); } /* Retrieves the sub file entry for an UTF-8 encoded name * Returns 1 if successful, 0 if no such file entry or -1 on error */ int libfsntfs_file_entry_get_sub_file_entry_by_utf8_name( libfsntfs_file_entry_t *file_entry, const uint8_t *utf8_string, size_t utf8_string_length, libfsntfs_file_entry_t **sub_file_entry, libcerror_error_t **error ) { libfsntfs_directory_entry_t *sub_directory_entry = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_sub_file_entry_by_utf8_name"; uint64_t mft_entry_index = 0; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( sub_file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid sub file entry.", function ); return( -1 ); } if( *sub_file_entry != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid sub file entry value already set.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif result = libfsntfs_directory_entries_tree_get_entry_by_utf8_name( internal_file_entry->directory_entries_tree, internal_file_entry->file_io_handle, utf8_string, utf8_string_length, &sub_directory_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve directory entry.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_directory_entry_get_mft_entry_index( sub_directory_entry, &mft_entry_index, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry index.", function ); result = -1; } /* sub_file_entry takes over management of sub_directory_entry */ else if( libfsntfs_file_entry_initialize( sub_file_entry, internal_file_entry->io_handle, internal_file_entry->file_io_handle, internal_file_entry->file_system, mft_entry_index, sub_directory_entry, internal_file_entry->flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create sub file entry with MFT entry: %" PRIu64 ".", function, mft_entry_index ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); result = -1; } #endif if( result == -1 ) { if( sub_directory_entry != NULL ) { libfsntfs_directory_entry_free( &sub_directory_entry, NULL ); } } return( result ); } /* Retrieves the sub file entry for an UTF-16 encoded name * Returns 1 if successful, 0 if no such file entry or -1 on error */ int libfsntfs_file_entry_get_sub_file_entry_by_utf16_name( libfsntfs_file_entry_t *file_entry, const uint16_t *utf16_string, size_t utf16_string_length, libfsntfs_file_entry_t **sub_file_entry, libcerror_error_t **error ) { libfsntfs_directory_entry_t *sub_directory_entry = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_sub_file_entry_by_utf16_name"; uint64_t mft_entry_index = 0; int result = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( sub_file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid sub file entry.", function ); return( -1 ); } if( *sub_file_entry != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid sub file entry value already set.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif result = libfsntfs_directory_entries_tree_get_entry_by_utf16_name( internal_file_entry->directory_entries_tree, internal_file_entry->file_io_handle, utf16_string, utf16_string_length, &sub_directory_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve directory entry.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_directory_entry_get_mft_entry_index( sub_directory_entry, &mft_entry_index, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry index.", function ); result = -1; } /* sub_file_entry takes over management of sub_directory_entry */ else if( libfsntfs_file_entry_initialize( sub_file_entry, internal_file_entry->io_handle, internal_file_entry->file_io_handle, internal_file_entry->file_system, mft_entry_index, sub_directory_entry, internal_file_entry->flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create sub file entry with MFT entry: %" PRIu64 ".", function, mft_entry_index ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); result = -1; } #endif if( result == -1 ) { if( sub_directory_entry != NULL ) { libfsntfs_directory_entry_free( &sub_directory_entry, NULL ); } } return( result ); } /* Reads data at the current offset from the default data stream (nameless $DATA attribute) * Returns the number of bytes read or -1 on error */ ssize_t libfsntfs_file_entry_read_buffer( libfsntfs_file_entry_t *file_entry, void *buffer, size_t buffer_size, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_read_buffer"; ssize_t read_count = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( internal_file_entry->data_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid file entry - missing data attribute.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif read_count = libfdata_stream_read_buffer( internal_file_entry->data_cluster_block_stream, (intptr_t *) internal_file_entry->file_io_handle, buffer, buffer_size, 0, error ); if( read_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read from data cluster block stream.", function ); read_count = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( read_count ); } /* Reads data at a specific offset from the default data stream (nameless $DATA attribute) * Returns the number of bytes read or -1 on error */ ssize_t libfsntfs_file_entry_read_buffer_at_offset( libfsntfs_file_entry_t *file_entry, void *buffer, size_t buffer_size, off64_t offset, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_read_buffer_at_offset"; ssize_t read_count = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( internal_file_entry->data_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid file entry - missing data attribute.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif read_count = libfdata_stream_read_buffer_at_offset( internal_file_entry->data_cluster_block_stream, (intptr_t *) internal_file_entry->file_io_handle, buffer, buffer_size, offset, 0, error ); if( read_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read from data cluster block stream.", function ); read_count = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( read_count ); } /* Seeks a certain offset in the default data stream (nameless $DATA attribute) * Returns the offset if seek is successful or -1 on error */ off64_t libfsntfs_file_entry_seek_offset( libfsntfs_file_entry_t *file_entry, off64_t offset, int whence, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_seek_offset"; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( internal_file_entry->data_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid file entry - missing data attribute.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif offset = libfdata_stream_seek_offset( internal_file_entry->data_cluster_block_stream, offset, whence, error ); if( offset == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek offset in data cluster block stream.", function ); offset = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( offset ); } /* Retrieves the current offset of the default data stream (nameless $DATA attribute) * Returns the offset if successful or -1 on error */ int libfsntfs_file_entry_get_offset( libfsntfs_file_entry_t *file_entry, off64_t *offset, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_offset"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( internal_file_entry->data_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid file entry - missing data attribute.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfdata_stream_get_offset( internal_file_entry->data_cluster_block_stream, offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve offset from data cluster block stream.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the size of the default data stream (nameless $DATA attribute) * Returns 1 if successful or -1 on error */ int libfsntfs_file_entry_get_size( libfsntfs_file_entry_t *file_entry, size64_t *size, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_size"; size64_t safe_size = 0; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid size.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_file_entry->data_cluster_block_stream != NULL ) { if( libfdata_stream_get_size( internal_file_entry->data_cluster_block_stream, &safe_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data attribute data size.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif if( result == 1 ) { *size = safe_size; } return( result ); } /* Retrieves the number of extents (decoded data runs) of the default data stream (nameless $DATA attribute) * Returns 1 if successful or -1 on error */ int libfsntfs_file_entry_get_number_of_extents( libfsntfs_file_entry_t *file_entry, int *number_of_extents, libcerror_error_t **error ) { libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_number_of_extents"; int result = 1; int safe_number_of_extents = 0; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; if( number_of_extents == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid number of extents.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_file_entry->extents_array != NULL ) { if( libcdata_array_get_number_of_entries( internal_file_entry->extents_array, &safe_number_of_extents, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of extents.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif if( result == 1 ) { *number_of_extents = safe_number_of_extents; } return( result ); } /* Retrieves a specific extent (decoded data run) of the default data stream (nameless $DATA attribute) * Returns 1 if successful or -1 on error */ int libfsntfs_file_entry_get_extent_by_index( libfsntfs_file_entry_t *file_entry, int extent_index, off64_t *extent_offset, size64_t *extent_size, uint32_t *extent_flags, libcerror_error_t **error ) { libfsntfs_extent_t *data_extent = NULL; libfsntfs_internal_file_entry_t *internal_file_entry = NULL; static char *function = "libfsntfs_file_entry_get_extent_by_index"; int result = 1; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } internal_file_entry = (libfsntfs_internal_file_entry_t *) file_entry; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libcdata_array_get_entry_by_index( internal_file_entry->extents_array, extent_index, (intptr_t **) &data_extent, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve extent: %d.", function, extent_index ); result = -1; } if( result == 1 ) { if( libfsntfs_extent_get_values( data_extent, extent_offset, extent_size, extent_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve extent: %d values.", function, extent_index ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_file_entry->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } ================================================ FILE: libfsntfs/libfsntfs_file_entry.h ================================================ /* * File entry functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_FILE_ENTRY_H ) #define _LIBFSNTFS_FILE_ENTRY_H #include #include #include "libfsntfs_directory_entries_tree.h" #include "libfsntfs_directory_entry.h" #include "libfsntfs_extern.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_file_system.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_mft_entry.h" #include "libfsntfs_path_hint.h" #include "libfsntfs_security_descriptor_values.h" #include "libfsntfs_types.h" #include "libfsntfs_volume.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_internal_file_entry libfsntfs_internal_file_entry_t; struct libfsntfs_internal_file_entry { /* The IO handle */ libfsntfs_io_handle_t *io_handle; /* The file IO handle */ libbfio_handle_t *file_io_handle; /* The file system */ libfsntfs_file_system_t *file_system; /* The MFT entry */ libfsntfs_mft_entry_t *mft_entry; /* The directory entry */ libfsntfs_directory_entry_t *directory_entry; /* The directory entries tree */ libfsntfs_directory_entries_tree_t *directory_entries_tree; /* The security descriptor values */ libfsntfs_security_descriptor_values_t *security_descriptor_values; /* The default (nameless) $DATA attribute */ libfsntfs_mft_attribute_t *data_attribute; /* The data extents array */ libcdata_array_t *extents_array; /* The attributes array */ libcdata_array_t *attributes_array; /* The reparse point ($REPARSE_POINT) attribute */ libfsntfs_attribute_t *reparse_point_attribute; /* The security descriptor ($SECURITY_DESCRIPTOR) attribute */ libfsntfs_attribute_t *security_descriptor_attribute; /* The standard information ($STANDARD_INFORMATION) attribute */ libfsntfs_attribute_t *standard_information_attribute; /* The default (nameless) $DATA attribute cluster block stream */ libfdata_stream_t *data_cluster_block_stream; /* The flags */ uint8_t flags; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) /* The read/write lock */ libcthreads_read_write_lock_t *read_write_lock; #endif }; int libfsntfs_file_entry_initialize( libfsntfs_file_entry_t **file_entry, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfsntfs_file_system_t *file_system, uint64_t mft_entry_index, libfsntfs_directory_entry_t *directory_entry, uint8_t flags, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_free( libfsntfs_file_entry_t **file_entry, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_is_empty( libfsntfs_file_entry_t *file_entry, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_is_allocated( libfsntfs_file_entry_t *file_entry, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_is_corrupted( libfsntfs_file_entry_t *file_entry, libcerror_error_t **error ); int libfsntfs_internal_file_entry_get_attribute_by_index( libfsntfs_internal_file_entry_t *internal_file_entry, libfsntfs_mft_entry_t *mft_entry, int attribute_index, libfsntfs_attribute_t **attribute, libcerror_error_t **error ); int libfsntfs_internal_file_entry_get_reparse_point_attribute( libfsntfs_internal_file_entry_t *internal_file_entry, libfsntfs_mft_entry_t *mft_entry, libfsntfs_attribute_t **attribute, libcerror_error_t **error ); int libfsntfs_internal_file_entry_get_security_descriptor_attribute( libfsntfs_internal_file_entry_t *internal_file_entry, libfsntfs_attribute_t **attribute, libcerror_error_t **error ); int libfsntfs_internal_file_entry_get_standard_information_attribute( libfsntfs_internal_file_entry_t *internal_file_entry, libfsntfs_attribute_t **attribute, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_file_reference( libfsntfs_file_entry_t *file_entry, uint64_t *file_reference, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_base_record_file_reference( libfsntfs_file_entry_t *file_entry, uint64_t *file_reference, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_parent_file_reference( libfsntfs_file_entry_t *file_entry, uint64_t *parent_file_reference, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_parent_file_reference_by_attribute_index( libfsntfs_file_entry_t *file_entry, int attribute_index, uint64_t *file_reference, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_journal_sequence_number( libfsntfs_file_entry_t *file_entry, uint64_t *journal_sequence_number, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_creation_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_modification_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_access_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_entry_modification_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_file_attribute_flags( libfsntfs_file_entry_t *file_entry, uint32_t *file_attribute_flags, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_i30_file_reference( libfsntfs_file_entry_t *file_entry, uint64_t *file_reference, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_i30_creation_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_i30_modification_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_i30_access_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_i30_entry_modification_time( libfsntfs_file_entry_t *file_entry, uint64_t *filetime, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_i30_size( libfsntfs_file_entry_t *file_entry, uint64_t *size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_i30_file_attribute_flags( libfsntfs_file_entry_t *file_entry, uint32_t *file_attribute_flags, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf8_name_size( libfsntfs_file_entry_t *file_entry, size_t *utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf8_name( libfsntfs_file_entry_t *file_entry, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf16_name_size( libfsntfs_file_entry_t *file_entry, size_t *utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf16_name( libfsntfs_file_entry_t *file_entry, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_name_attribute_index( libfsntfs_file_entry_t *file_entry, int *attribute_index, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf8_name_size_by_attribute_index( libfsntfs_file_entry_t *file_entry, int attribute_index, size_t *utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf8_name_by_attribute_index( libfsntfs_file_entry_t *file_entry, int attribute_index, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf16_name_size_by_attribute_index( libfsntfs_file_entry_t *file_entry, int attribute_index, size_t *utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf16_name_by_attribute_index( libfsntfs_file_entry_t *file_entry, int attribute_index, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); int libfsntfs_internal_file_entry_get_path_hint( libfsntfs_internal_file_entry_t *internal_file_entry, int attribute_index, libfsntfs_path_hint_t **path_hint, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf8_path_hint_size( libfsntfs_file_entry_t *file_entry, int attribute_index, size_t *utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf8_path_hint( libfsntfs_file_entry_t *file_entry, int attribute_index, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf16_path_hint_size( libfsntfs_file_entry_t *file_entry, int attribute_index, size_t *utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf16_path_hint( libfsntfs_file_entry_t *file_entry, int attribute_index, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf8_symbolic_link_target_size( libfsntfs_file_entry_t *file_entry, size_t *utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf8_symbolic_link_target( libfsntfs_file_entry_t *file_entry, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf16_symbolic_link_target_size( libfsntfs_file_entry_t *file_entry, size_t *utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_utf16_symbolic_link_target( libfsntfs_file_entry_t *file_entry, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_security_descriptor_size( libfsntfs_file_entry_t *file_entry, size_t *data_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_security_descriptor( libfsntfs_file_entry_t *file_entry, uint8_t *data, size_t data_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_number_of_attributes( libfsntfs_file_entry_t *file_entry, int *number_of_attributes, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_attribute_by_index( libfsntfs_file_entry_t *file_entry, int attribute_index, libfsntfs_attribute_t **attribute, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_has_directory_entries_index( libfsntfs_file_entry_t *file_entry, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_has_default_data_stream( libfsntfs_file_entry_t *file_entry, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_has_i30_entry( libfsntfs_file_entry_t *file_entry, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_is_symbolic_link( libfsntfs_file_entry_t *file_entry, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_number_of_alternate_data_streams( libfsntfs_file_entry_t *file_entry, int *number_of_alternate_data_streams, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_alternate_data_stream_by_index( libfsntfs_file_entry_t *file_entry, int alternate_data_stream_index, libfsntfs_data_stream_t **alternate_data_stream, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_has_alternate_data_stream_by_utf8_name( libfsntfs_file_entry_t *file_entry, const uint8_t *utf8_string, size_t utf8_string_length, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_has_alternate_data_stream_by_utf16_name( libfsntfs_file_entry_t *file_entry, const uint16_t *utf16_string, size_t utf16_string_length, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_alternate_data_stream_by_utf8_name( libfsntfs_file_entry_t *file_entry, const uint8_t *utf8_string, size_t utf8_string_length, libfsntfs_data_stream_t **alternate_data_stream, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_alternate_data_stream_by_utf16_name( libfsntfs_file_entry_t *file_entry, const uint16_t *utf16_string, size_t utf16_string_length, libfsntfs_data_stream_t **alternate_data_stream, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_number_of_sub_file_entries( libfsntfs_file_entry_t *file_entry, int *number_of_sub_entries, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_sub_file_entry_by_index( libfsntfs_file_entry_t *file_entry, int sub_file_entry_index, libfsntfs_file_entry_t **sub_file_entry, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_sub_file_entry_by_utf8_name( libfsntfs_file_entry_t *file_entry, const uint8_t *utf8_string, size_t utf8_string_length, libfsntfs_file_entry_t **sub_file_entry, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_sub_file_entry_by_utf16_name( libfsntfs_file_entry_t *file_entry, const uint16_t *utf16_string, size_t utf16_string_length, libfsntfs_file_entry_t **sub_file_entry, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ ssize_t libfsntfs_file_entry_read_buffer( libfsntfs_file_entry_t *file_entry, void *buffer, size_t buffer_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ ssize_t libfsntfs_file_entry_read_buffer_at_offset( libfsntfs_file_entry_t *file_entry, void *buffer, size_t buffer_size, off64_t offset, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ off64_t libfsntfs_file_entry_seek_offset( libfsntfs_file_entry_t *file_entry, off64_t offset, int whence, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_offset( libfsntfs_file_entry_t *file_entry, off64_t *offset, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_size( libfsntfs_file_entry_t *file_entry, size64_t *size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_number_of_extents( libfsntfs_file_entry_t *file_entry, int *number_of_extents, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_entry_get_extent_by_index( libfsntfs_file_entry_t *file_entry, int extent_index, off64_t *extent_offset, size64_t *extent_size, uint32_t *extent_flags, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_FILE_ENTRY_H ) */ ================================================ FILE: libfsntfs/libfsntfs_file_name_attribute.c ================================================ /* * File name attribute ($FILE_NAME) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_attribute.h" #include "libfsntfs_definitions.h" #include "libfsntfs_file_name_attribute.h" #include "libfsntfs_file_name_values.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_types.h" /* Retrieves the parent file reference * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_attribute_get_parent_file_reference( libfsntfs_attribute_t *attribute, uint64_t *parent_file_reference, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_file_name_attribute_get_parent_file_reference"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_parent_file_reference( (libfsntfs_file_name_values_t *) internal_attribute->value, parent_file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve parent file reference.", function ); return( -1 ); } return( 1 ); } /* Retrieves the creation date and time * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_attribute_get_creation_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_file_name_attribute_get_creation_time"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_creation_time( (libfsntfs_file_name_values_t *) internal_attribute->value, filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve creation time.", function ); return( -1 ); } return( 1 ); } /* Retrieves the (file) modification (last written) date and time * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_attribute_get_modification_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_file_name_attribute_get_modification_time"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_modification_time( (libfsntfs_file_name_values_t *) internal_attribute->value, filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve modification time.", function ); return( -1 ); } return( 1 ); } /* Retrieves the access date and time * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_attribute_get_access_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_file_name_attribute_get_access_time"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_access_time( (libfsntfs_file_name_values_t *) internal_attribute->value, filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve access time.", function ); return( -1 ); } return( 1 ); } /* Retrieves the (file system entry) modification date and time * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_attribute_get_entry_modification_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_file_name_attribute_get_entry_modification_time"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_entry_modification_time( (libfsntfs_file_name_values_t *) internal_attribute->value, filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry modification time.", function ); return( -1 ); } return( 1 ); } /* Retrieves the file attribute flags * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_attribute_get_file_attribute_flags( libfsntfs_attribute_t *attribute, uint32_t *file_attribute_flags, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_file_name_attribute_get_file_attribute_flags"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_file_attribute_flags( (libfsntfs_file_name_values_t *) internal_attribute->value, file_attribute_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file attribute flags.", function ); return( -1 ); } return( 1 ); } /* Retrieves the name space * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_attribute_get_name_space( libfsntfs_attribute_t *attribute, uint8_t *name_space, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_file_name_attribute_get_name_space"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_name_space( (libfsntfs_file_name_values_t *) internal_attribute->value, name_space, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve name space.", function ); return( -1 ); } return( 1 ); } /* Retrieves the size of the UTF-8 encoded name * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_attribute_get_utf8_name_size( libfsntfs_attribute_t *attribute, size_t *utf8_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_file_name_attribute_get_utf8_name_size"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_utf8_name_size( (libfsntfs_file_name_values_t *) internal_attribute->value, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-8 name.", function ); return( -1 ); } return( 1 ); } /* Retrieves the UTF-8 encoded name * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_attribute_get_utf8_name( libfsntfs_attribute_t *attribute, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_file_name_attribute_get_utf8_name"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_utf8_name( (libfsntfs_file_name_values_t *) internal_attribute->value, utf8_string, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 name.", function ); return( -1 ); } return( 1 ); } /* Retrieves the size of the UTF-16 encoded name * This function uses UCS-2 (with surrogates) to support characters outside Unicode * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_attribute_get_utf16_name_size( libfsntfs_attribute_t *attribute, size_t *utf16_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_file_name_attribute_get_utf16_name_size"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_utf16_name_size( (libfsntfs_file_name_values_t *) internal_attribute->value, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-16 name.", function ); return( -1 ); } return( 1 ); } /* Retrieves the UTF-16 encoded name * This function uses UCS-2 (with surrogates) to support characters outside Unicode * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_attribute_get_utf16_name( libfsntfs_attribute_t *attribute, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_file_name_attribute_get_utf16_name"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } if( libfsntfs_file_name_values_get_utf16_name( (libfsntfs_file_name_values_t *) internal_attribute->value, utf16_string, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 name.", function ); return( -1 ); } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_file_name_attribute.h ================================================ /* * File name attribute ($FILE_NAME) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_FILE_NAME_ATTRIBUTE_H ) #define _LIBFSNTFS_FILE_NAME_ATTRIBUTE_H #include #include #include "libfsntfs_extern.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_types.h" #if defined( __cplusplus ) extern "C" { #endif LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_parent_file_reference( libfsntfs_attribute_t *attribute, uint64_t *parent_file_reference, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_creation_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_modification_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_access_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_entry_modification_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_file_attribute_flags( libfsntfs_attribute_t *attribute, uint32_t *file_attribute_flags, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_name_space( libfsntfs_attribute_t *attribute, uint8_t *name_space, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_utf8_name_size( libfsntfs_attribute_t *attribute, size_t *utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_utf8_name( libfsntfs_attribute_t *attribute, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_utf16_name_size( libfsntfs_attribute_t *attribute, size_t *utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_file_name_attribute_get_utf16_name( libfsntfs_attribute_t *attribute, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_FILE_NAME_ATTRIBUTE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_file_name_values.c ================================================ /* * File name attribute ($FILE_NAME) values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include "libfsntfs_debug.h" #include "libfsntfs_definitions.h" #include "libfsntfs_file_name_values.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libfdatetime.h" #include "libfsntfs_libuna.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_name.h" #include "fsntfs_file_name.h" /* Creates file name values * Make sure the value file_name_values is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_values_initialize( libfsntfs_file_name_values_t **file_name_values, libcerror_error_t **error ) { static char *function = "libfsntfs_file_name_values_initialize"; if( file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file name values.", function ); return( -1 ); } if( *file_name_values != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file name values value already set.", function ); return( -1 ); } *file_name_values = memory_allocate_structure( libfsntfs_file_name_values_t ); if( *file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create file name values.", function ); goto on_error; } if( memory_set( *file_name_values, 0, sizeof( libfsntfs_file_name_values_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear file name values.", function ); goto on_error; } return( 1 ); on_error: if( *file_name_values != NULL ) { memory_free( *file_name_values ); *file_name_values = NULL; } return( -1 ); } /* Frees file name values * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_values_free( libfsntfs_file_name_values_t **file_name_values, libcerror_error_t **error ) { static char *function = "libfsntfs_file_name_values_free"; if( file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file name values.", function ); return( -1 ); } if( *file_name_values != NULL ) { if( ( *file_name_values )->name != NULL ) { memory_free( ( *file_name_values )->name ); } memory_free( *file_name_values ); *file_name_values = NULL; } return( 1 ); } /* Clones file name values * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_values_clone( libfsntfs_file_name_values_t **destination_file_name_values, libfsntfs_file_name_values_t *source_file_name_values, libcerror_error_t **error ) { static char *function = "libfsntfs_file_name_values_clone"; if( destination_file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file name values.", function ); return( -1 ); } if( *destination_file_name_values != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid destination file name values value already set.", function ); return( -1 ); } if( source_file_name_values == NULL ) { *destination_file_name_values = source_file_name_values; return( 1 ); } *destination_file_name_values = memory_allocate_structure( libfsntfs_file_name_values_t ); if( *destination_file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create destination file name values.", function ); goto on_error; } if( memory_copy( *destination_file_name_values, source_file_name_values, sizeof( libfsntfs_file_name_values_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to copy source file name values to destination.", function ); goto on_error; } ( *destination_file_name_values )->name = NULL; ( *destination_file_name_values )->name_size = 0; if( libfsntfs_file_name_values_set_name( *destination_file_name_values, source_file_name_values->name, source_file_name_values->name_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set destination name.", function ); goto on_error; } return( 1 ); on_error: if( *destination_file_name_values != NULL ) { memory_free( *destination_file_name_values ); *destination_file_name_values = NULL; } return( -1 ); } /* Sets the name * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_values_set_name( libfsntfs_file_name_values_t *file_name_values, const uint8_t *utf16_stream, size_t utf16_stream_size, libcerror_error_t **error ) { static char *function = "libfsntfs_file_name_values_set_name"; if( file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file name values.", function ); return( -1 ); } if( file_name_values->name != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file name values - name value already set.", function ); return( -1 ); } if( utf16_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-16 stream.", function ); return( -1 ); } if( ( utf16_stream_size == 0 ) || ( utf16_stream_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid UTF-16 stream size value out of bounds.", function ); return( -1 ); } file_name_values->name = (uint8_t *) memory_allocate( sizeof( uint8_t ) * (size_t) utf16_stream_size ); if( file_name_values->name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create name.", function ); goto on_error; } if( memory_copy( file_name_values->name, utf16_stream, utf16_stream_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy name.", function ); goto on_error; } file_name_values->name_size = utf16_stream_size; return( 1 ); on_error: if( file_name_values->name != NULL ) { memory_free( file_name_values->name ); file_name_values->name = NULL; } file_name_values->name_size = 0; return( -1 ); } /* Reads the file name values * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_values_read_data( libfsntfs_file_name_values_t *file_name_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_file_name_values_read_data"; size_t data_offset = 0; uint16_t name_size = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint64_t value_64bit = 0; uint32_t value_32bit = 0; #endif if( file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file name values.", function ); return( -1 ); } if( file_name_values->name != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file name values - name already set.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid data size value exceeds maximum.", function ); return( -1 ); } if( data_size < sizeof( fsntfs_file_name_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: unsupported data size value too small.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: file name data:\n", function ); libcnotify_print_data( data, data_size, 0 ); } #endif byte_stream_copy_to_uint64_little_endian( ( (fsntfs_file_name_t *) data )->parent_file_reference, file_name_values->parent_file_reference ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_file_name_t *) data )->creation_time, file_name_values->creation_time ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_file_name_t *) data )->modification_time, file_name_values->modification_time ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_file_name_t *) data )->access_time, file_name_values->access_time ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_file_name_t *) data )->entry_modification_time, file_name_values->entry_modification_time ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_file_name_t *) data )->data_size, file_name_values->size ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_file_name_t *) data )->file_attribute_flags, file_name_values->file_attribute_flags ); name_size = (uint16_t) ( (fsntfs_file_name_t *) data )->name_size; file_name_values->name_space = ( (fsntfs_file_name_t *) data )->name_space; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: parent file reference\t\t: %" PRIu64 "-%" PRIu64 "\n", function, file_name_values->parent_file_reference & 0xffffffffffffUL, file_name_values->parent_file_reference >> 48 ); if( libfsntfs_debug_print_filetime_value( function, "creation time\t\t\t", ( (fsntfs_file_name_t *) data )->creation_time, 8, LIBFDATETIME_ENDIAN_LITTLE, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print FILETIME value.", function ); goto on_error; } if( libfsntfs_debug_print_filetime_value( function, "modification time\t\t\t", ( (fsntfs_file_name_t *) data )->modification_time, 8, LIBFDATETIME_ENDIAN_LITTLE, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print FILETIME value.", function ); goto on_error; } if( libfsntfs_debug_print_filetime_value( function, "entry modification time\t\t", ( (fsntfs_file_name_t *) data )->entry_modification_time, 8, LIBFDATETIME_ENDIAN_LITTLE, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print FILETIME value.", function ); goto on_error; } if( libfsntfs_debug_print_filetime_value( function, "access time\t\t\t", ( (fsntfs_file_name_t *) data )->access_time, 8, LIBFDATETIME_ENDIAN_LITTLE, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print FILETIME value.", function ); goto on_error; } byte_stream_copy_to_uint64_little_endian( ( (fsntfs_file_name_t *) data )->allocated_data_size, value_64bit ); libcnotify_printf( "%s: allocated data size\t\t: %" PRIu64 "\n", function, value_64bit ); libcnotify_printf( "%s: data size\t\t\t\t: %" PRIu64 "\n", function, file_name_values->size ); libcnotify_printf( "%s: file attribute flags\t\t: 0x%08" PRIx32 "\n", function, file_name_values->file_attribute_flags ); libfsntfs_debug_print_file_attribute_flags( file_name_values->file_attribute_flags ); libcnotify_printf( "\n" ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_file_name_t *) data )->extended_data, value_32bit ); libcnotify_printf( "%s: extended data\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); libcnotify_printf( "%s: name size\t\t\t\t: %" PRIu16 "\n", function, name_size ); libcnotify_printf( "%s: name space\t\t\t: %" PRIu8 " (%s)\n", function, file_name_values->name_space, libfsntfs_debug_print_file_name_attribute_name_space( file_name_values->name_space ) ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ data_offset = sizeof( fsntfs_file_name_t ); if( name_size > 0 ) { name_size *= 2; if( (size_t) name_size > ( data_size - data_offset ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid name size value out of bounds.", function ); goto on_error; } if( libfsntfs_file_name_values_set_name( file_name_values, &( data[ data_offset ] ), (size_t) name_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set name.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( libfsntfs_debug_print_utf16_string_value( function, "name\t\t\t\t", file_name_values->name, file_name_values->name_size, LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print UTF-16 string value.", function ); goto on_error; } libcnotify_printf( "\n" ); } data_offset += file_name_values->name_size; #endif /* defined( HAVE_DEBUG_OUTPUT ) */ /* TODO debug print alignment padding */ } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( data_offset < data_size ) { libcnotify_printf( "%s: trailing data:\n", function ); libcnotify_print_data( &( data[ data_offset ] ), data_size - data_offset, 0 ); } } #endif return( 1 ); on_error: if( file_name_values->name != NULL ) { memory_free( file_name_values->name ); file_name_values->name = NULL; } file_name_values->name_size = 0; return( -1 ); } /* Reads the file name values from an MFT attribute * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_values_read_from_mft_attribute( libfsntfs_file_name_values_t *file_name_values, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ) { uint8_t *data = NULL; static char *function = "libfsntfs_file_name_values_read_from_mft_attribute"; size_t data_size = 0; uint32_t attribute_type = 0; int result = 0; if( file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file name values.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_type( mft_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve type from attribute.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_mft_attribute_data_is_resident( mft_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if attribute data is resident.", function ); return( -1 ); } else if( result == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported non-resident attribute.", function ); return( 1 ); } if( libfsntfs_mft_attribute_get_resident_data( mft_attribute, &data, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve resident data from attribute.", function ); return( -1 ); } if( libfsntfs_file_name_values_read_data( file_name_values, data, data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read file name values.", function ); return( -1 ); } return( 1 ); } /* Retrieves the parent file reference * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_values_get_parent_file_reference( libfsntfs_file_name_values_t *file_name_values, uint64_t *parent_file_reference, libcerror_error_t **error ) { static char *function = "libfsntfs_file_name_values_get_parent_file_reference"; if( file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file name values.", function ); return( -1 ); } if( parent_file_reference == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid parent file reference.", function ); return( -1 ); } *parent_file_reference = file_name_values->parent_file_reference; return( 1 ); } /* Retrieves the creation date and time * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_values_get_creation_time( libfsntfs_file_name_values_t *file_name_values, uint64_t *filetime, libcerror_error_t **error ) { static char *function = "libfsntfs_file_name_values_get_creation_time"; if( file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file name values.", function ); return( -1 ); } if( filetime == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid FILETIME.", function ); return( -1 ); } *filetime = file_name_values->creation_time; return( 1 ); } /* Retrieves the (file) modification (last written) date and time * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_values_get_modification_time( libfsntfs_file_name_values_t *file_name_values, uint64_t *filetime, libcerror_error_t **error ) { static char *function = "libfsntfs_file_name_values_get_modification_time"; if( file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file name values.", function ); return( -1 ); } if( filetime == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid FILETIME.", function ); return( -1 ); } *filetime = file_name_values->modification_time; return( 1 ); } /* Retrieves the access date and time * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_values_get_access_time( libfsntfs_file_name_values_t *file_name_values, uint64_t *filetime, libcerror_error_t **error ) { static char *function = "libfsntfs_file_name_values_get_access_time"; if( file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file name values.", function ); return( -1 ); } if( filetime == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid FILETIME.", function ); return( -1 ); } *filetime = file_name_values->access_time; return( 1 ); } /* Retrieves the (file system entry) modification date and time * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_values_get_entry_modification_time( libfsntfs_file_name_values_t *file_name_values, uint64_t *filetime, libcerror_error_t **error ) { static char *function = "libfsntfs_file_name_values_get_entry_modification_time"; if( file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file name values.", function ); return( -1 ); } if( filetime == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid FILETIME.", function ); return( -1 ); } *filetime = file_name_values->entry_modification_time; return( 1 ); } /* Retrieves the size * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_values_get_size( libfsntfs_file_name_values_t *file_name_values, uint64_t *size, libcerror_error_t **error ) { static char *function = "libfsntfs_file_name_values_get_size"; if( file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file name values.", function ); return( -1 ); } if( size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid size.", function ); return( -1 ); } *size = file_name_values->size; return( 1 ); } /* Retrieves the file attribute flags * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_values_get_file_attribute_flags( libfsntfs_file_name_values_t *file_name_values, uint32_t *file_attribute_flags, libcerror_error_t **error ) { static char *function = "libfsntfs_file_name_values_get_file_attribute_flags"; if( file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file name values.", function ); return( -1 ); } if( file_attribute_flags == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file attribute flags.", function ); return( -1 ); } *file_attribute_flags = file_name_values->file_attribute_flags; return( 1 ); } /* Retrieves the name space * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_values_get_name_space( libfsntfs_file_name_values_t *file_name_values, uint8_t *name_space, libcerror_error_t **error ) { static char *function = "libfsntfs_file_name_values_get_name_space"; if( file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file name values.", function ); return( -1 ); } if( name_space == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid name space.", function ); return( -1 ); } *name_space = file_name_values->name_space; return( 1 ); } /* Retrieves the size of the UTF-8 encoded name * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_values_get_utf8_name_size( libfsntfs_file_name_values_t *file_name_values, size_t *utf8_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_file_name_values_get_utf8_name_size"; if( file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file name values.", function ); return( -1 ); } if( libuna_utf8_string_size_from_utf16_stream( file_name_values->name, (size_t) file_name_values->name_size, LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 string size.", function ); return( -1 ); } return( 1 ); } /* Retrieves the UTF-8 encoded name * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_values_get_utf8_name( libfsntfs_file_name_values_t *file_name_values, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_file_name_values_get_utf8_name"; if( file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file name values.", function ); return( -1 ); } if( libuna_utf8_string_copy_from_utf16_stream( utf8_string, utf8_string_size, file_name_values->name, (size_t) file_name_values->name_size, LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 string.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: string data:\n", function ); libcnotify_print_data( utf8_string, utf8_string_size, 0 ); } #endif return( 1 ); } /* Retrieves the size of the UTF-16 encoded name * This function uses UCS-2 (with surrogates) to support characters outside Unicode * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_values_get_utf16_name_size( libfsntfs_file_name_values_t *file_name_values, size_t *utf16_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_file_name_values_get_utf16_name_size"; if( file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file name values.", function ); return( -1 ); } if( libuna_utf16_string_size_from_utf16_stream( file_name_values->name, (size_t) file_name_values->name_size, LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 string size.", function ); return( -1 ); } return( 1 ); } /* Retrieves the UTF-16 encoded name * This function uses UCS-2 (with surrogates) to support characters outside Unicode * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_file_name_values_get_utf16_name( libfsntfs_file_name_values_t *file_name_values, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_file_name_values_get_utf16_name"; if( file_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file name values.", function ); return( -1 ); } if( libuna_utf16_string_copy_from_utf16_stream( utf16_string, utf16_string_size, file_name_values->name, (size_t) file_name_values->name_size, LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 string.", function ); return( -1 ); } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_file_name_values.h ================================================ /* * File name attribute ($FILE_NAME) values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_FILE_NAME_VALUES_H ) #define _LIBFSNTFS_FILE_NAME_VALUES_H #include #include #include "libfsntfs_libcerror.h" #include "libfsntfs_mft_attribute.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_file_name_values libfsntfs_file_name_values_t; struct libfsntfs_file_name_values { /* The parent file reference */ uint64_t parent_file_reference; /* The creation time */ uint64_t creation_time; /* The modification time */ uint64_t modification_time; /* The access time */ uint64_t access_time; /* The entry modification time */ uint64_t entry_modification_time; /* The size */ uint64_t size; /* The file attribute flags */ uint32_t file_attribute_flags; /* The name space */ uint8_t name_space; /* The UTF-16 little-endian formatted name */ uint8_t *name; /* The name size */ size_t name_size; }; int libfsntfs_file_name_values_initialize( libfsntfs_file_name_values_t **file_name_values, libcerror_error_t **error ); int libfsntfs_file_name_values_free( libfsntfs_file_name_values_t **file_name_values, libcerror_error_t **error ); int libfsntfs_file_name_values_clone( libfsntfs_file_name_values_t **destination_file_name_values, libfsntfs_file_name_values_t *source_file_name_values, libcerror_error_t **error ); int libfsntfs_file_name_values_set_name( libfsntfs_file_name_values_t *file_name_values, const uint8_t *utf16_stream, size_t utf16_stream_size, libcerror_error_t **error ); int libfsntfs_file_name_values_read_data( libfsntfs_file_name_values_t *file_name_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_file_name_values_read_from_mft_attribute( libfsntfs_file_name_values_t *file_name_values, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ); int libfsntfs_file_name_values_get_parent_file_reference( libfsntfs_file_name_values_t *file_name_values, uint64_t *parent_file_reference, libcerror_error_t **error ); int libfsntfs_file_name_values_get_creation_time( libfsntfs_file_name_values_t *file_name_values, uint64_t *filetime, libcerror_error_t **error ); int libfsntfs_file_name_values_get_modification_time( libfsntfs_file_name_values_t *file_name_values, uint64_t *filetime, libcerror_error_t **error ); int libfsntfs_file_name_values_get_access_time( libfsntfs_file_name_values_t *file_name_values, uint64_t *filetime, libcerror_error_t **error ); int libfsntfs_file_name_values_get_entry_modification_time( libfsntfs_file_name_values_t *file_name_values, uint64_t *filetime, libcerror_error_t **error ); int libfsntfs_file_name_values_get_size( libfsntfs_file_name_values_t *file_name_values, uint64_t *size, libcerror_error_t **error ); int libfsntfs_file_name_values_get_file_attribute_flags( libfsntfs_file_name_values_t *file_name_values, uint32_t *file_attribute_flags, libcerror_error_t **error ); int libfsntfs_file_name_values_get_name_space( libfsntfs_file_name_values_t *file_name_values, uint8_t *name_space, libcerror_error_t **error ); int libfsntfs_file_name_values_get_utf8_name_size( libfsntfs_file_name_values_t *file_name_values, size_t *utf8_string_size, libcerror_error_t **error ); int libfsntfs_file_name_values_get_utf8_name( libfsntfs_file_name_values_t *file_name_values, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); int libfsntfs_file_name_values_get_utf16_name_size( libfsntfs_file_name_values_t *file_name_values, size_t *utf16_string_size, libcerror_error_t **error ); int libfsntfs_file_name_values_get_utf16_name( libfsntfs_file_name_values_t *file_name_values, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_FILE_NAME_VALUES_H ) */ ================================================ FILE: libfsntfs/libfsntfs_file_system.c ================================================ /* * File system functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_cluster_block.h" #include "libfsntfs_cluster_block_vector.h" #include "libfsntfs_definitions.h" #include "libfsntfs_file_system.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_libuna.h" #include "libfsntfs_mft.h" #include "libfsntfs_mft_attribute_list.h" #include "libfsntfs_mft_entry.h" #include "libfsntfs_name.h" #include "libfsntfs_path_hint.h" #include "libfsntfs_security_descriptor_index.h" #include "libfsntfs_security_descriptor_values.h" /* Creates a file system * Make sure the value file_system is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_file_system_initialize( libfsntfs_file_system_t **file_system, libcerror_error_t **error ) { static char *function = "libfsntfs_file_system_initialize"; if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } if( *file_system != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file system value already set.", function ); return( -1 ); } *file_system = memory_allocate_structure( libfsntfs_file_system_t ); if( *file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create file system.", function ); goto on_error; } if( memory_set( *file_system, 0, sizeof( libfsntfs_file_system_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear file system.", function ); memory_free( *file_system ); *file_system = NULL; return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_initialize( &( ( *file_system )->read_write_lock ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize read/write lock.", function ); goto on_error; } #endif return( 1 ); on_error: if( *file_system != NULL ) { memory_free( *file_system ); *file_system = NULL; } return( -1 ); } /* Frees a file system * Returns 1 if successful or -1 on error */ int libfsntfs_file_system_free( libfsntfs_file_system_t **file_system, libcerror_error_t **error ) { static char *function = "libfsntfs_file_system_free"; int result = 1; if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } if( *file_system != NULL ) { #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_free( &( ( *file_system )->read_write_lock ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free read/write lock.", function ); result = -1; } #endif if( ( *file_system )->path_hints_tree != NULL ) { if( libcdata_btree_free( &( ( *file_system )->path_hints_tree ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_path_hint_free, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free path hints tree.", function ); result = -1; } } if( ( *file_system )->security_descriptor_index != NULL ) { if( libfsntfs_security_descriptor_index_free( &( ( *file_system )->security_descriptor_index ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free security descriptor index.", function ); result = -1; } } if( ( *file_system )->mft != NULL ) { if( libfsntfs_mft_free( &( ( *file_system )->mft ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free MFT.", function ); result = -1; } } memory_free( *file_system ); *file_system = NULL; } return( result ); } /* Reads the MFT * Returns 1 if successful or -1 on error */ int libfsntfs_file_system_read_mft( libfsntfs_file_system_t *file_system, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, off64_t mft_offset, uint8_t flags, libcerror_error_t **error ) { libfsntfs_data_run_t *data_run = NULL; libfsntfs_mft_attribute_t *data_attribute = NULL; libfsntfs_mft_attribute_t *last_data_attribute = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; static char *function = "libfsntfs_file_system_read_mft"; size64_t mft_size = 0; uint64_t file_reference = 0; uint64_t number_of_mft_entries = 0; uint16_t attribute_data_flags = 0; int attribute_index = 0; int data_run_index = 0; int file_reference_index = 0; int number_of_data_runs = 0; int number_of_file_entries = 0; int segment_index = 0; if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } if( file_system->mft != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file system - MFT value already set.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( mft_offset < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid MFT offset value out of bounds.", function ); goto on_error; } if( mft_size > (size64_t) INT64_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid MFT size value exceeds maximum.", function ); return( -1 ); } if( libfsntfs_mft_entry_initialize( &mft_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create MFT entry.", function ); goto on_error; } if( libfsntfs_mft_entry_read_file_io_handle( mft_entry, file_io_handle, mft_offset, io_handle->mft_entry_size, LIBFSNTFS_MFT_ENTRY_INDEX_MFT, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read MFT entry: %d.", function, LIBFSNTFS_MFT_ENTRY_INDEX_MFT ); goto on_error; } if( mft_entry->is_empty == 0 ) { if( libfsntfs_mft_entry_read_attributes_data( mft_entry, io_handle, mft_entry->data, mft_entry->data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read attributes of MFT entry: %d.", function, LIBFSNTFS_MFT_ENTRY_INDEX_MFT ); goto on_error; } } if( libfsntfs_mft_attribute_get_data_flags( mft_entry->data_attribute, &attribute_data_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute data flags.", function ); goto on_error; } if( ( attribute_data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported compressed attribute data.", function ); goto on_error; } if( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) != 0 ) { if( libbfio_handle_get_size( file_io_handle, &mft_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve $MFT metadata file size.", function ); goto on_error; } } else { if( libfsntfs_mft_attribute_get_data_size( mft_entry->data_attribute, &mft_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data size of MFT entry: %d.", function, LIBFSNTFS_MFT_ENTRY_INDEX_MFT ); goto on_error; } } if( libfsntfs_mft_initialize( &( file_system->mft ), io_handle, (size64_t) io_handle->mft_entry_size, flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create MFT.", function ); goto on_error; } if( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) != 0 ) { if( libfdata_vector_append_segment( file_system->mft->mft_entry_vector, &segment_index, 0, 0, mft_size, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append $MFT metadata file range to MFT entry vector.", function ); goto on_error; } } else { if( libfsntfs_mft_attribute_get_number_of_data_runs( mft_entry->data_attribute, &number_of_data_runs, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of data runs.", function ); goto on_error; } for( data_run_index = 0; data_run_index < number_of_data_runs; data_run_index++ ) { if( libfsntfs_mft_attribute_get_data_run_by_index( mft_entry->data_attribute, data_run_index, &data_run, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to data run: %d.", function, data_run_index ); goto on_error; } if( data_run == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing data run: %d.", data_run_index ); goto on_error; } if( libfdata_vector_append_segment( file_system->mft->mft_entry_vector, &segment_index, 0, data_run->start_offset, data_run->size, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append data run: %d to MFT entry vector.", function, data_run_index ); goto on_error; } } last_data_attribute = mft_entry->data_attribute; } if( ( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) == 0 ) && ( mft_entry->list_attribute != NULL ) ) { if( libfsntfs_mft_entry_read_attribute_list( mft_entry, io_handle, file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read attribute list.", function ); goto on_error; } if( libfsntfs_mft_attribute_list_get_number_of_file_references( mft_entry->attribute_list, &number_of_file_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of attribute list data MFT entries.", function ); goto on_error; } for( file_reference_index = 0; file_reference_index < number_of_file_entries; file_reference_index++ ) { if( libfsntfs_mft_attribute_list_get_file_reference_by_index( mft_entry->attribute_list, file_reference_index, &file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute list data MFT entry: %d.", function, file_reference_index ); goto on_error; } if( libfsntfs_mft_entry_read_attribute_list_data_mft_entry_by_index( mft_entry, io_handle, file_io_handle, file_system->mft->mft_entry_vector, file_system->mft->mft_entry_cache, file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read attribute list data MFT entry: %" PRIu64 "-%" PRIu64 ".", function, file_reference & 0xffffffffffffUL, file_reference >> 48 ); goto on_error; } if( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) == 0 ) { if( libfsntfs_mft_attribute_get_next_attribute( last_data_attribute, &data_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve next data attribute: %d.", function, attribute_index ); goto on_error; } if( data_attribute != NULL ) { attribute_index++; if( libfsntfs_mft_attribute_get_number_of_data_runs( data_attribute, &number_of_data_runs, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of data runs.", function ); goto on_error; } for( data_run_index = 0; data_run_index < number_of_data_runs; data_run_index++ ) { if( libfsntfs_mft_attribute_get_data_run_by_index( data_attribute, data_run_index, &data_run, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data run: %d.", function, data_run_index ); goto on_error; } if( data_run == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing data run: %d.", data_run_index ); goto on_error; } if( libfdata_vector_append_segment( file_system->mft->mft_entry_vector, &segment_index, 0, data_run->start_offset, data_run->size, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append data run: %d to MFT entry vector.", function, data_run_index ); goto on_error; } } last_data_attribute = data_attribute; } } } } number_of_mft_entries = (uint64_t) ( mft_size / io_handle->mft_entry_size ); if( number_of_mft_entries > (uint64_t) INT_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid number of MFT entries value out of bounds.", function ); goto on_error; } file_system->mft->number_of_mft_entries = number_of_mft_entries; if( libfsntfs_mft_entry_free( &mft_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free MFT entry.", function ); goto on_error; } if( libcdata_btree_initialize( &( file_system->path_hints_tree ), LIBFSNTFS_INDEX_TREE_MAXIMUM_NUMBER_OF_SUB_NODES, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create path hints B-tree.", function ); goto on_error; } return( 1 ); on_error: if( file_system->path_hints_tree != NULL ) { libcdata_btree_free( &( file_system->path_hints_tree ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_path_hint_free, NULL ); } if( mft_entry != NULL ) { libfsntfs_mft_entry_free( &mft_entry, NULL ); } return( -1 ); } /* Reads the bitmap file entry * Returns 1 if successful or -1 on error */ int libfsntfs_file_system_read_bitmap( libfsntfs_file_system_t *file_system, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libcerror_error_t **error ) { libfcache_cache_t *cluster_block_cache = NULL; libfdata_vector_t *cluster_block_vector = NULL; libfsntfs_cluster_block_t *cluster_block = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; static char *function = "libfsntfs_file_system_read_bitmap"; size_t cluster_block_data_offset = 0; off64_t bitmap_offset = 0; off64_t start_offset = 0; uint32_t value_32bit = 0; uint8_t bit_index = 0; int cluster_block_index = 0; int number_of_cluster_blocks = 0; if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( libfsntfs_mft_get_mft_entry_by_index( file_system->mft, file_io_handle, LIBFSNTFS_MFT_ENTRY_INDEX_BITMAP, &mft_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: %d.", function, LIBFSNTFS_MFT_ENTRY_INDEX_BITMAP ); goto on_error; } if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing MFT entry: %d.", function, LIBFSNTFS_MFT_ENTRY_INDEX_BITMAP ); goto on_error; } if( mft_entry->data_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid MFT entry: %d - missing data attribute.", function, LIBFSNTFS_MFT_ENTRY_INDEX_BITMAP ); goto on_error; } if( libfsntfs_cluster_block_vector_initialize( &cluster_block_vector, io_handle, mft_entry->data_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create cluster block vector.", function ); goto on_error; } if( libfcache_cache_initialize( &cluster_block_cache, 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create cluster block cache.", function ); goto on_error; } if( libfdata_vector_get_number_of_elements( cluster_block_vector, &number_of_cluster_blocks, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of cluster blocks.", function ); goto on_error; } for( cluster_block_index = 0; cluster_block_index < number_of_cluster_blocks; cluster_block_index++ ) { if( libfdata_vector_get_element_value_by_index( cluster_block_vector, (intptr_t *) file_io_handle, (libfdata_cache_t *) cluster_block_cache, cluster_block_index, (intptr_t **) &cluster_block, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve cluster block: %d from vector.", function, cluster_block_index ); goto on_error; } if( cluster_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing cluster block: %d.", function, cluster_block_index ); goto on_error; } if( cluster_block->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid cluster block: %d - missing data.", function, cluster_block_index ); goto on_error; } if( ( ( cluster_block->data_size % 4 ) != 0 ) || ( cluster_block->data_size > (size_t) SSIZE_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: cluster block: %d data size value out of bounds.", function, cluster_block_index ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: bitmap segment: %d data:\n", function, cluster_block_index ); libcnotify_print_data( cluster_block->data, cluster_block->data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif cluster_block_data_offset = 0; start_offset = -1; while( cluster_block_data_offset < cluster_block->data_size ) { byte_stream_copy_to_uint32_little_endian( &( cluster_block->data[ cluster_block_data_offset ] ), value_32bit ); for( bit_index = 0; bit_index < 32; bit_index++ ) { if( ( value_32bit & 0x00000001UL ) == 0 ) { if( start_offset >= 0 ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: offset range\t\t\t\t: 0x%08" PRIx64 " - 0x%08" PRIx64 " (0x%08" PRIx64 ")\n", function, start_offset, bitmap_offset, bitmap_offset - start_offset ); } #endif /* if( libfsntfs_offset_list_append_offset( offset_list, start_offset, bitmap_offset - start_offset, 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append offset range to offset list.", function ); goto on_error; } */ start_offset = -1; } } else { if( start_offset < 0 ) { start_offset = bitmap_offset; } } bitmap_offset += io_handle->cluster_block_size; value_32bit >>= 1; } cluster_block_data_offset += 4; } if( start_offset >= 0 ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: offset range\t\t\t\t: 0x%08" PRIx64 " - 0x%08" PRIx64 " (0x%08" PRIx64 ")\n", function, start_offset, bitmap_offset, bitmap_offset - start_offset ); } #endif /* TODO if( libfsntfs_offset_list_append_offset( offset_list, start_offset, bitmap_offset - start_offset, 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append offset range to offset list.", function ); goto on_error; } */ } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "\n" ); } #endif } if( libfdata_vector_free( &cluster_block_vector, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free cluster block vector.", function ); goto on_error; } if( libfcache_cache_free( &cluster_block_cache, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free cluster block cache.", function ); goto on_error; } return( 1 ); on_error: if( cluster_block_cache != NULL ) { libfcache_cache_free( &cluster_block_cache, NULL ); } if( cluster_block_vector != NULL ) { libfdata_vector_free( &cluster_block_vector, NULL ); } return( -1 ); } /* Reads the security descriptors * Returns 1 if successful or -1 on error */ int libfsntfs_file_system_read_security_descriptors( libfsntfs_file_system_t *file_system, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libcerror_error_t **error ) { libfsntfs_file_name_values_t *file_name_values = NULL; libfsntfs_mft_attribute_t *data_attribute = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; static char *function = "libfsntfs_file_system_read_security_descriptors"; int result = 0; if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } if( file_system->security_descriptor_index != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file system - security descriptor index value already set.", function ); return( -1 ); } if( libfsntfs_mft_get_mft_entry_by_index( file_system->mft, file_io_handle, LIBFSNTFS_MFT_ENTRY_INDEX_SECURE, &mft_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: %d.", function, LIBFSNTFS_MFT_ENTRY_INDEX_SECURE ); goto on_error; } if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing MFT entry: %d.", function, LIBFSNTFS_MFT_ENTRY_INDEX_SECURE ); goto on_error; } if( libfsntfs_mft_entry_get_attribute_by_index( mft_entry, mft_entry->file_name_attribute_index, &mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d from MFT entry: %d.", function, mft_entry->file_name_attribute_index, LIBFSNTFS_MFT_ENTRY_INDEX_SECURE ); goto on_error; } if( libfsntfs_file_name_values_initialize( &file_name_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file name values.", function ); goto on_error; } if( libfsntfs_file_name_values_read_from_mft_attribute( file_name_values, mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read file name values from attribute: %d from MFT entry: %d.", function, mft_entry->file_name_attribute_index, LIBFSNTFS_MFT_ENTRY_INDEX_SECURE ); goto on_error; } result = libfsntfs_name_compare_with_utf8_string( file_name_values->name, file_name_values->name_size, (uint8_t *) "$Secure", 7, 1, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GENERIC, "%s: unable to compare UTF-8 string with data attribute name.", function ); goto on_error; } else if( result == LIBUNA_COMPARE_EQUAL ) { if( libfsntfs_mft_entry_get_alternate_data_attribute_by_utf8_name( mft_entry, (uint8_t *) "$SDS", 4, &data_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve $SDS data attribute.", function ); goto on_error; } if( libfsntfs_security_descriptor_index_initialize( &( file_system->security_descriptor_index ), io_handle, file_io_handle, data_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create security descriptor index.", function ); goto on_error; } if( libfsntfs_security_descriptor_index_read_sii_index( file_system->security_descriptor_index, io_handle, file_io_handle, mft_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read security descriptor identifier ($SII) index.", function ); goto on_error; } } if( libfsntfs_file_name_values_free( &file_name_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file name values.", function ); goto on_error; } return( 1 ); on_error: if( file_system->security_descriptor_index != NULL ) { libfsntfs_security_descriptor_index_free( &( file_system->security_descriptor_index ), NULL ); } if( file_name_values != NULL ) { libfsntfs_file_name_values_free( &file_name_values, NULL ); } return( -1 ); } /* Retrieves the number of MFT entries * Returns 1 if successful or -1 on error */ int libfsntfs_file_system_get_number_of_mft_entries( libfsntfs_file_system_t *file_system, uint64_t *number_of_mft_entries, libcerror_error_t **error ) { static char *function = "libfsntfs_file_system_get_number_of_mft_entries"; if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } if( libfsntfs_mft_get_number_of_entries( file_system->mft, number_of_mft_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of MFT entries.", function ); return( -1 ); } return( 1 ); } /* Retrieves the MFT entry for a specific index * Returns 1 if successful or -1 on error */ int libfsntfs_file_system_get_mft_entry_by_index( libfsntfs_file_system_t *file_system, libbfio_handle_t *file_io_handle, uint64_t mft_entry_index, libfsntfs_mft_entry_t **mft_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_file_system_get_mft_entry_by_index"; if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } if( libfsntfs_mft_get_mft_entry_by_index( file_system->mft, file_io_handle, mft_entry_index, mft_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: %" PRIi64 ".", function, mft_entry_index ); return( -1 ); } return( 1 ); } /* Retrieves the MFT entry for a specific index * This function creates new MFT entry * Returns 1 if successful or -1 on error */ int libfsntfs_file_system_get_mft_entry_by_index_no_cache( libfsntfs_file_system_t *file_system, libbfio_handle_t *file_io_handle, uint64_t mft_entry_index, libfsntfs_mft_entry_t **mft_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_file_system_get_mft_entry_by_index_no_cache"; if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } if( libfsntfs_mft_get_mft_entry_by_index_no_cache( file_system->mft, file_io_handle, mft_entry_index, mft_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: %" PRIi64 ".", function, mft_entry_index ); return( -1 ); } return( 1 ); } /* Retrieves the security descriptor for a specific identifier * This function creates new security descriptor values * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_system_get_security_descriptor_values_by_identifier( libfsntfs_file_system_t *file_system, libbfio_handle_t *file_io_handle, uint32_t security_descriptor_identifier, libfsntfs_security_descriptor_values_t **security_descriptor_values, libcerror_error_t **error ) { static char *function = "libfsntfs_file_system_get_security_descriptor_values_by_identifier"; int result = 0; if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } if( file_system->security_descriptor_index != NULL ) { result = libfsntfs_security_descriptor_index_get_entry_by_identifier( file_system->security_descriptor_index, file_io_handle, security_descriptor_identifier, security_descriptor_values, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security descriptor from index for identifier: %" PRIu32 ".", function, security_descriptor_identifier ); return( -1 ); } } return( result ); } /* Retrieves the path hint of a specific file reference * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_file_system_get_path_hint( libfsntfs_file_system_t *file_system, libbfio_handle_t *file_io_handle, uint64_t file_reference, libfsntfs_path_hint_t **path_hint, int recursion_depth, libcerror_error_t **error ) { libcdata_tree_node_t *upper_node = NULL; libfsntfs_file_name_values_t *file_name_values = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; libfsntfs_path_hint_t *existing_path_hint = NULL; libfsntfs_path_hint_t *lookup_path_hint = NULL; libfsntfs_path_hint_t *parent_path_hint = NULL; libfsntfs_path_hint_t *safe_path_hint = NULL; uint8_t *parent_path = NULL; static char *function = "libfsntfs_file_system_get_path_hint"; size_t name_size = 0; size_t parent_path_size = 0; uint64_t mft_entry_index = 0; uint64_t mft_entry_file_reference = 0; uint64_t parent_file_reference = 0; uint64_t parent_mft_entry_index = 0; uint32_t attribute_type = 0; uint16_t mft_entry_sequence_number = 0; uint16_t sequence_number = 0; int attribute_index = 0; int number_of_attributes = 0; int result = 0; int value_index = 0; if( file_system == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file system.", function ); return( -1 ); } if( path_hint == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path hint.", function ); return( -1 ); } if( ( recursion_depth < 0 ) || ( recursion_depth > LIBFSNTFS_MAXIMUM_RECURSION_DEPTH ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid recursion depth value out of bounds.", function ); return( -1 ); } mft_entry_index = file_reference & 0xffffffffffffUL; if( libfsntfs_file_system_get_mft_entry_by_index( file_system, file_io_handle, mft_entry_index, &mft_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: %" PRIu64 ".", function, mft_entry_index ); goto on_error; } if( libfsntfs_mft_entry_get_file_reference( mft_entry, &mft_entry_file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: %" PRIu64 ".", function, mft_entry_index ); goto on_error; } if( mft_entry_file_reference != file_reference ) { result = libfsntfs_mft_entry_is_allocated( mft_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: %" PRIu64 ".", function, mft_entry_index ); goto on_error; } else if( result != 0 ) { return( 0 ); } /* The sequence number is updated when the MFT entry is deleted */ sequence_number = (uint16_t) ( file_reference >> 48 ); mft_entry_sequence_number = (uint16_t) ( mft_entry_file_reference >> 48 ); if( sequence_number != ( mft_entry_sequence_number - 1 ) ) { return( 0 ); } } if( libfsntfs_path_hint_initialize( &lookup_path_hint, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create path hint.", function ); goto on_error; } lookup_path_hint->file_reference = mft_entry_file_reference; result = libcdata_btree_get_value_by_value( file_system->path_hints_tree, (intptr_t *) lookup_path_hint, (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_path_hint_compare_by_file_reference, &upper_node, (intptr_t **) path_hint, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve path hint from tree.", function ); goto on_error; } else if( result == 0 ) { if( libfsntfs_mft_entry_get_number_of_attributes( mft_entry, &number_of_attributes, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of attributes.", function ); goto on_error; } for( attribute_index = 0; attribute_index < number_of_attributes; attribute_index++ ) { if( libfsntfs_mft_entry_get_attribute_by_index( mft_entry, attribute_index, &mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d.", function, attribute_index ); goto on_error; } if( libfsntfs_mft_attribute_get_type( mft_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d type.", function, attribute_index ); goto on_error; } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ) { continue; } if( libfsntfs_file_name_values_initialize( &file_name_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file name values.", function ); goto on_error; } if( libfsntfs_file_name_values_read_from_mft_attribute( file_name_values, mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read file name values.", function ); goto on_error; } if( libfsntfs_file_name_values_get_parent_file_reference( file_name_values, &parent_file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve parent file reference.", function ); goto on_error; } parent_mft_entry_index = parent_file_reference & 0xffffffffffffUL; if( file_name_values->name_space != LIBFSNTFS_FILE_NAME_SPACE_DOS ) { parent_path = NULL; parent_path_size = 0; if( ( mft_entry_index != LIBFSNTFS_MFT_ENTRY_INDEX_ROOT_DIRECTORY ) && ( parent_mft_entry_index == LIBFSNTFS_MFT_ENTRY_INDEX_ROOT_DIRECTORY ) ) { parent_path = (uint8_t *) ""; parent_path_size = 1; } else if( ( parent_mft_entry_index != 0 ) && ( parent_mft_entry_index != mft_entry_index ) ) { result = libfsntfs_file_system_get_path_hint( file_system, file_io_handle, parent_file_reference, &parent_path_hint, recursion_depth + 1, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve path hint for MFT entry: %" PRIu64 ".", function, parent_mft_entry_index ); goto on_error; } else if( result == 0 ) { parent_path = (uint8_t *) "$Orphan"; parent_path_size = 8; } else { parent_path = parent_path_hint->path; parent_path_size = parent_path_hint->path_size; } } if( libfsntfs_file_name_values_get_utf8_name_size( file_name_values, &name_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-8 name.", function ); goto on_error; } if( libfsntfs_path_hint_initialize( &safe_path_hint, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create path hint.", function ); goto on_error; } safe_path_hint->file_reference = file_reference; safe_path_hint->path_size = parent_path_size + name_size; safe_path_hint->path = (uint8_t *) memory_allocate( sizeof( uint8_t ) * safe_path_hint->path_size ); if( safe_path_hint->path == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create path.", function ); goto on_error; } if( ( parent_path != NULL ) && ( parent_path_size > 0 ) ) { if( memory_copy( safe_path_hint->path, parent_path, parent_path_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy parent path to path.", function ); goto on_error; } safe_path_hint->path[ parent_path_size - 1 ] = '\\'; } if( name_size > 0 ) { if( libfsntfs_file_name_values_get_utf8_name( file_name_values, &( safe_path_hint->path[ parent_path_size ] ), name_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 name.", function ); goto on_error; } } if( mft_entry_index == LIBFSNTFS_MFT_ENTRY_INDEX_ROOT_DIRECTORY ) { safe_path_hint->path[ 0 ] = '\\'; } result = libcdata_btree_insert_value( file_system->path_hints_tree, &value_index, (intptr_t *) safe_path_hint, (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_path_hint_compare_by_file_reference, &upper_node, (intptr_t **) &existing_path_hint, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to insert path hint into tree.", function ); goto on_error; } else if( result == 0 ) { if( libfsntfs_path_hint_free( &safe_path_hint, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free path hint.", function ); goto on_error; } *path_hint = existing_path_hint; } else { *path_hint = safe_path_hint; safe_path_hint = NULL; } result = 1; } if( libfsntfs_file_name_values_free( &file_name_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file name values.", function ); goto on_error; } } } if( libfsntfs_path_hint_free( &lookup_path_hint, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free path hint.", function ); goto on_error; } return( result ); on_error: if( safe_path_hint != NULL ) { libfsntfs_path_hint_free( &safe_path_hint, NULL ); } if( file_name_values != NULL ) { libfsntfs_file_name_values_free( &file_name_values, NULL ); } if( lookup_path_hint != NULL ) { libfsntfs_path_hint_free( &lookup_path_hint, NULL ); } return( -1 ); } ================================================ FILE: libfsntfs/libfsntfs_file_system.h ================================================ /* * File system functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_FILE_SYSTEM_H ) #define _LIBFSNTFS_FILE_SYSTEM_H #include #include #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_mft.h" #include "libfsntfs_path_hint.h" #include "libfsntfs_security_descriptor_index.h" #include "libfsntfs_security_descriptor_values.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_file_system libfsntfs_file_system_t; struct libfsntfs_file_system { /* The MFT */ libfsntfs_mft_t *mft; /* The security descriptor index */ libfsntfs_security_descriptor_index_t *security_descriptor_index; /* The list data MFT entry B-tree */ libcdata_btree_t *list_data_mft_entry_tree; /* The path hints B-tree */ libcdata_btree_t *path_hints_tree; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) /* The read/write lock */ libcthreads_read_write_lock_t *read_write_lock; #endif }; int libfsntfs_file_system_initialize( libfsntfs_file_system_t **file_system, libcerror_error_t **error ); int libfsntfs_file_system_free( libfsntfs_file_system_t **file_system, libcerror_error_t **error ); int libfsntfs_file_system_read_mft( libfsntfs_file_system_t *file_system, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, off64_t mft_offset, uint8_t flags, libcerror_error_t **error ); int libfsntfs_file_system_read_bitmap( libfsntfs_file_system_t *file_system, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libcerror_error_t **error ); int libfsntfs_file_system_read_security_descriptors( libfsntfs_file_system_t *file_system, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libcerror_error_t **error ); int libfsntfs_file_system_get_number_of_mft_entries( libfsntfs_file_system_t *file_system, uint64_t *number_of_mft_entries, libcerror_error_t **error ); int libfsntfs_file_system_get_mft_entry_by_index( libfsntfs_file_system_t *file_system, libbfio_handle_t *file_io_handle, uint64_t mft_entry_index, libfsntfs_mft_entry_t **mft_entry, libcerror_error_t **error ); int libfsntfs_file_system_get_mft_entry_by_index_no_cache( libfsntfs_file_system_t *file_system, libbfio_handle_t *file_io_handle, uint64_t mft_entry_index, libfsntfs_mft_entry_t **mft_entry, libcerror_error_t **error ); int libfsntfs_file_system_get_security_descriptor_values_by_identifier( libfsntfs_file_system_t *file_system, libbfio_handle_t *file_io_handle, uint32_t security_descriptor_identifier, libfsntfs_security_descriptor_values_t **security_descriptor_values, libcerror_error_t **error ); int libfsntfs_file_system_get_path_hint( libfsntfs_file_system_t *file_system, libbfio_handle_t *file_io_handle, uint64_t file_reference, libfsntfs_path_hint_t **path_hint, int recursion_depth, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_FILE_SYSTEM_H ) */ ================================================ FILE: libfsntfs/libfsntfs_fixup_values.c ================================================ /* * Fix-up values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_fixup_values.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" /* Applies the fix-up values to the data * Returns 1 if successful or -1 on error */ int libfsntfs_fixup_values_apply( uint8_t *data, size_t data_size, uint16_t fixup_values_offset, uint16_t number_of_fixup_values, libcerror_error_t **error ) { static char *function = "libfsntfs_fixup_values_apply"; size_t data_offset = 0; size_t fixup_placeholder_offset = 0; size_t fixup_value_offset = 0; size_t fixup_values_size = 0; uint16_t fixup_value_index = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint16_t value_16bit = 0; #endif if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } if( fixup_values_offset >= data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid fix-up values offset value out of bounds.", function ); return( -1 ); } fixup_values_size = 2 + ( (size_t) number_of_fixup_values * 2 ); if( ( number_of_fixup_values == 0 ) || ( fixup_values_size > ( data_size - fixup_values_offset ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid number of fix-up values value out of bounds.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: fix-up values data:\n", function ); libcnotify_print_data( &( data[ fixup_values_offset ] ), fixup_values_size, 0 ); } #endif fixup_placeholder_offset = (size_t) fixup_values_offset; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { byte_stream_copy_to_uint16_little_endian( &( data[ fixup_placeholder_offset ] ), value_16bit ); libcnotify_printf( "%s: fix-up placeholder value\t\t\t: 0x%04" PRIx16 "\n", function, value_16bit ); } #endif fixup_value_offset = fixup_placeholder_offset + 2; data_offset = 510; for( fixup_value_index = 0; fixup_value_index < number_of_fixup_values; fixup_value_index++ ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { byte_stream_copy_to_uint16_little_endian( &( data[ fixup_value_offset ] ), value_16bit ); libcnotify_printf( "%s: fix-up value: %" PRIu16 "\t\t\t\t: 0x%04" PRIx16 "\n", function, fixup_value_index, value_16bit ); } #endif if( ( data_offset + 1 ) < data_size ) { if( ( data[ data_offset ] != data[ fixup_placeholder_offset ] ) && ( data[ data_offset + 1 ] != data[ fixup_placeholder_offset + 1 ] ) ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { byte_stream_copy_to_uint16_little_endian( &( data[ data_offset ] ), value_16bit ); libcnotify_printf( "%s: corruption detected - mismatch between placeholder and value at offset: %" PRIzd " (0x%04" PRIx16 ")\n", function, data_offset, value_16bit ); } #endif /* TODO handle error */ } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: applying fix-up value: %" PRIu16 "\t\t\t: (offset: %" PRIzd ") 0x%02" PRIx8 "%02" PRIx8 " => (offset: %" PRIzd ") 0x%02" PRIx8 "%02" PRIx8 "\n", function, fixup_value_index, data_offset, data[ data_offset + 1 ], data[ data_offset ], fixup_value_offset, data[ fixup_value_offset + 1 ], data[ fixup_value_offset ] ); } #endif data[ data_offset ] = data[ fixup_value_offset ]; data[ data_offset + 1 ] = data[ fixup_value_offset + 1 ]; } fixup_value_offset += 2; data_offset += 512; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "\n" ); } #endif return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_fixup_values.h ================================================ /* * Fix-up values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_FIXUP_VALUES_H ) #define _LIBFSNTFS_FIXUP_VALUES_H #include #include #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif int libfsntfs_fixup_values_apply( uint8_t *data, size_t data_size, uint16_t fixup_values_offset, uint16_t number_of_fixup_values, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_FIXUP_VALUES_H ) */ ================================================ FILE: libfsntfs/libfsntfs_index.c ================================================ /* * Index functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_bitmap_values.h" #include "libfsntfs_debug.h" #include "libfsntfs_definitions.h" #include "libfsntfs_index.h" #include "libfsntfs_index_entry.h" #include "libfsntfs_index_entry_vector.h" #include "libfsntfs_index_node.h" #include "libfsntfs_index_root_header.h" #include "libfsntfs_index_value.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libfcache.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_libuna.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_mft_entry.h" #include "libfsntfs_unused.h" #include "fsntfs_index.h" /* Creates an index * Make sure the value index is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_index_initialize( libfsntfs_index_t **index, libfsntfs_io_handle_t *io_handle, const uint8_t *name, size_t name_size, libcerror_error_t **error ) { static char *function = "libfsntfs_index_initialize"; if( index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index.", function ); return( -1 ); } if( *index != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid index value already set.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid name.", function ); return( -1 ); } if( ( name_size <= 1 ) || ( name_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid name size value out of bounds.", function ); return( -1 ); } *index = memory_allocate_structure( libfsntfs_index_t ); if( *index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create index.", function ); goto on_error; } if( memory_set( *index, 0, sizeof( libfsntfs_index_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear index.", function ); memory_free( *index ); *index = NULL; return( -1 ); } ( *index )->name = (uint8_t *) memory_allocate( sizeof( uint8_t ) * name_size ); if( ( *index )->name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create name.", function ); goto on_error; } if( memory_copy( ( *index )->name, name, sizeof( uint8_t ) * name_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy name.", function ); goto on_error; } ( *index )->name_size = name_size; ( *index )->io_handle = io_handle; return( 1 ); on_error: if( *index != NULL ) { if( ( *index )->name != NULL ) { memory_free( ( *index )->name ); } memory_free( *index ); *index = NULL; } return( -1 ); } /* Frees an index * Returns 1 if successful or -1 on error */ int libfsntfs_index_free( libfsntfs_index_t **index, libcerror_error_t **error ) { static char *function = "libfsntfs_index_free"; int result = 1; if( index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index.", function ); return( -1 ); } if( *index != NULL ) { /* The io_handle, index_root_attribute, index_allocation_attribute and bitmap_attribute references are freed elsewhere */ if( ( *index )->root_header != NULL ) { if( libfsntfs_index_root_header_free( &( ( *index )->root_header ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free root header.", function ); result = -1; } } if( ( *index )->root_node != NULL ) { if( libfsntfs_index_node_free( &( ( *index )->root_node ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free root node.", function ); result = -1; } } if( ( *index )->index_entry_vector != NULL ) { if( libfdata_vector_free( &( ( *index )->index_entry_vector ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free index entry vector.", function ); result = -1; } } if( ( *index )->index_node_cache != NULL ) { if( libfcache_cache_free( &( ( *index )->index_node_cache ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free index node cache.", function ); result = -1; } } if( ( *index )->bitmap_values != NULL ) { if( libfsntfs_bitmap_values_free( &( ( *index )->bitmap_values ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free bitmap values.", function ); result = -1; } } if( ( *index )->name != NULL ) { memory_free( ( *index )->name ); } memory_free( *index ); *index = NULL; } return( result ); } /* Reads the index * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_index_read( libfsntfs_index_t *index, libbfio_handle_t *file_io_handle, libfsntfs_mft_entry_t *mft_entry, uint8_t flags, libcerror_error_t **error ) { libfsntfs_mft_attribute_t *bitmap_attribute = NULL; libfsntfs_mft_attribute_t *index_allocation_attribute = NULL; libfsntfs_mft_attribute_t *index_root_attribute = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; static char *function = "libfsntfs_index_read"; uint32_t attribute_type = 0; uint32_t index_entry_size = 0; int attribute_index = 0; int number_of_attributes = 0; int result = 0; if( index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index.", function ); return( -1 ); } if( index->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index - missing IO handle.", function ); return( -1 ); } if( libfsntfs_mft_entry_get_number_of_attributes( mft_entry, &number_of_attributes, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of attributes.", function ); return( -1 ); } for( attribute_index = 0; attribute_index < number_of_attributes; attribute_index++ ) { if( libfsntfs_mft_entry_get_attribute_by_index( mft_entry, attribute_index, &mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT attribute: %d.", function, attribute_index ); return( -1 ); } result = libfsntfs_mft_attribute_compare_name_with_utf8_string( mft_attribute, index->name, index->name_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GENERIC, "%s: unable to compare UTF-8 string with attribute: %d name.", function, attribute_index ); return( -1 ); } else if( result != 0 ) { if( libfsntfs_mft_attribute_get_type( mft_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } switch( attribute_type ) { case LIBFSNTFS_ATTRIBUTE_TYPE_BITMAP: if( libfsntfs_mft_attribute_append_to_chain( &bitmap_attribute, mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append attribute to bitmap attribute chain.", function ); return( -1 ); } break; case LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ALLOCATION: if( libfsntfs_mft_attribute_append_to_chain( &index_allocation_attribute, mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append attribute to index allocation attribute chain.", function ); return( -1 ); } break; case LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ROOT: index_root_attribute = mft_attribute; break; default: #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: unsupported index attribute type: 0x%08" PRIx32 "\n", function, attribute_type ); } #endif break; } } } if( index_root_attribute == NULL ) { return( 0 ); } if( libfsntfs_index_read_root_header( index, index_root_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read index root header.", function ); goto on_error; } /* The index does not necessarily have a $BITMAP attribute */ if( bitmap_attribute != NULL ) { if( libfsntfs_index_read_bitmap( index, file_io_handle, bitmap_attribute, flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read index bitmap.", function ); goto on_error; } } if( libfsntfs_index_read_root_node( index, index_root_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read index root node.", function ); goto on_error; } /* The index does not necessarily have an $INDEX_ALLOCATION attribute */ if( index_allocation_attribute != NULL ) { if( libfsntfs_index_root_header_get_index_entry_size( index->root_header, &index_entry_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve index entry size.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( index_entry_size != index->io_handle->index_entry_size ) { libcnotify_printf( "%s: mismatch in index entry size (in index root header: %" PRIu32 ", in volume header: %" PRIu32 ").", function, index_entry_size, index->io_handle->index_entry_size ); } } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ if( index_entry_size > index->io_handle->index_entry_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: invalid index entry size: %" PRIu32 " in index root header value exceeds value in volume header: %" PRIu32 ".", function, index_entry_size, index->io_handle->index_entry_size ); goto on_error; } if( libfsntfs_index_entry_vector_initialize( &( index->index_entry_vector ), index->io_handle, index_allocation_attribute, index_entry_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create index entry vector.", function ); goto on_error; } if( libfcache_cache_initialize( &( index->index_node_cache ), LIBFSNTFS_MAXIMUM_CACHE_ENTRIES_INDEX_NODES, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create index node cache.", function ); goto on_error; } } return( 1 ); on_error: if( index->index_node_cache != NULL ) { libfcache_cache_free( &( index->index_node_cache ), NULL ); } if( index->index_entry_vector != NULL ) { libfdata_vector_free( &( index->index_entry_vector ), NULL ); } return( -1 ); } /* Reads the index root header * Returns 1 if successful or -1 on error */ int libfsntfs_index_read_root_header( libfsntfs_index_t *index, libfsntfs_mft_attribute_t *index_root_attribute, libcerror_error_t **error ) { uint8_t *data = NULL; static char *function = "libfsntfs_index_read_root_header"; size_t data_size = 0; int result = 0; if( index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index.", function ); return( -1 ); } if( index->root_header != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid index - root header value already set.", function ); return( -1 ); } result = libfsntfs_mft_attribute_data_is_resident( index_root_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if index root attribute data is resident.", function ); return( -1 ); } else if( result == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported non-resident index root attribute.", function ); return( 1 ); } if( libfsntfs_mft_attribute_get_resident_data( index_root_attribute, &data, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve index root attribute data.", function ); goto on_error; } if( libfsntfs_index_root_header_initialize( &( index->root_header ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create root header.", function ); goto on_error; } if( libfsntfs_index_root_header_read_data( index->root_header, data, data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read root header.", function ); goto on_error; } return( 1 ); on_error: if( index->root_header != NULL ) { libfsntfs_index_root_header_free( &( index->root_header ), NULL ); } return( -1 ); } /* Reads the index root node * Returns 1 if successful or -1 on error */ int libfsntfs_index_read_root_node( libfsntfs_index_t *index, libfsntfs_mft_attribute_t *index_root_attribute, libcerror_error_t **error ) { uint8_t *data = NULL; static char *function = "libfsntfs_index_read_root_node"; size_t data_offset = 0; size_t data_size = 0; int result = 0; if( index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index.", function ); return( -1 ); } if( index->root_node != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid index - root node value already set.", function ); return( -1 ); } result = libfsntfs_mft_attribute_data_is_resident( index_root_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if index root attribute data is resident.", function ); return( -1 ); } else if( result == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported non-resident index root attribute.", function ); return( 1 ); } if( libfsntfs_mft_attribute_get_resident_data( index_root_attribute, &data, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve index root attribute data.", function ); goto on_error; } if( libfsntfs_index_node_initialize( &( index->root_node ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create index node.", function ); goto on_error; } data_offset = sizeof( fsntfs_index_root_header_t ); if( libfsntfs_index_node_read_header( index->root_node, data, data_size, data_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read index node header.", function ); goto on_error; } data_offset += sizeof( fsntfs_index_node_header_t ); index->flags = index->root_node->header->flags; if( libfsntfs_index_node_read_values( index->root_node, 0, data, data_size, data_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read index node values.", function ); goto on_error; } data_offset += index->root_node->header->size; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( data_offset < data_size ) { libcnotify_printf( "%s: trailing data:\n", function ); libcnotify_print_data( &( data[ data_offset ] ), data_size - data_offset, 0 ); } } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ return( 1 ); on_error: if( index->root_node != NULL ) { libfsntfs_index_node_free( &( index->root_node ), NULL ); } return( -1 ); } /* Reads the index bitmap * Returns 1 if successful or -1 on error */ int libfsntfs_index_read_bitmap( libfsntfs_index_t *index, libbfio_handle_t *file_io_handle, libfsntfs_mft_attribute_t *bitmap_attribute, uint8_t flags, libcerror_error_t **error ) { static char *function = "libfsntfs_index_read_bitmap"; uint32_t index_entry_size = 0; if( index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index.", function ); return( -1 ); } if( index->bitmap_values != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid index - bitmap values already set.", function ); return( -1 ); } if( libfsntfs_index_root_header_get_index_entry_size( index->root_header, &index_entry_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve index entry size from root header.", function ); goto on_error; } if( libfsntfs_bitmap_values_initialize( &( index->bitmap_values ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create bitmap values.", function ); goto on_error; } if( libfsntfs_bitmap_values_read_from_mft_attribute( index->bitmap_values, bitmap_attribute, index->io_handle, file_io_handle, index_entry_size, flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read bitmap values from attribute.", function ); goto on_error; } return( 1 ); on_error: if( index->bitmap_values != NULL ) { libfsntfs_bitmap_values_free( &( index->bitmap_values ), NULL ); } return( -1 ); } /* Retrieves the index entry size * Returns 1 if successful or -1 on error */ int libfsntfs_index_get_index_entry_size( libfsntfs_index_t *index, uint32_t *index_entry_size, libcerror_error_t **error ) { static char *function = "libfsntfs_index_get_index_entry_size"; if( index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index.", function ); return( -1 ); } if( libfsntfs_index_root_header_get_index_entry_size( index->root_header, index_entry_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve index entry size from root header.", function ); return( -1 ); } return( 1 ); } /* Retrieves the attribute type * Returns 1 if successful or -1 on error */ int libfsntfs_index_get_attribute_type( libfsntfs_index_t *index, uint32_t *attribute_type, libcerror_error_t **error ) { static char *function = "libfsntfs_index_get_attribute_type"; if( index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index.", function ); return( -1 ); } if( libfsntfs_index_root_header_get_attribute_type( index->root_header, attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type from root header.", function ); return( -1 ); } return( 1 ); } /* Retrieves the collation type * Returns 1 if successful or -1 on error */ int libfsntfs_index_get_collation_type( libfsntfs_index_t *index, uint32_t *collation_type, libcerror_error_t **error ) { static char *function = "libfsntfs_index_get_collation_type"; if( index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index.", function ); return( -1 ); } if( libfsntfs_index_root_header_get_collation_type( index->root_header, collation_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve collation type from root header.", function ); return( -1 ); } return( 1 ); } /* Determines if a sub node is allocated * Returns 1 if allocated, 0 if not or -1 on error */ int libfsntfs_index_sub_node_is_allocated( libfsntfs_index_t *index, int sub_node_vcn, libcerror_error_t **error ) { static char *function = "libfsntfs_index_sub_node_is_allocated"; off64_t sub_node_vcn_offset = 0; int result = 0; if( index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index.", function ); return( -1 ); } if( index->bitmap_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index - missing bitmap values.", function ); return( -1 ); } if( index->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index - missing IO handle.", function ); return( -1 ); } sub_node_vcn_offset = (off64_t) sub_node_vcn * index->io_handle->cluster_block_size; result = libcdata_range_list_range_is_present( index->bitmap_values->allocated_block_list, sub_node_vcn_offset, index->io_handle->cluster_block_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if range of sub node with VCN: %d is allocated.", function, sub_node_vcn ); return( -1 ); } return( result ); } /* Retrieves a sub index node * Returns 1 if successful or -1 on error */ int libfsntfs_index_get_sub_node( libfsntfs_index_t *index, libbfio_handle_t *file_io_handle, libfcache_cache_t *index_node_cache, off64_t index_entry_offset, int sub_node_vcn, libfsntfs_index_node_t **index_node, libcerror_error_t **error ) { static char *function = "libfsntfs_index_get_sub_node"; off64_t element_data_offset = 0; #if defined( HAVE_PROFILER ) int64_t profiler_start_timestamp = 0; uint32_t index_entry_size = 0; #endif if( index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index.", function ); return( -1 ); } if( index->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index - missing IO handle.", function ); return( -1 ); } #if defined( HAVE_PROFILER ) if( index->io_handle->profiler != NULL ) { if( libfsntfs_index_root_header_get_index_entry_size( index->root_header, &index_entry_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve index entry size.", function ); return( -1 ); } if( libfsntfs_profiler_start_timing( index->io_handle->profiler, &profiler_start_timestamp, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to start timing.", function ); return( -1 ); } } #endif /* defined( HAVE_PROFILER ) */ if( libfdata_vector_get_element_value_at_offset( index->index_entry_vector, (intptr_t *) file_io_handle, (libfdata_cache_t *) index_node_cache, index_entry_offset, &element_data_offset, (intptr_t **) index_node, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve index node from index entry with VCN: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").", function, sub_node_vcn, index_entry_offset, index_entry_offset ); return( -1 ); } #if defined( HAVE_PROFILER ) if( index->io_handle->profiler != NULL ) { if( libfsntfs_profiler_stop_timing( index->io_handle->profiler, profiler_start_timestamp, function, index_entry_offset, index_entry_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to stop timing.", function ); return( -1 ); } } #endif /* defined( HAVE_PROFILER ) */ return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_index.h ================================================ /* * Index functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_INDEX_H ) #define _LIBFSNTFS_INDEX_H #include #include #include "libfsntfs_bitmap_values.h" #include "libfsntfs_index_node.h" #include "libfsntfs_index_root_header.h" #include "libfsntfs_index_value.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfcache.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_mft_entry.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_index libfsntfs_index_t; struct libfsntfs_index { /* The IO handle */ libfsntfs_io_handle_t *io_handle; /* The name */ uint8_t *name; /* The name size */ size_t name_size; /* The flags */ uint32_t flags; /* The root header */ libfsntfs_index_root_header_t *root_header; /* The root node */ libfsntfs_index_node_t *root_node; /* The index entry vector */ libfdata_vector_t *index_entry_vector; /* The index node cache */ libfcache_cache_t *index_node_cache; /* The bitmap values */ libfsntfs_bitmap_values_t *bitmap_values; }; int libfsntfs_index_initialize( libfsntfs_index_t **index, libfsntfs_io_handle_t *io_handle, const uint8_t *name, size_t name_size, libcerror_error_t **error ); int libfsntfs_index_free( libfsntfs_index_t **index, libcerror_error_t **error ); int libfsntfs_index_read( libfsntfs_index_t *index, libbfio_handle_t *file_io_handle, libfsntfs_mft_entry_t *mft_entry, uint8_t flags, libcerror_error_t **error ); int libfsntfs_index_read_root_header( libfsntfs_index_t *index, libfsntfs_mft_attribute_t *index_root_attribute, libcerror_error_t **error ); int libfsntfs_index_read_root_node( libfsntfs_index_t *index, libfsntfs_mft_attribute_t *index_root_attribute, libcerror_error_t **error ); int libfsntfs_index_read_bitmap( libfsntfs_index_t *index, libbfio_handle_t *file_io_handle, libfsntfs_mft_attribute_t *bitmap_attribute, uint8_t flags, libcerror_error_t **error ); int libfsntfs_index_get_index_entry_size( libfsntfs_index_t *index, uint32_t *index_entry_size, libcerror_error_t **error ); int libfsntfs_index_get_attribute_type( libfsntfs_index_t *index, uint32_t *attribute_type, libcerror_error_t **error ); int libfsntfs_index_get_collation_type( libfsntfs_index_t *index, uint32_t *collation_type, libcerror_error_t **error ); int libfsntfs_index_sub_node_is_allocated( libfsntfs_index_t *index, int sub_node_vcn, libcerror_error_t **error ); int libfsntfs_index_get_sub_node( libfsntfs_index_t *index, libbfio_handle_t *file_io_handle, libfcache_cache_t *index_node_cache, off64_t index_entry_offset, int sub_node_vcn, libfsntfs_index_node_t **index_node, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_INDEX_H ) */ ================================================ FILE: libfsntfs/libfsntfs_index_entry.c ================================================ /* * Index entry entry functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_fixup_values.h" #include "libfsntfs_index_entry.h" #include "libfsntfs_index_entry_header.h" #include "libfsntfs_index_node.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "fsntfs_index.h" /* Creates an index entry * Make sure the value index_entry is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_index_entry_initialize( libfsntfs_index_entry_t **index_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_index_entry_initialize"; if( index_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index entry.", function ); return( -1 ); } if( *index_entry != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid index entry value already set.", function ); return( -1 ); } *index_entry = memory_allocate_structure( libfsntfs_index_entry_t ); if( *index_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create index entry.", function ); goto on_error; } if( memory_set( *index_entry, 0, sizeof( libfsntfs_index_entry_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear index entry.", function ); memory_free( *index_entry ); *index_entry = NULL; return( -1 ); } return( 1 ); on_error: if( *index_entry != NULL ) { memory_free( *index_entry ); *index_entry = NULL; } return( -1 ); } /* Frees an index entry * Returns 1 if successful or -1 on error */ int libfsntfs_index_entry_free( libfsntfs_index_entry_t **index_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_index_entry_free"; int result = 1; if( index_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index entry.", function ); return( -1 ); } if( *index_entry != NULL ) { if( ( *index_entry )->node != NULL ) { if( libfsntfs_index_node_free( &( ( *index_entry )->node ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free index node.", function ); result = -1; } } memory_free( *index_entry ); *index_entry = NULL; } return( result ); } /* Reads the index entry * Returns 1 if successful or -1 on error */ int libfsntfs_index_entry_read_file_io_handle( libfsntfs_index_entry_t *index_entry, libbfio_handle_t *file_io_handle, off64_t file_offset, uint32_t index_entry_size, uint32_t index_entry_index, libcerror_error_t **error ) { libfsntfs_index_entry_header_t *index_entry_header = NULL; uint8_t *index_entry_data = NULL; static char *function = "libfsntfs_index_entry_read_file_io_handle"; size_t data_offset = 0; size_t index_node_size = 0; size_t index_values_offset = 0; size_t unknown_data_size = 0; ssize_t read_count = 0; off64_t index_value_vcn_offset = 0; uint16_t fixup_values_offset = 0; uint16_t number_of_fixup_values = 0; if( index_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index entry.", function ); return( -1 ); } if( index_entry->node != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid index entry - node value already set.", function ); return( -1 ); } if( ( index_entry_size < ( sizeof( fsntfs_index_entry_header_t ) + sizeof( fsntfs_index_node_header_t ) ) ) || ( index_entry_size > MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid IO handle - index entry size value out of bounds.", function ); goto on_error; } index_entry_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * index_entry_size ); if( index_entry_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create index entry data.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading index entry: %" PRIu32 " at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, index_entry_index, file_offset, file_offset ); } #endif read_count = libbfio_handle_read_buffer_at_offset( file_io_handle, index_entry_data, (size_t) index_entry_size, file_offset, error ); if( read_count != (ssize_t) index_entry_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read index entry: %" PRIu32 " data at offset: %" PRIi64 " (0x%08" PRIx64 ").", function, index_entry_index, file_offset, file_offset ); goto on_error; } if( libfsntfs_index_entry_header_initialize( &index_entry_header, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create index entry header.", function ); goto on_error; } if( libfsntfs_index_entry_header_read_data( index_entry_header, index_entry_data, (size_t) index_entry_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read index entry header.", function ); goto on_error; } data_offset = sizeof( fsntfs_index_entry_header_t ); if( libfsntfs_index_node_initialize( &( index_entry->node ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create index node.", function ); goto on_error; } if( libfsntfs_index_node_read_header( index_entry->node, index_entry_data, (size_t) index_entry_size, data_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read index node header.", function ); goto on_error; } data_offset += sizeof( fsntfs_index_node_header_t ); if( libfsntfs_index_entry_header_get_fixup_values_offset( index_entry_header, &fixup_values_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve fix-up values offset.", function ); goto on_error; } /* TODO check bounds of index_values_offset */ index_values_offset = (size_t) index_entry->node->header->index_values_offset + sizeof( fsntfs_index_entry_header_t ); if( fixup_values_offset > index_values_offset ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: fix-up values offset exceeds index values offset.", function ); goto on_error; } if( data_offset < fixup_values_offset ) { unknown_data_size = (size_t) fixup_values_offset - data_offset; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: unknown data:\n", function ); libcnotify_print_data( &( index_entry_data[ data_offset ] ), unknown_data_size, 0 ); } #endif data_offset += unknown_data_size; } if( libfsntfs_index_entry_header_get_number_of_fixup_values( index_entry_header, &number_of_fixup_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of fix-up values.", function ); goto on_error; } if( number_of_fixup_values > 0 ) { if( libfsntfs_fixup_values_apply( index_entry_data, (size_t) index_entry_size, fixup_values_offset, number_of_fixup_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to apply fix-up values.", function ); goto on_error; } data_offset += 2 + ( (size_t) number_of_fixup_values * 2 ); } if( libfsntfs_index_entry_header_free( &index_entry_header, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free index entry header.", function ); goto on_error; } index_value_vcn_offset = (off64_t) index_entry_index * index_entry_size; if( libfsntfs_index_node_read_values( index_entry->node, index_value_vcn_offset, index_entry_data, (size_t) index_entry_size, data_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read index node values.", function ); goto on_error; } /* TODO refactor */ index_node_size = (size_t) index_entry->node->header->size - sizeof( fsntfs_index_node_header_t ); if( data_offset < (size_t) index_values_offset ) { unknown_data_size = (size_t) index_values_offset - data_offset; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: unknown data:\n", function ); libcnotify_print_data( &( index_entry_data[ data_offset ] ), unknown_data_size, 0 ); } #endif data_offset += unknown_data_size; index_node_size -= unknown_data_size; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { data_offset += index_node_size; if( data_offset < (size_t) index_entry_size ) { libcnotify_printf( "%s: trailing data:\n", function ); libcnotify_print_data( &( index_entry_data[ data_offset ] ), (size_t) index_entry_size - data_offset, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } } #endif memory_free( index_entry_data ); return( 1 ); on_error: if( index_entry->node != NULL ) { libfsntfs_index_node_free( &( index_entry->node ), NULL ); } if( index_entry_header != NULL ) { libfsntfs_index_entry_header_free( &index_entry_header, NULL ); } if( index_entry_data != NULL ) { memory_free( index_entry_data ); } return( -1 ); } ================================================ FILE: libfsntfs/libfsntfs_index_entry.h ================================================ /* * Index entry functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_INDEX_ENTRY_H ) #define _LIBFSNTFS_INDEX_ENTRY_H #include #include #include "libfsntfs_index_node.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_index_entry libfsntfs_index_entry_t; struct libfsntfs_index_entry { /* The index node */ libfsntfs_index_node_t *node; }; int libfsntfs_index_entry_initialize( libfsntfs_index_entry_t **index_entry, libcerror_error_t **error ); int libfsntfs_index_entry_free( libfsntfs_index_entry_t **index_entry, libcerror_error_t **error ); int libfsntfs_index_entry_read_file_io_handle( libfsntfs_index_entry_t *index_entry, libbfio_handle_t *file_io_handle, off64_t file_offset, uint32_t index_entry_size, uint32_t index_entry_index, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_INDEX_ENTRY_H ) */ ================================================ FILE: libfsntfs/libfsntfs_index_entry_header.c ================================================ /* * The NTFS index entry header functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_debug.h" #include "libfsntfs_index_entry_header.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "fsntfs_index.h" const char fsntfs_index_entry_signature[ 4 ] = { 'I', 'N', 'D', 'X' }; /* Creates an index entry header * Make sure the value index_entry_header is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_index_entry_header_initialize( libfsntfs_index_entry_header_t **index_entry_header, libcerror_error_t **error ) { static char *function = "libfsntfs_index_entry_header_initialize"; if( index_entry_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index entry header.", function ); return( -1 ); } if( *index_entry_header != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid index entry header value already set.", function ); return( -1 ); } *index_entry_header = memory_allocate_structure( libfsntfs_index_entry_header_t ); if( *index_entry_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create index entry header.", function ); goto on_error; } if( memory_set( *index_entry_header, 0, sizeof( libfsntfs_index_entry_header_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear index entry header.", function ); goto on_error; } return( 1 ); on_error: if( *index_entry_header != NULL ) { memory_free( *index_entry_header ); *index_entry_header = NULL; } return( -1 ); } /* Frees an index entry header * Returns 1 if successful or -1 on error */ int libfsntfs_index_entry_header_free( libfsntfs_index_entry_header_t **index_entry_header, libcerror_error_t **error ) { static char *function = "libfsntfs_index_entry_header_free"; if( index_entry_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index entry header.", function ); return( -1 ); } if( *index_entry_header != NULL ) { memory_free( *index_entry_header ); *index_entry_header = NULL; } return( 1 ); } /* Reads the index entry header * Returns 1 if successful or -1 on error */ int libfsntfs_index_entry_header_read_data( libfsntfs_index_entry_header_t *index_entry_header, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_index_entry_header_read_data"; #if defined( HAVE_DEBUG_OUTPUT ) uint64_t value_64bit = 0; #endif if( index_entry_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index entry header.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( ( data_size < sizeof( fsntfs_index_entry_header_t ) ) || ( data_size > (size_t) SSIZE_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: index entry header data:\n", function ); libcnotify_print_data( data, sizeof( fsntfs_index_entry_header_t ), 0 ); } #endif if( memory_compare( ( (fsntfs_index_entry_header_t *) data )->signature, fsntfs_index_entry_signature, 4 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: invalid index entry signature.", function ); return( -1 ); } byte_stream_copy_to_uint16_little_endian( ( (fsntfs_index_entry_header_t *) data )->fixup_values_offset, index_entry_header->fixup_values_offset ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_index_entry_header_t *) data )->number_of_fixup_values, index_entry_header->number_of_fixup_values ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: signature\t\t\t: %c%c%c%c\n", function, ( (fsntfs_index_entry_header_t *) data )->signature[ 0 ], ( (fsntfs_index_entry_header_t *) data )->signature[ 1 ], ( (fsntfs_index_entry_header_t *) data )->signature[ 2 ], ( (fsntfs_index_entry_header_t *) data )->signature[ 3 ] ); libcnotify_printf( "%s: fixup values offset\t\t: %" PRIu16 "\n", function, index_entry_header->fixup_values_offset ); libcnotify_printf( "%s: number of fixup values\t\t: %" PRIu16 "\n", function, index_entry_header->number_of_fixup_values ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_index_entry_header_t *) data )->journal_sequence_number, value_64bit ); libcnotify_printf( "%s: journal sequence number\t\t: %" PRIu64 "\n", function, value_64bit ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_index_entry_header_t *) data )->vcn, value_64bit ); libcnotify_printf( "%s: VCN\t\t\t\t: %" PRIu64 "\n", function, value_64bit ); libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ if( index_entry_header->fixup_values_offset < ( sizeof( fsntfs_index_entry_header_t ) + sizeof( fsntfs_index_node_header_t ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid fix-up values offset value out of bounds.", function ); return( -1 ); } return( 1 ); } /* Retrieves the fix-up values offset * Returns 1 if successful or -1 on error */ int libfsntfs_index_entry_header_get_fixup_values_offset( libfsntfs_index_entry_header_t *index_entry_header, uint16_t *fixup_values_offset, libcerror_error_t **error ) { static char *function = "libfsntfs_index_entry_header_get_fixup_values_offset"; if( index_entry_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index entry header.", function ); return( -1 ); } if( fixup_values_offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid fix-up values offset.", function ); return( -1 ); } *fixup_values_offset = index_entry_header->fixup_values_offset; return( 1 ); } /* Retrieves the number of fix-up values * Returns 1 if successful or -1 on error */ int libfsntfs_index_entry_header_get_number_of_fixup_values( libfsntfs_index_entry_header_t *index_entry_header, uint16_t *number_of_fixup_values, libcerror_error_t **error ) { static char *function = "libfsntfs_index_entry_header_get_number_of_fixup_values"; if( index_entry_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index entry header.", function ); return( -1 ); } if( number_of_fixup_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid number of fix-up values.", function ); return( -1 ); } *number_of_fixup_values = index_entry_header->number_of_fixup_values; return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_index_entry_header.h ================================================ /* * The NTFS index entry header functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_INDEX_ENTRY_HEADER_H ) #define _LIBFSNTFS_INDEX_ENTRY_HEADER_H #include #include #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_index_entry_header libfsntfs_index_entry_header_t; struct libfsntfs_index_entry_header { /* The fix-up values offset */ uint16_t fixup_values_offset; /* The number of fix-up values */ uint16_t number_of_fixup_values; }; int libfsntfs_index_entry_header_initialize( libfsntfs_index_entry_header_t **index_entry_header, libcerror_error_t **error ); int libfsntfs_index_entry_header_free( libfsntfs_index_entry_header_t **index_entry_header, libcerror_error_t **error ); int libfsntfs_index_entry_header_read_data( libfsntfs_index_entry_header_t *index_entry_header, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_index_entry_header_get_fixup_values_offset( libfsntfs_index_entry_header_t *index_entry_header, uint16_t *fixup_values_offset, libcerror_error_t **error ); int libfsntfs_index_entry_header_get_number_of_fixup_values( libfsntfs_index_entry_header_t *index_entry_header, uint16_t *number_of_fixup_values, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_INDEX_ENTRY_HEADER_H ) */ ================================================ FILE: libfsntfs/libfsntfs_index_entry_vector.c ================================================ /* * The index entry vector functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include "libfsntfs_data_run.h" #include "libfsntfs_definitions.h" #include "libfsntfs_index_entry.h" #include "libfsntfs_index_entry_vector.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_unused.h" /* Creates an index entry vector * Make sure the value index_entry_vector is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_index_entry_vector_initialize( libfdata_vector_t **index_entry_vector, libfsntfs_io_handle_t *io_handle, libfsntfs_mft_attribute_t *mft_attribute, uint32_t index_entry_size, libcerror_error_t **error ) { libfdata_vector_t *safe_index_entry_vector = NULL; libfsntfs_data_run_t *data_run = NULL; static char *function = "libfsntfs_index_entry_vector_initialize"; size64_t attribute_data_vcn_size = 0; size64_t calculated_allocated_data_size = 0; size64_t stored_allocated_data_size = 0; off64_t attribute_data_vcn_offset = 0; off64_t calculated_attribute_data_vcn_offset = 0; uint16_t attribute_data_flags = 0; int attribute_index = 0; int entry_index = 0; int number_of_entries = 0; int segment_index = 0; if( index_entry_vector == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index entry vector.", function ); return( -1 ); } if( *index_entry_vector != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid index entry vector value already set.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( io_handle->cluster_block_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid IO handle - cluster block size value out of bounds.", function ); return( -1 ); } if( index_entry_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid index entry size value out of bounds.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_data_flags( mft_attribute, &attribute_data_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute data flags.", function ); goto on_error; } if( ( attribute_data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported compressed attribute data.", function ); goto on_error; } if( libfsntfs_mft_attribute_get_allocated_data_size( mft_attribute, &stored_allocated_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute allocated data size.", function ); goto on_error; } if( libfdata_vector_initialize( &safe_index_entry_vector, (size64_t) index_entry_size, NULL, NULL, NULL, (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsntfs_index_entry_vector_read_element_data, NULL, LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create index entry vector.", function ); goto on_error; } while( mft_attribute != NULL ) { if( libfsntfs_mft_attribute_get_data_vcn_range( mft_attribute, (uint64_t *) &attribute_data_vcn_offset, (uint64_t *) &attribute_data_vcn_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute data VCN range.", function ); goto on_error; } if( attribute_data_vcn_size != 0xffffffffffffffffULL ) { if( (uint64_t) attribute_data_vcn_offset > (uint64_t) ( ( INT64_MAX / io_handle->cluster_block_size ) - 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data first VCN value out of bounds.", function ); goto on_error; } if( attribute_data_vcn_size > (size64_t) ( ( INT64_MAX / io_handle->cluster_block_size ) - 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data last VCN value out of bounds.", function ); goto on_error; } if( attribute_data_vcn_offset > (off64_t) attribute_data_vcn_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data first VCN value out of bounds.", function ); goto on_error; } attribute_data_vcn_size += 1; attribute_data_vcn_size -= attribute_data_vcn_offset; attribute_data_vcn_offset *= io_handle->cluster_block_size; attribute_data_vcn_size *= io_handle->cluster_block_size; if( ( calculated_attribute_data_vcn_offset != 0 ) && ( calculated_attribute_data_vcn_offset != attribute_data_vcn_offset ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data VCN offset value out of bounds.", function ); goto on_error; } calculated_attribute_data_vcn_offset = attribute_data_vcn_offset + (off64_t) attribute_data_vcn_size; } if( libfsntfs_mft_attribute_get_number_of_data_runs( mft_attribute, &number_of_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d number of data runs.", function, attribute_index ); goto on_error; } for( entry_index = 0; entry_index < number_of_entries; entry_index++ ) { if( libfsntfs_mft_attribute_get_data_run_by_index( mft_attribute, entry_index, &data_run, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d data run: %d.", function, attribute_index, entry_index ); goto on_error; } if( data_run == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing attribute: %d data run: %d.", function, attribute_index, entry_index ); goto on_error; } if( libfdata_vector_append_segment( safe_index_entry_vector, &segment_index, 0, data_run->start_offset, data_run->size, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append attribute: %d data run: %d vector segment.", function, attribute_index, entry_index ); goto on_error; } calculated_allocated_data_size += data_run->size; } attribute_index++; if( libfsntfs_mft_attribute_get_next_attribute( mft_attribute, &mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve next MFT attribute: %d.", function, attribute_index ); goto on_error; } } if( calculated_allocated_data_size != stored_allocated_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: size of data runs: %" PRIu64 " does not match allocated data size: %" PRIu64 ".", function, calculated_allocated_data_size, stored_allocated_data_size ); goto on_error; } *index_entry_vector = safe_index_entry_vector; return( 1 ); on_error: if( safe_index_entry_vector != NULL ) { libfdata_vector_free( &safe_index_entry_vector, NULL ); } return( -1 ); } /* Reads the index entry * Callback function for the index entry vector * Returns 1 if successful or -1 on error */ int libfsntfs_index_entry_vector_read_element_data( intptr_t *data_handle LIBFSNTFS_ATTRIBUTE_UNUSED, libbfio_handle_t *file_io_handle, libfdata_vector_t *vector, libfdata_cache_t *cache, int element_index, int element_data_file_index LIBFSNTFS_ATTRIBUTE_UNUSED, off64_t index_entry_offset, size64_t index_entry_size, uint32_t element_flags LIBFSNTFS_ATTRIBUTE_UNUSED, uint8_t read_flags LIBFSNTFS_ATTRIBUTE_UNUSED, libcerror_error_t **error ) { libfsntfs_index_entry_t *index_entry = NULL; static char *function = "libfsntfs_index_entry_vector_read_element_data"; LIBFSNTFS_UNREFERENCED_PARAMETER( data_handle ) LIBFSNTFS_UNREFERENCED_PARAMETER( element_data_file_index ) LIBFSNTFS_UNREFERENCED_PARAMETER( element_flags ) LIBFSNTFS_UNREFERENCED_PARAMETER( read_flags ) if( (uint64_t) element_index > (uint64_t) UINT32_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid element index value out of bounds.", function ); return( -1 ); } if( (uint64_t) index_entry_size > (uint64_t) UINT32_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid index entry size value out of bounds.", function ); return( -1 ); } if( libfsntfs_index_entry_initialize( &index_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create index entry.", function ); goto on_error; } if( libfsntfs_index_entry_read_file_io_handle( index_entry, file_io_handle, index_entry_offset, (uint32_t) index_entry_size, (uint32_t) element_index, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read index entry: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").", function, element_index, index_entry_offset, index_entry_offset ); goto on_error; } if( libfdata_vector_set_element_value_by_index( vector, (intptr_t *) file_io_handle, cache, element_index, (intptr_t *) index_entry->node, (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_index_node_free, LIBFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set index node as element value.", function ); goto on_error; } index_entry->node = NULL; if( libfsntfs_index_entry_free( &index_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free index entry.", function ); goto on_error; } return( 1 ); on_error: if( index_entry != NULL ) { libfsntfs_index_entry_free( &index_entry, NULL ); } return( -1 ); } ================================================ FILE: libfsntfs/libfsntfs_index_entry_vector.h ================================================ /* * The index entry vector functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_INDEX_ENTRY_VECTOR_H ) #define _LIBFSNTFS_INDEX_ENTRY_VECTOR_H #include #include #include "libfsntfs_libbfio.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_attribute.h" #if defined( __cplusplus ) extern "C" { #endif int libfsntfs_index_entry_vector_initialize( libfdata_vector_t **index_entry_vector, libfsntfs_io_handle_t *io_handle, libfsntfs_mft_attribute_t *mft_attribute, uint32_t index_entry_size, libcerror_error_t **error ); int libfsntfs_index_entry_vector_read_element_data( intptr_t *data_handle, libbfio_handle_t *file_io_handle, libfdata_vector_t *vector, libfdata_cache_t *cache, int element_index, int element_file_index, off64_t index_entry_offset, size64_t index_entry_size, uint32_t element_flags, uint8_t read_flags, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_INDEX_ENTRY_VECTOR_H ) */ ================================================ FILE: libfsntfs/libfsntfs_index_node.c ================================================ /* * Index node functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_definitions.h" #include "libfsntfs_index_node.h" #include "libfsntfs_index_node_header.h" #include "libfsntfs_index_value.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "fsntfs_index.h" /* Creates an index node * Make sure the value index_node is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_index_node_initialize( libfsntfs_index_node_t **index_node, libcerror_error_t **error ) { static char *function = "libfsntfs_index_node_initialize"; if( index_node == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index node.", function ); return( -1 ); } if( *index_node != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid index node value already set.", function ); return( -1 ); } *index_node = memory_allocate_structure( libfsntfs_index_node_t ); if( *index_node == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create index node.", function ); goto on_error; } if( memory_set( *index_node, 0, sizeof( libfsntfs_index_node_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear index node.", function ); memory_free( *index_node ); *index_node = NULL; return( -1 ); } if( libcdata_array_initialize( &( ( *index_node )->values_array ), 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create values array.", function ); goto on_error; } return( 1 ); on_error: if( *index_node != NULL ) { memory_free( *index_node ); *index_node = NULL; } return( -1 ); } /* Frees an index node * Returns 1 if successful or -1 on error */ int libfsntfs_index_node_free( libfsntfs_index_node_t **index_node, libcerror_error_t **error ) { static char *function = "libfsntfs_index_node_free"; int result = 1; if( index_node == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index node.", function ); return( -1 ); } if( *index_node != NULL ) { if( ( *index_node )->header != NULL ) { if( libfsntfs_index_node_header_free( &( ( *index_node )->header ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free index node header.", function ); result = -1; } } if( libcdata_array_free( &( ( *index_node )->values_array ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_index_value_free, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free values array.", function ); result = -1; } memory_free( *index_node ); *index_node = NULL; } return( result ); } /* Reads the index node header * Returns 1 if successful or -1 on error */ int libfsntfs_index_node_read_header( libfsntfs_index_node_t *index_node, const uint8_t *data, size_t data_size, size_t data_offset, libcerror_error_t **error ) { static char *function = "libfsntfs_index_node_read_header"; if( index_node == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index node.", function ); return( -1 ); } if( index_node->header != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid index node - header value already set.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: data size value exceeds maximum.", function ); return( -1 ); } if( data_offset >= data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: data offset value out of bounds.", function ); return( -1 ); } if( libfsntfs_index_node_header_initialize( &( index_node->header ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create index node header.", function ); goto on_error; } if( libfsntfs_index_node_header_read_data( index_node->header, &( data[ data_offset ] ), data_size - data_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read index node header.", function ); goto on_error; } index_node->header_data_offset = data_offset; return( 1 ); on_error: if( index_node->header != NULL ) { libfsntfs_index_node_header_free( &( index_node->header ), NULL ); } return( -1 ); } /* Reads the index node values * Returns 1 if successful or -1 on error */ int libfsntfs_index_node_read_values( libfsntfs_index_node_t *index_node, off64_t index_value_vcn_offset, const uint8_t *data, size_t data_size, size_t data_offset, libcerror_error_t **error ) { libfsntfs_index_value_t *index_value = NULL; static char *function = "libfsntfs_index_node_read_values"; size_t index_node_size = 0; size_t index_values_offset = 0; size_t unknown_data_size = 0; ssize_t read_count = 0; uint32_t index_value_flags = 0; int entry_index = 0; int index_value_entry = 0; if( index_node == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index node.", function ); return( -1 ); } if( index_node->header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid index node - missing header value.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: data size value exceeds maximum.", function ); return( -1 ); } if( data_offset >= data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: data offset value out of bounds.", function ); return( -1 ); } index_values_offset = (size_t) index_node->header->index_values_offset; if( index_values_offset > ( data_size - index_node->header_data_offset ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid index values offset value out of bounds.", function ); return( -1 ); } index_values_offset += index_node->header_data_offset; index_node_size = index_node->header->size; if( ( index_node_size < sizeof( fsntfs_index_node_header_t ) ) || ( index_node_size > data_size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid index node size value out of bounds.", function ); goto on_error; } index_node_size -= sizeof( fsntfs_index_node_header_t ); if( index_node_size == 0 ) { return( 1 ); } if( data_offset < index_values_offset ) { unknown_data_size = (size_t) index_values_offset - data_offset; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: unknown data:\n", function ); libcnotify_print_data( &( data[ data_offset ] ), unknown_data_size, 0 ); } #endif data_offset += unknown_data_size; if( unknown_data_size > index_node_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid index values offset value out of bounds.", function ); goto on_error; } index_node_size -= (uint32_t) unknown_data_size; } while( index_node_size > 0 ) { if( libfsntfs_index_value_initialize( &index_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create index value.", function ); goto on_error; } read_count = libfsntfs_index_value_read( index_value, index_value_vcn_offset + data_offset, &index_value_entry, data, data_size, data_offset, error ); if( read_count == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read index value.", function ); goto on_error; } data_offset += read_count; index_node_size -= (uint32_t) read_count; index_value_flags = index_value->flags; if( libcdata_array_append_entry( index_node->values_array, &entry_index, (intptr_t *) index_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append index value to values array.", function ); goto on_error; } index_value = NULL; if( ( index_value_flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_LAST ) != 0 ) { break; } } #if defined( HAVE_DEBUG_OUTPUT ) if( index_node_size > 0 ) { if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: trailing data:\n", function ); libcnotify_print_data( &( data[ data_offset ] ), (size_t) index_node_size, 0 ); } data_offset += index_node_size; } #endif return( 1 ); on_error: if( index_value != NULL ) { libfsntfs_index_value_free( &index_value, NULL ); } return( -1 ); } /* Retrieves the number of values * Returns 1 if successful or -1 on error */ int libfsntfs_index_node_get_number_of_values( libfsntfs_index_node_t *index_node, int *number_of_values, libcerror_error_t **error ) { static char *function = "libfsntfs_index_node_get_number_of_values"; if( index_node == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index node.", function ); return( -1 ); } if( libcdata_array_get_number_of_entries( index_node->values_array, number_of_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of entries from values array.", function ); return( -1 ); } return( 1 ); } /* Retrieves a specific value * Returns 1 if successful or -1 on error */ int libfsntfs_index_node_get_value_by_index( libfsntfs_index_node_t *index_node, int value_entry, libfsntfs_index_value_t **value, libcerror_error_t **error ) { static char *function = "libfsntfs_index_node_get_value_by_index"; if( index_node == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index node.", function ); return( -1 ); } if( libcdata_array_get_entry_by_index( index_node->values_array, value_entry, (intptr_t **) value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry: %d from values array.", function, value_entry ); return( -1 ); } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_index_node.h ================================================ /* * Index node functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_INDEX_NODE_H ) #define _LIBFSNTFS_INDEX_NODE_H #include #include #include "libfsntfs_index_node_header.h" #include "libfsntfs_index_value.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_index_node libfsntfs_index_node_t; struct libfsntfs_index_node { /* The node header data offset */ size_t header_data_offset; /* The header */ libfsntfs_index_node_header_t *header; /* The values array */ libcdata_array_t *values_array; }; int libfsntfs_index_node_initialize( libfsntfs_index_node_t **index_node, libcerror_error_t **error ); int libfsntfs_index_node_free( libfsntfs_index_node_t **index_node, libcerror_error_t **error ); int libfsntfs_index_node_read_header( libfsntfs_index_node_t *index_node, const uint8_t *data, size_t data_size, size_t data_offset, libcerror_error_t **error ); int libfsntfs_index_node_read_values( libfsntfs_index_node_t *index_node, off64_t index_value_vcn_offset, const uint8_t *data, size_t data_size, size_t data_offset, libcerror_error_t **error ); int libfsntfs_index_node_get_number_of_values( libfsntfs_index_node_t *index_node, int *number_of_values, libcerror_error_t **error ); int libfsntfs_index_node_get_value_by_index( libfsntfs_index_node_t *index_node, int value_entry, libfsntfs_index_value_t **value, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_INDEX_NODE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_index_node_header.c ================================================ /* * Index node header functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_debug.h" #include "libfsntfs_definitions.h" #include "libfsntfs_index_node_header.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "fsntfs_index.h" /* Creates an index node header * Make sure the value index_node_header is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_index_node_header_initialize( libfsntfs_index_node_header_t **index_node_header, libcerror_error_t **error ) { static char *function = "libfsntfs_index_node_header_initialize"; if( index_node_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index node header.", function ); return( -1 ); } if( *index_node_header != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid index node header value already set.", function ); return( -1 ); } *index_node_header = memory_allocate_structure( libfsntfs_index_node_header_t ); if( *index_node_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create index node header.", function ); goto on_error; } if( memory_set( *index_node_header, 0, sizeof( libfsntfs_index_node_header_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear index node header.", function ); memory_free( *index_node_header ); *index_node_header = NULL; return( -1 ); } return( 1 ); on_error: if( *index_node_header != NULL ) { memory_free( *index_node_header ); *index_node_header = NULL; } return( -1 ); } /* Frees an index node header * Returns 1 if successful or -1 on error */ int libfsntfs_index_node_header_free( libfsntfs_index_node_header_t **index_node_header, libcerror_error_t **error ) { static char *function = "libfsntfs_index_node_header_free"; if( index_node_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index node header.", function ); return( -1 ); } if( *index_node_header != NULL ) { memory_free( *index_node_header ); *index_node_header = NULL; } return( 1 ); } /* Reads the index node header header * Returns the number of bytes read if successful or -1 on error */ int libfsntfs_index_node_header_read_data( libfsntfs_index_node_header_t *index_node_header, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_index_node_header_read_data"; #if defined( HAVE_DEBUG_OUTPUT ) uint32_t value_32bit = 0; #endif if( index_node_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index node header.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data.", function ); return( -1 ); } if( ( data_size < sizeof( fsntfs_index_node_header_t ) ) || ( data_size > (size_t) SSIZE_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: index node header header data:\n", function ); libcnotify_print_data( data, sizeof( fsntfs_index_node_header_t ), 0 ); } #endif byte_stream_copy_to_uint32_little_endian( ( (fsntfs_index_node_header_t *) data )->index_values_offset, index_node_header->index_values_offset ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_index_node_header_t *) data )->size, index_node_header->size ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_index_node_header_t *) data )->flags, index_node_header->flags ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: index values offset\t\t: %" PRIu32 "\n", function, index_node_header->index_values_offset ); libcnotify_printf( "%s: size\t\t\t\t: %" PRIu32 "\n", function, index_node_header->size ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_index_node_header_t *) data )->allocated_size, value_32bit ); libcnotify_printf( "%s: allocated size\t\t\t: %" PRIu32 "\n", function, value_32bit ); libcnotify_printf( "%s: flags\t\t\t\t: 0x%08" PRIx32 "\n", function, index_node_header->flags ); libfsntfs_debug_print_index_node_flags( index_node_header->flags ); libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ if( index_node_header->size > 0 ) { if( (size_t) index_node_header->size < sizeof( fsntfs_index_node_header_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid index node header size value out of bounds.", function ); return( -1 ); } if( ( (size_t) index_node_header->index_values_offset < sizeof( fsntfs_index_node_header_t ) ) || ( index_node_header->index_values_offset > index_node_header->size ) || ( ( index_node_header->index_values_offset % 8 ) != 0 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid index values offset value out of bounds.", function ); return( -1 ); } } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_index_node_header.h ================================================ /* * Index node header functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_INDEX_NODE_HEADER_H ) #define _LIBFSNTFS_INDEX_NODE_HEADER_H #include #include #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_index_node_header libfsntfs_index_node_header_t; struct libfsntfs_index_node_header { /* The size */ uint32_t size; /* The index values offset */ uint32_t index_values_offset; /* The flags */ uint32_t flags; }; int libfsntfs_index_node_header_initialize( libfsntfs_index_node_header_t **index_node_header, libcerror_error_t **error ); int libfsntfs_index_node_header_free( libfsntfs_index_node_header_t **index_node_header, libcerror_error_t **error ); int libfsntfs_index_node_header_read_data( libfsntfs_index_node_header_t *index_node_header, const uint8_t *data, size_t data_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_INDEX_NODE_HEADER_H ) */ ================================================ FILE: libfsntfs/libfsntfs_index_root_header.c ================================================ /* * The NTFS index root header functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_debug.h" #include "libfsntfs_index_root_header.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "fsntfs_index.h" /* Creates an index root header * Make sure the value index_root_header is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_index_root_header_initialize( libfsntfs_index_root_header_t **index_root_header, libcerror_error_t **error ) { static char *function = "libfsntfs_index_root_header_initialize"; if( index_root_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index root header.", function ); return( -1 ); } if( *index_root_header != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid index root header value already set.", function ); return( -1 ); } *index_root_header = memory_allocate_structure( libfsntfs_index_root_header_t ); if( *index_root_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create index root header.", function ); goto on_error; } if( memory_set( *index_root_header, 0, sizeof( libfsntfs_index_root_header_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear index root header.", function ); goto on_error; } return( 1 ); on_error: if( *index_root_header != NULL ) { memory_free( *index_root_header ); *index_root_header = NULL; } return( -1 ); } /* Frees an index root header * Returns 1 if successful or -1 on error */ int libfsntfs_index_root_header_free( libfsntfs_index_root_header_t **index_root_header, libcerror_error_t **error ) { static char *function = "libfsntfs_index_root_header_free"; if( index_root_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index root header.", function ); return( -1 ); } if( *index_root_header != NULL ) { memory_free( *index_root_header ); *index_root_header = NULL; } return( 1 ); } /* Reads the index root header * Returns 1 if successful or -1 on error */ int libfsntfs_index_root_header_read_data( libfsntfs_index_root_header_t *index_root_header, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_index_root_header_read_data"; #if defined( HAVE_DEBUG_OUTPUT ) uint32_t value_32bit = 0; #endif if( index_root_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index root header.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( ( data_size < sizeof( fsntfs_index_root_header_t ) ) || ( data_size > (size_t) SSIZE_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: index root header data:\n", function ); libcnotify_print_data( data, sizeof( fsntfs_index_root_header_t ), 0 ); } #endif byte_stream_copy_to_uint32_little_endian( ( (fsntfs_index_root_header_t *) data )->attribute_type, index_root_header->attribute_type ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_index_root_header_t *) data )->collation_type, index_root_header->collation_type ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_index_root_header_t *) data )->index_entry_size, index_root_header->index_entry_size ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: attribute type\t\t\t\t: 0x%08" PRIx32 " (%s)\n", function, index_root_header->attribute_type, libfsntfs_debug_print_attribute_type( index_root_header->attribute_type ) ); libcnotify_printf( "%s: collation type\t\t\t\t: 0x%08" PRIx32 " (%s)\n", function, index_root_header->collation_type, libfsntfs_debug_print_collation_type( index_root_header->collation_type ) ); libcnotify_printf( "%s: index entry size\t\t\t\t: %" PRIu32 "\n", function, index_root_header->index_entry_size ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_index_root_header_t *) data )->index_entry_number_of_cluster_blocks, value_32bit ); libcnotify_printf( "%s: index entry number of cluster blocks\t: %" PRIu32 "\n", function, value_32bit ); libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ return( 1 ); } /* Retrieves the index entry size * Returns 1 if successful or -1 on error */ int libfsntfs_index_root_header_get_index_entry_size( libfsntfs_index_root_header_t *index_root_header, uint32_t *index_entry_size, libcerror_error_t **error ) { static char *function = "libfsntfs_index_root_header_get_index_entry_size"; if( index_root_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index root header.", function ); return( -1 ); } if( index_entry_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index entry size.", function ); return( -1 ); } *index_entry_size = index_root_header->index_entry_size; return( 1 ); } /* Retrieves the attribute type * Returns 1 if successful or -1 on error */ int libfsntfs_index_root_header_get_attribute_type( libfsntfs_index_root_header_t *index_root_header, uint32_t *attribute_type, libcerror_error_t **error ) { static char *function = "libfsntfs_index_root_header_get_attribute_type"; if( index_root_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index root header.", function ); return( -1 ); } if( attribute_type == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute type.", function ); return( -1 ); } *attribute_type = index_root_header->attribute_type; return( 1 ); } /* Retrieves the collation type * Returns 1 if successful or -1 on error */ int libfsntfs_index_root_header_get_collation_type( libfsntfs_index_root_header_t *index_root_header, uint32_t *collation_type, libcerror_error_t **error ) { static char *function = "libfsntfs_index_root_header_get_collation_type"; if( index_root_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index root header.", function ); return( -1 ); } if( collation_type == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid collation type.", function ); return( -1 ); } *collation_type = index_root_header->collation_type; return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_index_root_header.h ================================================ /* * The NTFS index root header functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_INDEX_ROOT_HEADER_H ) #define _LIBFSNTFS_INDEX_ROOT_HEADER_H #include #include #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_index_root_header libfsntfs_index_root_header_t; struct libfsntfs_index_root_header { /* The index entry size */ uint32_t index_entry_size; /* The attribute type */ uint32_t attribute_type; /* The collation type */ uint32_t collation_type; }; int libfsntfs_index_root_header_initialize( libfsntfs_index_root_header_t **index_root_header, libcerror_error_t **error ); int libfsntfs_index_root_header_free( libfsntfs_index_root_header_t **index_root_header, libcerror_error_t **error ); int libfsntfs_index_root_header_read_data( libfsntfs_index_root_header_t *index_root_header, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_index_root_header_get_index_entry_size( libfsntfs_index_root_header_t *index_root_header, uint32_t *index_entry_size, libcerror_error_t **error ); int libfsntfs_index_root_header_get_attribute_type( libfsntfs_index_root_header_t *index_root_header, uint32_t *attribute_type, libcerror_error_t **error ); int libfsntfs_index_root_header_get_collation_type( libfsntfs_index_root_header_t *index_root_header, uint32_t *collation_type, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_INDEX_ROOT_HEADER_H ) */ ================================================ FILE: libfsntfs/libfsntfs_index_value.c ================================================ /* * Index value functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_debug.h" #include "libfsntfs_definitions.h" #include "libfsntfs_index_value.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "fsntfs_index.h" /* Creates an index value * Make sure the value index_value is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_index_value_initialize( libfsntfs_index_value_t **index_value, libcerror_error_t **error ) { static char *function = "libfsntfs_index_value_initialize"; if( index_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index value.", function ); return( -1 ); } if( *index_value != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid index value value already set.", function ); return( -1 ); } *index_value = memory_allocate_structure( libfsntfs_index_value_t ); if( *index_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create index value.", function ); goto on_error; } if( memory_set( *index_value, 0, sizeof( libfsntfs_index_value_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear index value.", function ); memory_free( *index_value ); *index_value = NULL; return( -1 ); } return( 1 ); on_error: if( *index_value != NULL ) { memory_free( *index_value ); *index_value = NULL; } return( -1 ); } /* Frees an index value * Returns 1 if successful or -1 on error */ int libfsntfs_index_value_free( libfsntfs_index_value_t **index_value, libcerror_error_t **error ) { static char *function = "libfsntfs_index_value_free"; if( index_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index value.", function ); return( -1 ); } if( *index_value != NULL ) { if( ( *index_value )->key_data != NULL ) { memory_free( ( *index_value )->key_data ); } if( ( *index_value )->value_data != NULL ) { memory_free( ( *index_value )->value_data ); } memory_free( *index_value ); *index_value = NULL; } return( 1 ); } /* Reads the index value * Returns the number of bytes read if successful or -1 on error */ ssize_t libfsntfs_index_value_read( libfsntfs_index_value_t *index_value, off64_t index_value_vcn_offset, int *index_value_entry, const uint8_t *data, size_t data_size, size_t data_offset, libcerror_error_t **error ) { static char *function = "libfsntfs_index_value_read"; uint32_t remaining_size = 0; if( index_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index value.", function ); return( -1 ); } if( index_value_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index value entry.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: data size value exceeds maximum.", function ); return( -1 ); } if( data_offset > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: data offset value exceeds maximum.", function ); return( -1 ); } if( data_offset >= data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: data offset value out of bounds.", function ); return( -1 ); } if( ( data_size < sizeof( fsntfs_index_value_t ) ) || ( data_offset > ( data_size - sizeof( fsntfs_index_value_t ) ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: data size value too small.", function ); return( -1 ); } index_value->offset = index_value_vcn_offset; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: index value: %03d header data:\n", function, *index_value_entry ); libcnotify_print_data( &( data[ data_offset ] ), sizeof( fsntfs_index_value_t ), 0 ); } #endif byte_stream_copy_to_uint64_little_endian( ( (fsntfs_index_value_t *) &( data[ data_offset ] ) )->file_reference, index_value->file_reference ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_index_value_t *) &( data[ data_offset ] ) )->size, index_value->size ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_index_value_t *) &( data[ data_offset ] ) )->key_data_size, index_value->key_data_size ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_index_value_t *) &( data[ data_offset ] ) )->flags, index_value->flags ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: index value: %03d file reference\t\t: %" PRIu64 "-%" PRIu64 "\n", function, *index_value_entry, index_value->file_reference & 0xffffffffffffUL, index_value->file_reference >> 48 ); libcnotify_printf( "%s: index value: %03d offset\t\t\t: %" PRIi64 " (0x%08" PRIx64 ")\n", function, *index_value_entry, index_value->offset, index_value->offset ); libcnotify_printf( "%s: index value: %03d size\t\t\t: %" PRIu16 "\n", function, *index_value_entry, index_value->size ); libcnotify_printf( "%s: index value: %03d key data size\t\t: %" PRIu16 "\n", function, *index_value_entry, index_value->key_data_size ); libcnotify_printf( "%s: index value: %03d flags\t\t\t: 0x%08" PRIx32 "\n", function, *index_value_entry, index_value->flags ); libfsntfs_debug_print_index_value_flags( index_value->flags ); libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ data_offset += sizeof( fsntfs_index_value_t ); if( ( (size_t) index_value->size < sizeof( fsntfs_index_value_t ) ) || ( (size_t) index_value->size > data_size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: index value: %03d size exceeds data size.", function, *index_value_entry ); goto on_error; } remaining_size = (size_t) index_value->size - sizeof( fsntfs_index_value_t ); if( index_value->key_data_size > 0 ) { if( (uint32_t) index_value->key_data_size > remaining_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: index value: %03d data size exceeds size.", function, *index_value_entry ); goto on_error; } index_value->key_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * index_value->key_data_size ); if( index_value->key_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create index value: %03d key data.", function, *index_value_entry ); goto on_error; } if( data_offset > ( data_size - index_value->key_data_size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: data size value too small.", function ); goto on_error; } if( memory_copy( index_value->key_data, &( data[ data_offset ] ), (size_t) index_value->key_data_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy index value: %03d data.", function, *index_value_entry ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: index value: %03d key data:\n", function, *index_value_entry ); libcnotify_print_data( &( data[ data_offset ] ), (size_t) index_value->key_data_size, 0 ); } #endif data_offset += index_value->key_data_size; remaining_size -= index_value->key_data_size; } if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 ) { if( remaining_size < 8 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: index value: %03d sub node data size exceeds size.", function, *index_value_entry ); goto on_error; } remaining_size -= 8; } if( remaining_size > 0 ) { index_value->value_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * remaining_size ); if( index_value->value_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create index value: %03d value data.", function, *index_value_entry ); goto on_error; } index_value->value_data_size = remaining_size; if( data_offset > ( data_size - index_value->value_data_size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: data size value too small.", function ); goto on_error; } if( memory_copy( index_value->value_data, &( data[ data_offset ] ), (size_t) index_value->value_data_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy index value: %03d data.", function, *index_value_entry ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: index value: %03d value data:\n", function, *index_value_entry ); libcnotify_print_data( index_value->value_data, (size_t) index_value->value_data_size, 0 ); } #endif data_offset += remaining_size; } if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: index value: %03d sub node VCN data:\n", function, *index_value_entry ); libcnotify_print_data( &( data[ data_offset ] ), 8, 0 ); } #endif if( data_offset > ( data_size - 8 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: data size value too small.", function ); goto on_error; } byte_stream_copy_to_uint64_little_endian( &( data[ data_offset ] ), index_value->sub_node_vcn ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: index value: %03d sub node VCN\t\t: %" PRIu64 "\n", function, *index_value_entry, index_value->sub_node_vcn ); libcnotify_printf( "\n" ); } #endif } *index_value_entry += 1; return( (ssize_t) index_value->size ); on_error: if( index_value->value_data != NULL ) { memory_free( index_value->value_data ); index_value->value_data = NULL; } index_value->value_data_size = 0; if( index_value->key_data != NULL ) { memory_free( index_value->key_data ); index_value->key_data = NULL; } index_value->key_data_size = 0; return( -1 ); } ================================================ FILE: libfsntfs/libfsntfs_index_value.h ================================================ /* * Index value functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_INDEX_VALUE_H ) #define _LIBFSNTFS_INDEX_VALUE_H #include #include #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_index_value libfsntfs_index_value_t; struct libfsntfs_index_value { /* The offset */ off64_t offset; /* The size */ uint32_t size; /* The key data */ uint8_t *key_data; /* The key data size */ uint16_t key_data_size; /* The value data */ uint8_t *value_data; /* The value data size */ uint32_t value_data_size; /* The file reference */ uint64_t file_reference; /* The flags */ uint32_t flags; /* The sub node virtual cluster number (VCN) */ uint64_t sub_node_vcn; }; int libfsntfs_index_value_initialize( libfsntfs_index_value_t **index_value, libcerror_error_t **error ); int libfsntfs_index_value_free( libfsntfs_index_value_t **index_value, libcerror_error_t **error ); ssize_t libfsntfs_index_value_read( libfsntfs_index_value_t *index_value, off64_t index_value_vcn_offset, int *index_value_entry, const uint8_t *data, size_t data_size, size_t data_offset, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_INDEX_VALUE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_io_handle.c ================================================ /* * Input/Output (IO) handle functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_io_handle.h" #include "libfsntfs_libcerror.h" const char *fsntfs_volume_file_system_signature = "NTFS "; /* Creates an IO handle * Make sure the value io_handle is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_io_handle_initialize( libfsntfs_io_handle_t **io_handle, libcerror_error_t **error ) { static char *function = "libfsntfs_io_handle_initialize"; if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( *io_handle != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid IO handle value already set.", function ); return( -1 ); } *io_handle = memory_allocate_structure( libfsntfs_io_handle_t ); if( *io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create IO handle.", function ); goto on_error; } if( memory_set( *io_handle, 0, sizeof( libfsntfs_io_handle_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear IO handle.", function ); memory_free( *io_handle ); *io_handle = NULL; return( -1 ); } #if defined( HAVE_PROFILER ) if( libfsntfs_profiler_initialize( &( ( *io_handle )->profiler ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize profiler.", function ); goto on_error; } if( libfsntfs_profiler_open( ( *io_handle )->profiler, "profiler.csv", error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open profiler.", function ); goto on_error; } #endif /* defined( HAVE_PROFILER ) */ return( 1 ); on_error: if( *io_handle != NULL ) { #if defined( HAVE_PROFILER ) if( ( *io_handle )->profiler != NULL ) { libfsntfs_profiler_free( &( ( *io_handle )->profiler ), NULL ); } #endif memory_free( *io_handle ); *io_handle = NULL; } return( -1 ); } /* Frees an IO handle * Returns 1 if successful or -1 on error */ int libfsntfs_io_handle_free( libfsntfs_io_handle_t **io_handle, libcerror_error_t **error ) { static char *function = "libfsntfs_io_handle_free"; int result = 1; if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( *io_handle != NULL ) { #if defined( HAVE_PROFILER ) if( libfsntfs_profiler_close( ( *io_handle )->profiler, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close profiler.", function ); result = -1; } if( libfsntfs_profiler_free( &( ( *io_handle )->profiler ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free profiler.", function ); result = -1; } #endif /* defined( HAVE_PROFILER ) */ memory_free( *io_handle ); *io_handle = NULL; } return( result ); } /* Clears the IO handle * Returns 1 if successful or -1 on error */ int libfsntfs_io_handle_clear( libfsntfs_io_handle_t *io_handle, libcerror_error_t **error ) { static char *function = "libfsntfs_io_handle_clear"; #if defined( HAVE_PROFILER ) libfsntfs_profiler_t *profiler = NULL; #endif if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } #if defined( HAVE_PROFILER ) profiler = io_handle->profiler; #endif if( memory_set( io_handle, 0, sizeof( libfsntfs_io_handle_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear IO handle.", function ); return( -1 ); } #if defined( HAVE_PROFILER ) io_handle->profiler = profiler; #endif return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_io_handle.h ================================================ /* * Input/Output (IO) handle functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_IO_HANDLE_H ) #define _LIBFSNTFS_IO_HANDLE_H #include #include #include "libfsntfs_libcerror.h" #include "libfsntfs_profiler.h" #if defined( __cplusplus ) extern "C" { #endif extern const char *fsntfs_volume_file_system_signature; typedef struct libfsntfs_io_handle libfsntfs_io_handle_t; struct libfsntfs_io_handle { /* The cluster block size */ size32_t cluster_block_size; /* The index entry size */ uint32_t index_entry_size; /* The MFT entry size */ uint32_t mft_entry_size; /* The number of bytes per sector */ uint16_t bytes_per_sector; #if defined( HAVE_PROFILER ) /* The profiler */ libfsntfs_profiler_t *profiler; #endif /* Value to indicate if abort was signalled */ int abort; }; int libfsntfs_io_handle_initialize( libfsntfs_io_handle_t **io_handle, libcerror_error_t **error ); int libfsntfs_io_handle_free( libfsntfs_io_handle_t **io_handle, libcerror_error_t **error ); int libfsntfs_io_handle_clear( libfsntfs_io_handle_t *io_handle, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_IO_HANDLE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_libbfio.h ================================================ /* * The libbfio header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_LIBBFIO_H ) #define _LIBFSNTFS_LIBBFIO_H #include /* Define HAVE_LOCAL_LIBBFIO for local use of libbfio */ #if defined( HAVE_LOCAL_LIBBFIO ) #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBBFIO_DLL_IMPORT * before including libbfio.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBBFIO_DLL_IMPORT #endif #include #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( LIBBFIO_HAVE_MULTI_THREAD_SUPPORT ) #error Multi-threading support requires libbfio with multi-threading support #endif #endif /* defined( HAVE_LOCAL_LIBBFIO ) */ #endif /* !defined( _LIBFSNTFS_LIBBFIO_H ) */ ================================================ FILE: libfsntfs/libfsntfs_libcdata.h ================================================ /* * The libcdata header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_LIBCDATA_H ) #define _LIBFSNTFS_LIBCDATA_H #include /* Define HAVE_LOCAL_LIBCDATA for local use of libcdata */ #if defined( HAVE_LOCAL_LIBCDATA ) #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBCDATA_DLL_IMPORT * before including libcdata.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBCDATA_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBCDATA ) */ #endif /* !defined( _LIBFSNTFS_LIBCDATA_H ) */ ================================================ FILE: libfsntfs/libfsntfs_libcerror.h ================================================ /* * The libcerror header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_LIBCERROR_H ) #define _LIBFSNTFS_LIBCERROR_H #include /* Define HAVE_LOCAL_LIBCERROR for local use of libcerror */ #if defined( HAVE_LOCAL_LIBCERROR ) #include #include #include #include #else /* If libtool DLL support is enabled set LIBCERROR_DLL_IMPORT * before including libcerror.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBCERROR_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBCERROR ) */ #endif /* !defined( _LIBFSNTFS_LIBCERROR_H ) */ ================================================ FILE: libfsntfs/libfsntfs_libclocale.h ================================================ /* * The libclocale header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_LIBCLOCALE_H ) #define _LIBFSNTFS_LIBCLOCALE_H #include /* Define HAVE_LOCAL_LIBCLOCALE for local use of libclocale */ #if defined( HAVE_LOCAL_LIBCLOCALE ) #include #include #include #include #else /* If libtool DLL support is enabled set LIBCLOCALE_DLL_IMPORT * before including libclocale.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBCLOCALE_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBCLOCALE ) */ #endif /* !defined( _LIBFSNTFS_LIBCLOCALE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_libcnotify.h ================================================ /* * The libcnotify header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_LIBCNOTIFY_H ) #define _LIBFSNTFS_LIBCNOTIFY_H #include /* Define HAVE_LOCAL_LIBCNOTIFY for local use of libcnotify */ #if defined( HAVE_LOCAL_LIBCNOTIFY ) #include #include #include #include #else /* If libtool DLL support is enabled set LIBCNOTIFY_DLL_IMPORT * before including libcnotify.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBCNOTIFY_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBCNOTIFY ) */ #endif /* !defined( _LIBFSNTFS_LIBCNOTIFY_H ) */ ================================================ FILE: libfsntfs/libfsntfs_libcthreads.h ================================================ /* * The libcthreads header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_LIBCTHREADS_H ) #define _LIBFSNTFS_LIBCTHREADS_H #include #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBFSNTFS ) #define HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT #endif #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) /* Define HAVE_LOCAL_LIBCTHREADS for local use of libcthreads */ #if defined( HAVE_LOCAL_LIBCTHREADS ) #include #include #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBCTHREADS_DLL_IMPORT * before including libcthreads.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBCTHREADS_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBCTHREADS ) */ #endif /* defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) */ #endif /* !defined( _LIBFSNTFS_LIBCTHREADS_H ) */ ================================================ FILE: libfsntfs/libfsntfs_libfcache.h ================================================ /* * The libfcache header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_LIBFCACHE_H ) #define _LIBFSNTFS_LIBFCACHE_H #include /* Define HAVE_LOCAL_LIBFCACHE for local use of libfcache */ #if defined( HAVE_LOCAL_LIBFCACHE ) #include #include #include #include #else /* If libtool DLL support is enabled set LIBFCACHE_DLL_IMPORT * before including libfcache.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBFCACHE_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBFCACHE ) */ #endif /* !defined( _LIBFSNTFS_LIBFCACHE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_libfdata.h ================================================ /* * The libfdata header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_LIBFDATA_H ) #define _LIBFSNTFS_LIBFDATA_H #include /* Define HAVE_LOCAL_LIBFDATA for local use of libfdata */ #if defined( HAVE_LOCAL_LIBFDATA ) #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBFDATA_DLL_IMPORT * before including libfdata.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBFDATA_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBFDATA ) */ #endif /* !defined( _LIBFSNTFS_LIBFDATA_H ) */ ================================================ FILE: libfsntfs/libfsntfs_libfdatetime.h ================================================ /* * The libfdatetime header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_LIBFDATETIME_H ) #define _LIBFSNTFS_LIBFDATETIME_H #include /* Define HAVE_LOCAL_LIBFDATETIME for local use of libfdatetime */ #if defined( HAVE_LOCAL_LIBFDATETIME ) #include #include #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBFDATETIME_DLL_IMPORT * before including libfdatetime.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBFDATETIME_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBFDATETIME ) */ #endif /* !defined( _LIBFSNTFS_LIBFDATETIME_H ) */ ================================================ FILE: libfsntfs/libfsntfs_libfguid.h ================================================ /* * The libfguid header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_LIBFGUID_H ) #define _LIBFSNTFS_LIBFGUID_H #include /* Define HAVE_LOCAL_LIBFGUID for local use of libfguid */ #if defined( HAVE_LOCAL_LIBFGUID ) #include #include #include #else /* If libtool DLL support is enabled set LIBFGUID_DLL_IMPORT * before including libfguid.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBFGUID_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBFGUID ) */ #endif /* !defined( _LIBFSNTFS_LIBFGUID_H ) */ ================================================ FILE: libfsntfs/libfsntfs_libfwnt.h ================================================ /* * The libfwnt header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_LIBFWNT_H ) #define _LIBFSNTFS_LIBFWNT_H #include /* Define HAVE_LOCAL_LIBFWNT for local use of libfwnt */ #if defined( HAVE_LOCAL_LIBFWNT ) #include #include #include #include #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBFWNT_DLL_IMPORT * before including libfwnt.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBFWNT_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBFWNT ) */ #endif /* !defined( _LIBFSNTFS_LIBFWNT_H ) */ ================================================ FILE: libfsntfs/libfsntfs_libuna.h ================================================ /* * The libuna header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_LIBUNA_H ) #define _LIBFSNTFS_LIBUNA_H #include /* Define HAVE_LOCAL_LIBUNA for local use of libuna */ #if defined( HAVE_LOCAL_LIBUNA ) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBUNA_DLL_IMPORT * before including libuna.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBUNA_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBUNA ) */ #endif /* !defined( _LIBFSNTFS_LIBUNA_H ) */ ================================================ FILE: libfsntfs/libfsntfs_logged_utility_stream_values.c ================================================ /* * Logged utility stream attribute ($LOGGED_UTILITY_STREAM) values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_definitions.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_logged_utility_stream_values.h" #include "libfsntfs_mft_attribute.h" #include "fsntfs_logged_utility_stream.h" /* Creates logged utility stream values * Make sure the value logged_utility_stream_values is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_logged_utility_stream_values_initialize( libfsntfs_logged_utility_stream_values_t **logged_utility_stream_values, libcerror_error_t **error ) { static char *function = "libfsntfs_logged_utility_stream_values_initialize"; if( logged_utility_stream_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid logged utility stream values.", function ); return( -1 ); } if( *logged_utility_stream_values != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid logged utility stream values value already set.", function ); return( -1 ); } *logged_utility_stream_values = memory_allocate_structure( libfsntfs_logged_utility_stream_values_t ); if( *logged_utility_stream_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create logged utility stream values.", function ); goto on_error; } if( memory_set( *logged_utility_stream_values, 0, sizeof( libfsntfs_logged_utility_stream_values_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear logged utility stream values.", function ); goto on_error; } return( 1 ); on_error: if( *logged_utility_stream_values != NULL ) { memory_free( *logged_utility_stream_values ); *logged_utility_stream_values = NULL; } return( -1 ); } /* Frees logged utility stream values * Returns 1 if successful or -1 on error */ int libfsntfs_logged_utility_stream_values_free( libfsntfs_logged_utility_stream_values_t **logged_utility_stream_values, libcerror_error_t **error ) { static char *function = "libfsntfs_logged_utility_stream_values_free"; if( logged_utility_stream_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid logged utility stream values.", function ); return( -1 ); } if( *logged_utility_stream_values != NULL ) { memory_free( *logged_utility_stream_values ); *logged_utility_stream_values = NULL; } return( 1 ); } /* Reads the logged utility stream values * Returns 1 if successful or -1 on error */ int libfsntfs_logged_utility_stream_values_read_data( libfsntfs_logged_utility_stream_values_t *logged_utility_stream_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_logged_utility_stream_values_read_data"; if( logged_utility_stream_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid logged utility stream values.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: logged utility stream data:\n", function ); libcnotify_print_data( data, data_size, 0 ); } #endif if( data_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported logged utility stream data size: %" PRIzd "\n", function, data_size ); return( -1 ); } return( 1 ); } /* Reads the logged utility stream values from an MFT attribute * Returns 1 if successful or -1 on error */ int libfsntfs_logged_utility_stream_values_read_from_mft_attribute( libfsntfs_logged_utility_stream_values_t *logged_utility_stream_values, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ) { uint8_t *data = NULL; static char *function = "libfsntfs_logged_utility_stream_values_read_from_mft_attribute"; size_t data_size = 0; uint32_t attribute_type = 0; int result = 0; if( logged_utility_stream_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid logged utility stream values.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_type( mft_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve type from attribute.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_LOGGED_UTILITY_STREAM ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_mft_attribute_data_is_resident( mft_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if attribute data is resident.", function ); return( -1 ); } else if( result == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported non-resident attribute.", function ); return( 1 ); } if( libfsntfs_mft_attribute_get_resident_data( mft_attribute, &data, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve resident data from attribute.", function ); return( -1 ); } if( libfsntfs_logged_utility_stream_values_read_data( logged_utility_stream_values, data, data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read logged utility stream values.", function ); return( -1 ); } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_logged_utility_stream_values.h ================================================ /* * Logged utility stream attribute ($LOGGED_UTILITY_STREAM) values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_LOGGED_UTILITY_STREAM_VALUES_H ) #define _LIBFSNTFS_LOGGED_UTILITY_STREAM_VALUES_H #include #include #include "libfsntfs_libcerror.h" #include "libfsntfs_mft_attribute.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_logged_utility_stream_values libfsntfs_logged_utility_stream_values_t; struct libfsntfs_logged_utility_stream_values { /* Dummy */ int dummy; }; int libfsntfs_logged_utility_stream_values_initialize( libfsntfs_logged_utility_stream_values_t **logged_utility_stream_values, libcerror_error_t **error ); int libfsntfs_logged_utility_stream_values_free( libfsntfs_logged_utility_stream_values_t **logged_utility_stream_values, libcerror_error_t **error ); int libfsntfs_logged_utility_stream_values_read_data( libfsntfs_logged_utility_stream_values_t *logged_utility_stream_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_logged_utility_stream_values_read_from_mft_attribute( libfsntfs_logged_utility_stream_values_t *logged_utility_stream_values, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_LOGGED_UTILITY_STREAM_VALUES_H ) */ ================================================ FILE: libfsntfs/libfsntfs_mft.c ================================================ /* * MFT functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_definitions.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfcache.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft.h" #include "libfsntfs_mft_attribute_list.h" #include "libfsntfs_mft_entry.h" #include "libfsntfs_types.h" /* Creates a MFT * Make sure the value mft is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_mft_initialize( libfsntfs_mft_t **mft, libfsntfs_io_handle_t *io_handle, size64_t mft_entry_size, uint8_t flags, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_initialize"; if( mft == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT.", function ); return( -1 ); } if( *mft != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT value already set.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } *mft = memory_allocate_structure( libfsntfs_mft_t ); if( *mft == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create MFT.", function ); goto on_error; } if( memory_set( *mft, 0, sizeof( libfsntfs_mft_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear MFT.", function ); memory_free( *mft ); *mft = NULL; return( -1 ); } if( libfdata_vector_initialize( &( ( *mft )->mft_entry_vector ), mft_entry_size, (intptr_t *) io_handle, NULL, NULL, (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsntfs_mft_entry_read_element_data, NULL, LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create MFT entry vector.", function ); goto on_error; } if( libfcache_cache_initialize( &( ( *mft )->mft_entry_cache ), LIBFSNTFS_MAXIMUM_CACHE_ENTRIES_MFT_ENTRIES, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create MFT entry cache.", function ); goto on_error; } if( libfcache_cache_initialize( &( ( *mft )->single_mft_entry_cache ), 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create signle MFT entry cache.", function ); goto on_error; } ( *mft )->io_handle = io_handle; ( *mft )->flags = flags; return( 1 ); on_error: if( *mft != NULL ) { if( ( *mft )->mft_entry_cache != NULL ) { libfcache_cache_free( &( ( *mft )->mft_entry_cache ), NULL ); } if( ( *mft )->mft_entry_vector != NULL ) { libfdata_vector_free( &( ( *mft )->mft_entry_vector ), NULL ); } memory_free( *mft ); *mft = NULL; } return( -1 ); } /* Frees a MFT * Returns 1 if successful or -1 on error */ int libfsntfs_mft_free( libfsntfs_mft_t **mft, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_free"; int result = 1; if( mft == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT.", function ); return( -1 ); } if( *mft != NULL ) { if( libfdata_vector_free( &( ( *mft )->mft_entry_vector ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free MFT entry vector.", function ); result = -1; } if( libfcache_cache_free( &( ( *mft )->mft_entry_cache ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free MFT entry cache.", function ); result = -1; } if( libfcache_cache_free( &( ( *mft )->single_mft_entry_cache ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free single MFT entry cache.", function ); result = -1; } if( ( *mft )->attribute_list_tree != NULL ) { if( libcdata_btree_free( &( ( *mft )->attribute_list_tree ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_list_free, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free attribute list tree.", function ); result = -1; } } memory_free( *mft ); *mft = NULL; } return( result ); } /* Reads the attribute list data MFT entries * Returns 1 if successful or -1 on error */ int libfsntfs_mft_read_list_data_mft_entries( libfsntfs_mft_t *mft, libbfio_handle_t *file_io_handle, libcerror_error_t **error ) { libcdata_tree_node_t *upper_node = NULL; libfsntfs_mft_attribute_list_t *attribute_list = NULL; libfsntfs_mft_attribute_list_t *existing_attribute_list = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; static char *function = "libfsntfs_mft_read_list_data_mft_entries"; uint64_t base_record_file_reference = 0; uint64_t file_reference = 0; uint64_t mft_entry_index = 0; int result = 0; int value_index = 0; if( mft == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT.", function ); return( -1 ); } if( mft->attribute_list_tree != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT - attribute list tree value already set.", function ); return( -1 ); } if( libcdata_btree_initialize( &( mft->attribute_list_tree ), LIBFSNTFS_INDEX_TREE_MAXIMUM_NUMBER_OF_SUB_NODES, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create attribute list B-tree.", function ); goto on_error; } for( mft_entry_index = 0; mft_entry_index < mft->number_of_mft_entries; mft_entry_index++ ) { if( libfdata_vector_get_element_value_by_index( mft->mft_entry_vector, (intptr_t *) file_io_handle, (libfdata_cache_t *) mft->mft_entry_cache, (int) mft_entry_index, (intptr_t **) &mft_entry, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: %" PRIu64 ".", function, mft_entry_index ); goto on_error; } result = libfsntfs_mft_entry_get_base_record_file_reference( mft_entry, &base_record_file_reference, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve base record file reference from MFT entry: %" PRIu64 ".", function, mft_entry_index ); goto on_error; } if( ( result == 0 ) || ( base_record_file_reference == 0 ) ) { continue; } if( libfsntfs_mft_attribute_list_initialize( &attribute_list, base_record_file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create attribute list.", function ); goto on_error; } result = libcdata_btree_insert_value( mft->attribute_list_tree, &value_index, (intptr_t *) attribute_list, (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_mft_attribute_list_compare_by_base_record_file_reference, &upper_node, (intptr_t **) &existing_attribute_list, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to insert attribute list into tree.", function ); goto on_error; } else if( result == 0 ) { if( libfsntfs_mft_attribute_list_free( &attribute_list, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free attribute list.", function ); goto on_error; } } else { existing_attribute_list = attribute_list; attribute_list = NULL; } if( libfsntfs_mft_entry_get_file_reference( mft_entry, &file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file reference from MFT entry: %" PRIu64 ".", function, mft_entry_index ); goto on_error; } if( libfsntfs_mft_attribute_list_insert_file_reference( existing_attribute_list, file_reference, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to insert attribute list data file reference in attribute list.", function ); goto on_error; } } return( 1 ); on_error: if( attribute_list != NULL ) { libfsntfs_mft_attribute_list_free( &attribute_list, NULL ); } if( mft->attribute_list_tree != NULL ) { libcdata_btree_free( &( mft->attribute_list_tree ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_list_free, NULL ); } return( -1 ); } /* Retrieves the number of MFT entries * Returns 1 if successful or -1 on error */ int libfsntfs_mft_get_number_of_entries( libfsntfs_mft_t *mft, uint64_t *number_of_entries, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_get_number_of_entries"; if( mft == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT.", function ); return( -1 ); } if( number_of_entries == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid number of entries.", function ); return( -1 ); } *number_of_entries = mft->number_of_mft_entries; return( 1 ); } /* Retrieves the MFT entry for a specific index * Returns 1 if successful or -1 on error */ int libfsntfs_mft_get_mft_entry_by_index( libfsntfs_mft_t *mft, libbfio_handle_t *file_io_handle, uint64_t mft_entry_index, libfsntfs_mft_entry_t **mft_entry, libcerror_error_t **error ) { libfsntfs_mft_entry_t *safe_mft_entry = NULL; static char *function = "libfsntfs_mft_get_mft_entry_by_index"; if( mft == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT.", function ); return( -1 ); } if( mft_entry_index > mft->number_of_mft_entries ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid MFT entry index value out of bounds.", function ); return( -1 ); } if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( libfdata_vector_get_element_value_by_index( mft->mft_entry_vector, (intptr_t *) file_io_handle, (libfdata_cache_t *) mft->mft_entry_cache, (int) mft_entry_index, (intptr_t **) &safe_mft_entry, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: %" PRIu64 ".", function, mft_entry_index ); return( -1 ); } if( libfsntfs_mft_entry_read_attributes( safe_mft_entry, mft->io_handle, file_io_handle, mft->mft_entry_vector, mft->attribute_list_tree, mft->flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read MFT entry: %d attributes.", function, mft_entry_index ); return( -1 ); } *mft_entry = safe_mft_entry; return( 1 ); } /* Retrieves the MFT entry for a specific index * Returns 1 if successful or -1 on error */ int libfsntfs_mft_get_mft_entry_by_index_no_cache( libfsntfs_mft_t *mft, libbfio_handle_t *file_io_handle, uint64_t mft_entry_index, libfsntfs_mft_entry_t **mft_entry, libcerror_error_t **error ) { libfsntfs_mft_entry_t *safe_mft_entry = NULL; static char *function = "libfsntfs_mft_get_mft_entry_by_index_no_cache"; if( mft == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT.", function ); return( -1 ); } if( mft_entry_index > mft->number_of_mft_entries ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid MFT entry index value out of bounds.", function ); return( -1 ); } if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( libfdata_vector_get_element_value_by_index( mft->mft_entry_vector, (intptr_t *) file_io_handle, (libfdata_cache_t *) mft->single_mft_entry_cache, (int) mft_entry_index, (intptr_t **) &safe_mft_entry, LIBFDATA_READ_FLAG_IGNORE_CACHE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: %" PRIu64 ".", function, mft_entry_index ); return( -1 ); } if( libfsntfs_mft_entry_read_attributes( safe_mft_entry, mft->io_handle, file_io_handle, mft->mft_entry_vector, mft->attribute_list_tree, mft->flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read MFT entry: %d attributes.", function, mft_entry_index ); return( -1 ); } if( libfcache_cache_clear_value_by_index( mft->single_mft_entry_cache, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to clear single MFT entry cache entry: 0.", function ); return( -1 ); } *mft_entry = safe_mft_entry; return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_mft.h ================================================ /* * MFT functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_MFT_H ) #define _LIBFSNTFS_MFT_H #include #include #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfcache.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_entry.h" #include "libfsntfs_types.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_mft libfsntfs_mft_t; struct libfsntfs_mft { /* The number of MFT entries */ uint64_t number_of_mft_entries; /* The MFT entry vector */ libfdata_vector_t *mft_entry_vector; /* The MFT entry cache */ libfcache_cache_t *mft_entry_cache; /* The single MFT entry cache */ libfcache_cache_t *single_mft_entry_cache; /* The attribute list B-tree */ libcdata_btree_t *attribute_list_tree; /* The IO handle */ libfsntfs_io_handle_t *io_handle; /* The flags */ uint8_t flags; }; int libfsntfs_mft_initialize( libfsntfs_mft_t **mft, libfsntfs_io_handle_t *io_handle, size64_t mft_entry_size, uint8_t flags, libcerror_error_t **error ); int libfsntfs_mft_free( libfsntfs_mft_t **mft, libcerror_error_t **error ); int libfsntfs_mft_read_list_data_mft_entries( libfsntfs_mft_t *mft, libbfio_handle_t *file_io_handle, libcerror_error_t **error ); int libfsntfs_mft_get_number_of_entries( libfsntfs_mft_t *mft, uint64_t *number_of_entries, libcerror_error_t **error ); int libfsntfs_mft_get_mft_entry_by_index( libfsntfs_mft_t *mft, libbfio_handle_t *file_io_handle, uint64_t mft_entry_index, libfsntfs_mft_entry_t **mft_entry, libcerror_error_t **error ); int libfsntfs_mft_get_mft_entry_by_index_no_cache( libfsntfs_mft_t *mft, libbfio_handle_t *file_io_handle, uint64_t mft_entry_index, libfsntfs_mft_entry_t **mft_entry, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_MFT_H ) */ ================================================ FILE: libfsntfs/libfsntfs_mft_attribute.c ================================================ /* * Master File Table (MFT) attribute functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_data_run.h" #include "libfsntfs_debug.h" #include "libfsntfs_definitions.h" #include "libfsntfs_extent.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libuna.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_name.h" #include "fsntfs_mft_attribute.h" /* Creates a MFT attribute * Make sure the value mft_attribute is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_initialize( libfsntfs_mft_attribute_t **mft_attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_initialize"; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( *mft_attribute != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT attribute value already set.", function ); return( -1 ); } *mft_attribute = memory_allocate_structure( libfsntfs_mft_attribute_t ); if( *mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create MFT attribute.", function ); goto on_error; } if( memory_set( *mft_attribute, 0, sizeof( libfsntfs_mft_attribute_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear MFT attribute.", function ); goto on_error; } return( 1 ); on_error: if( *mft_attribute != NULL ) { memory_free( *mft_attribute ); *mft_attribute = NULL; } return( -1 ); } /* Frees a MFT attribute * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_free( libfsntfs_mft_attribute_t **mft_attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_free"; int result = 1; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( *mft_attribute != NULL ) { if( ( *mft_attribute )->name != NULL ) { memory_free( ( *mft_attribute )->name ); } if( ( *mft_attribute )->data != NULL ) { memory_free( ( *mft_attribute )->data ); } if( ( *mft_attribute )->data_runs_array != NULL ) { if( libcdata_array_free( &( ( *mft_attribute )->data_runs_array ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_data_run_free, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free data runs array.", function ); result = -1; } } memory_free( *mft_attribute ); *mft_attribute = NULL; } return( result ); } /* Clones a MFT attribute * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_clone( libfsntfs_mft_attribute_t **destination_mft_attribute, libfsntfs_mft_attribute_t *source_mft_attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_clone"; if( destination_mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( *destination_mft_attribute != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid destination MFT attribute value already set.", function ); return( -1 ); } if( source_mft_attribute == NULL ) { *destination_mft_attribute = source_mft_attribute; return( 1 ); } *destination_mft_attribute = memory_allocate_structure( libfsntfs_mft_attribute_t ); if( *destination_mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create destnation MFT attribute.", function ); goto on_error; } if( memory_copy( *destination_mft_attribute, source_mft_attribute, sizeof( libfsntfs_mft_attribute_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to copy source MFT attribute to destination.", function ); goto on_error; } ( *destination_mft_attribute )->name = NULL; ( *destination_mft_attribute )->data = NULL; ( *destination_mft_attribute )->data_runs_array = NULL; ( *destination_mft_attribute )->next_attribute = NULL; if( source_mft_attribute->name != NULL ) { ( *destination_mft_attribute )->name = (uint8_t *) memory_allocate( source_mft_attribute->name_size ); if( ( *destination_mft_attribute )->name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create destination name.", function ); goto on_error; } if( memory_copy( ( *destination_mft_attribute )->name, source_mft_attribute->name, source_mft_attribute->name_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy source name to destination.", function ); goto on_error; } ( *destination_mft_attribute )->name_size = source_mft_attribute->name_size; } if( source_mft_attribute->data != NULL ) { ( *destination_mft_attribute )->data = (uint8_t *) memory_allocate( source_mft_attribute->data_size ); if( ( *destination_mft_attribute )->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create destination data.", function ); goto on_error; } if( memory_copy( ( *destination_mft_attribute )->data, source_mft_attribute->data, source_mft_attribute->data_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy source data to destination.", function ); goto on_error; } ( *destination_mft_attribute )->data_size = source_mft_attribute->data_size; } if( libcdata_array_clone( &( ( *destination_mft_attribute )->data_runs_array ), source_mft_attribute->data_runs_array, (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_data_run_free, (int (*)(intptr_t **, intptr_t *, libcerror_error_t **)) &libfsntfs_data_run_clone, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to clone data runs array.", function ); goto on_error; } return( 1 ); on_error: if( *destination_mft_attribute != NULL ) { if( ( *destination_mft_attribute )->data != NULL ) { memory_free( ( *destination_mft_attribute )->data ); } if( ( *destination_mft_attribute )->data != NULL ) { memory_free( ( *destination_mft_attribute )->data ); } memory_free( *destination_mft_attribute ); *destination_mft_attribute = NULL; } return( -1 ); } /* Reads the MFT attribute * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_read_data( libfsntfs_mft_attribute_t *mft_attribute, libfsntfs_io_handle_t *io_handle, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { libfsntfs_data_run_t *data_run = NULL; const uint8_t *non_resident_data = NULL; const uint8_t *resident_data = NULL; static char *function = "libfsntfs_mft_attribute_read_data"; size_t data_offset = 0; size_t non_resident_data_size = 0; ssize_t read_count = 0; uint64_t last_cluster_block_number = 0; uint16_t compression_unit_size = 0; uint16_t data_runs_offset = 0; uint16_t name_offset = 0; int data_run_index = 0; int entry_index = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint64_t value_64bit = 0; uint32_t value_32bit = 0; #endif if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( mft_attribute->name != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT attribute - name value already set.", function ); return( -1 ); } if( mft_attribute->data != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT attribute - data value already set.", function ); return( -1 ); } if( mft_attribute->data_runs_array != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT attribute - data runs array value already set.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: data size value exceeds maximum.", function ); return( -1 ); } if( data_size < sizeof( fsntfs_mft_attribute_header_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: unsupported data size value too small\n", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: MFT attribute header data:\n", function ); libcnotify_print_data( data, sizeof( fsntfs_mft_attribute_header_t ), 0 ); } #endif byte_stream_copy_to_uint32_little_endian( ( (fsntfs_mft_attribute_header_t *) data )->type, mft_attribute->type ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_mft_attribute_header_t *) data )->size, mft_attribute->size ); mft_attribute->non_resident_flag = ( (fsntfs_mft_attribute_header_t *) data )->non_resident_flag; mft_attribute->name_size = (uint16_t) ( (fsntfs_mft_attribute_header_t *) data )->name_size; byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mft_attribute_header_t *) data )->name_offset, name_offset ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mft_attribute_header_t *) data )->data_flags, mft_attribute->data_flags ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mft_attribute_header_t *) data )->identifier, mft_attribute->identifier ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: type\t\t\t\t\t: 0x%08" PRIx32 " (%s)\n", function, mft_attribute->type, libfsntfs_debug_print_attribute_type( mft_attribute->type ) ); libcnotify_printf( "%s: size\t\t\t\t\t: %" PRIu32 "\n", function, mft_attribute->size ); libcnotify_printf( "%s: non resident flag\t\t\t: 0x%02" PRIx8 "\n", function, mft_attribute->non_resident_flag ); libcnotify_printf( "%s: name size\t\t\t\t: %" PRIu16 "\n", function, mft_attribute->name_size ); libcnotify_printf( "%s: name offset\t\t\t\t: %" PRIu16 "\n", function, name_offset ); libcnotify_printf( "%s: data flags\t\t\t\t: 0x%04" PRIx16 "\n", function, mft_attribute->data_flags ); libfsntfs_debug_print_mft_attribute_data_flags( mft_attribute->data_flags ); libcnotify_printf( "\n" ); libcnotify_printf( "%s: identifier\t\t\t\t: %" PRIu16 "\n", function, mft_attribute->identifier ); libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ data_offset = sizeof( fsntfs_mft_attribute_header_t ); if( ( mft_attribute->size < sizeof( fsntfs_mft_attribute_header_t ) ) || ( mft_attribute->size > data_size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: size value out of bounds.", function ); goto on_error; } if( ( ( mft_attribute->data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) != 0x0000 ) && ( ( mft_attribute->data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) != 0x0001 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported compression flags: 0x%04" PRIx16 ".", function, mft_attribute->data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ); goto on_error; } if( ( mft_attribute->data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) != 0 ) { if( io_handle->cluster_block_size > 4096 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported compression flags: 0x%04" PRIx16 " for volume with cluster block size: %" PRIzd ".", function, mft_attribute->data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK, io_handle->cluster_block_size ); goto on_error; } } mft_attribute->name_size *= 2; if( ( mft_attribute->non_resident_flag & 0x01 ) == 0 ) { if( data_size < ( data_offset + sizeof( fsntfs_mft_attribute_resident_t ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: unsupported data size value too small\n", function ); return( -1 ); } resident_data = &( data[ data_offset ] ); if( mft_attribute->size < ( data_offset + sizeof( fsntfs_mft_attribute_resident_t ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid MFT attribute size value out of bounds.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: MFT attribute resident data:\n", function ); libcnotify_print_data( resident_data, sizeof( fsntfs_mft_attribute_resident_t ), 0 ); } #endif byte_stream_copy_to_uint32_little_endian( ( (fsntfs_mft_attribute_resident_t *) resident_data )->data_size, mft_attribute->data_size ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mft_attribute_resident_t *) resident_data )->data_offset, mft_attribute->data_offset ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: data size\t\t\t\t: %" PRIu64 "\n", function, mft_attribute->data_size ); libcnotify_printf( "%s: data offset\t\t\t\t: %" PRIu16 "\n", function, mft_attribute->data_offset ); libcnotify_printf( "%s: indexed flag\t\t\t\t: 0x%02" PRIx8 "\n", function, ( (fsntfs_mft_attribute_resident_t *) resident_data )->indexed_flag ); libcnotify_printf( "%s: padding\t\t\t\t: 0x%02" PRIx8 "\n", function, ( (fsntfs_mft_attribute_resident_t *) resident_data )->padding ); libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ data_offset += sizeof( fsntfs_mft_attribute_resident_t ); } else { if( data_size < ( data_offset + sizeof( fsntfs_mft_attribute_non_resident_t ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: unsupported data size value too small\n", function ); return( -1 ); } non_resident_data = &( data[ data_offset ] ); non_resident_data_size = sizeof( fsntfs_mft_attribute_non_resident_t ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mft_attribute_non_resident_t *) non_resident_data )->compression_unit_size, compression_unit_size ); if( compression_unit_size != 0 ) { if( data_size < ( data_offset + sizeof( fsntfs_mft_attribute_non_resident_compressed_t ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: unsupported data size value too small.", function ); goto on_error; } non_resident_data_size = sizeof( fsntfs_mft_attribute_non_resident_compressed_t ); if( compression_unit_size > 31 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: compression unit size value out of bounds.", function ); goto on_error; } /* The size is calculated as: 2 ^ value */ mft_attribute->compression_unit_size = (size_t) 1 << compression_unit_size; mft_attribute->compression_unit_size *= io_handle->cluster_block_size; } else if( ( mft_attribute->data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) != 0 ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: data is flagged as compressed but no compression unit size set.\n", function ); } #endif mft_attribute->compression_unit_size = 16 * io_handle->cluster_block_size; } if( mft_attribute->size < ( data_offset + non_resident_data_size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid MFT attribute size value out of bounds.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: MFT attribute non-resident data:\n", function ); libcnotify_print_data( non_resident_data, non_resident_data_size, 0 ); } #endif byte_stream_copy_to_uint64_little_endian( ( (fsntfs_mft_attribute_non_resident_t *) non_resident_data )->data_first_vcn, mft_attribute->data_first_vcn ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_mft_attribute_non_resident_t *) non_resident_data )->data_last_vcn, mft_attribute->data_last_vcn ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mft_attribute_non_resident_t *) non_resident_data )->data_runs_offset, data_runs_offset ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_mft_attribute_non_resident_t *) non_resident_data )->allocated_data_size, mft_attribute->allocated_data_size ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_mft_attribute_non_resident_t *) non_resident_data )->data_size, mft_attribute->data_size ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_mft_attribute_non_resident_t *) non_resident_data )->valid_data_size, mft_attribute->valid_data_size ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: data first VCN\t\t\t: %" PRIi64 "\n", function, (int64_t) mft_attribute->data_first_vcn ); libcnotify_printf( "%s: data last VCN\t\t\t: %" PRIi64 "\n", function, (int64_t) mft_attribute->data_last_vcn ); libcnotify_printf( "%s: data runs offset\t\t\t: 0x%04" PRIx16 "\n", function, data_runs_offset ); libcnotify_printf( "%s: compression unit size\t\t: %" PRIu16 " (%" PRIzd ")\n", function, compression_unit_size, mft_attribute->compression_unit_size ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_mft_attribute_non_resident_t *) non_resident_data )->padding, value_32bit ); libcnotify_printf( "%s: padding\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); libcnotify_printf( "%s: allocated data size\t\t\t: %" PRIu64 "\n", function, mft_attribute->allocated_data_size ); libcnotify_printf( "%s: data size\t\t\t\t: %" PRIu64 "\n", function, mft_attribute->data_size ); libcnotify_printf( "%s: valid data size\t\t\t: %" PRIu64 " (0x%08" PRIx64 ")\n", function, mft_attribute->valid_data_size, mft_attribute->valid_data_size ); if( compression_unit_size > 0 ) { byte_stream_copy_to_uint64_little_endian( ( (fsntfs_mft_attribute_non_resident_compressed_t *) non_resident_data )->total_data_size, value_64bit ); libcnotify_printf( "%s: total data size\t\t\t: %" PRIu64 "\n", function, value_64bit ); } libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ data_offset += sizeof( fsntfs_mft_attribute_non_resident_t ); if( mft_attribute->valid_data_size > mft_attribute->data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: valid data size value out of bounds.", function ); goto on_error; } } if( mft_attribute->name_size > 0 ) { if( ( name_offset < data_offset ) || ( name_offset >= mft_attribute->size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: name offset value out of bounds.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( data_offset < name_offset ) { libcnotify_printf( "%s: unknown data:\n", function ); libcnotify_print_data( &( data[ data_offset ] ), (size_t) name_offset - data_offset, 0 ); } } #endif if( mft_attribute->name_size > ( mft_attribute->size - name_offset ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: name size value out of bounds.", function ); goto on_error; } data_offset = (size_t) name_offset; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: name data:\n", function ); libcnotify_print_data( &( data[ data_offset ] ), (size_t) mft_attribute->name_size, 0 ); } #endif mft_attribute->name = (uint8_t *) memory_allocate( sizeof( uint8_t ) * (size_t) mft_attribute->name_size ); if( mft_attribute->name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create name.", function ); goto on_error; } if( memory_copy( mft_attribute->name, &( data[ data_offset ] ), (size_t) mft_attribute->name_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy name.", function ); goto on_error; } data_offset += (size_t) mft_attribute->name_size; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( libfsntfs_debug_print_utf16_string_value( function, "name\t\t\t\t\t", mft_attribute->name, (size_t) mft_attribute->name_size, LIBUNA_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print UTF-16 string value.", function ); goto on_error; } libcnotify_printf( "\n" ); } #endif } if( ( mft_attribute->non_resident_flag & 0x01 ) == 0 ) { if( mft_attribute->data_size > 0 ) { if( ( mft_attribute->data_offset < data_offset ) || ( mft_attribute->data_offset >= mft_attribute->size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: resident data offset value out of bounds.", function ); goto on_error; } if( mft_attribute->data_size > ( mft_attribute->size - mft_attribute->data_offset ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: resident data size value out of bounds.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: resident data:\n", function ); libcnotify_print_data( &( data[ mft_attribute->data_offset ] ), (size_t) mft_attribute->data_size, 0 ); } #endif mft_attribute->data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * (size_t) mft_attribute->data_size ); if( mft_attribute->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create resident data.", function ); goto on_error; } if( memory_copy( mft_attribute->data, &( data[ mft_attribute->data_offset ] ), (size_t) mft_attribute->data_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy resident data.", function ); goto on_error; } data_offset = (size_t) mft_attribute->data_offset + (size_t) mft_attribute->data_size; } } else { /* Note that data size is set in the first attribute of a chain * and successive elements contain a size of 0 */ if( ( data_runs_offset < data_offset ) || ( data_runs_offset >= mft_attribute->size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: data runs offset value out of bounds.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( data_offset < name_offset ) { libcnotify_printf( "%s: unknown data:\n", function ); libcnotify_print_data( &( data[ data_offset ] ), (size_t) data_runs_offset - data_offset, 0 ); } } #endif data_offset = (size_t) data_runs_offset; if( libcdata_array_initialize( &( mft_attribute->data_runs_array ), 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create data runs array.", function ); goto on_error; } while( data_offset < data_size ) { if( libfsntfs_data_run_initialize( &data_run, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create data run: %d.", function, data_run_index ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading data run: %d.\n", function, data_run_index ); } #endif read_count = libfsntfs_data_run_read_data( data_run, io_handle, &( data[ data_offset ] ), data_size - data_offset, last_cluster_block_number, error ); if( read_count <= -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read data run: %d.", function, data_run_index ); goto on_error; } else if( read_count == 1 ) { if( libfsntfs_data_run_free( &data_run, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free data run: %d.", function, data_run_index ); goto on_error; } break; } data_offset += read_count; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( ( data_run->start_offset == 0 ) && ( ( mft_attribute->data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) == 0 ) && ( ( mft_attribute->data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_SPARSE ) == 0 ) ) { libcnotify_printf( "%s: data run is sparse but no attribute data flags set.\n\n", function ); } } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ if( ( data_run->range_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) == 0 ) { last_cluster_block_number = data_run->cluster_block_number; } if( libcdata_array_append_entry( mft_attribute->data_runs_array, &entry_index, (intptr_t *) data_run, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append data run: %d to array.", function, data_run_index ); goto on_error; } data_run = NULL; data_run_index++; } } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( data_offset < mft_attribute->size ) { libcnotify_printf( "%s: trailing data:\n", function ); libcnotify_print_data( &( data[ data_offset ] ), (size_t) mft_attribute->size - data_offset, 0 ); } } #endif return( 1 ); on_error: if( data_run != NULL ) { libfsntfs_data_run_free( &data_run, NULL ); } if( mft_attribute->data_runs_array != NULL ) { libcdata_array_free( &( mft_attribute->data_runs_array ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_data_run_free, NULL ); } if( mft_attribute->data != NULL ) { memory_free( mft_attribute->data ); mft_attribute->data = NULL; } if( mft_attribute->name != NULL ) { memory_free( mft_attribute->name ); mft_attribute->name = NULL; } mft_attribute->name_size = 0; return( -1 ); } /* Determines if the attribute data is resident * Returns 1 if the attribute data is resident, 0 if not or -1 on error */ int libfsntfs_mft_attribute_data_is_resident( libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_data_is_resident"; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( ( mft_attribute->non_resident_flag & 0x01 ) == 0 ) { return( 1 ); } return( 0 ); } /* Retrieves the type * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_get_type( libfsntfs_mft_attribute_t *mft_attribute, uint32_t *type, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_get_type"; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( type == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid type.", function ); return( -1 ); } *type = mft_attribute->type; return( 1 ); } /* Retrieves the data flags * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_get_data_flags( libfsntfs_mft_attribute_t *mft_attribute, uint16_t *data_flags, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_get_data_flags"; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( data_flags == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data flags.", function ); return( -1 ); } *data_flags = mft_attribute->data_flags; return( 1 ); } /* Retrieves the data size * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_get_data_size( libfsntfs_mft_attribute_t *mft_attribute, uint64_t *data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_get_data_size"; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( data_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data size.", function ); return( -1 ); } *data_size = mft_attribute->data_size; return( 1 ); } /* Retrieves the data VCN range * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_mft_attribute_get_data_vcn_range( libfsntfs_mft_attribute_t *mft_attribute, uint64_t *data_first_vcn, uint64_t *data_last_vcn, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_get_data_vcn_range"; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( data_first_vcn == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data first VCN.", function ); return( -1 ); } if( data_last_vcn == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data last VCN.", function ); return( -1 ); } if( ( mft_attribute->non_resident_flag & 0x01 ) != 0 ) { *data_first_vcn = mft_attribute->data_first_vcn; *data_last_vcn = mft_attribute->data_last_vcn; return( 1 ); } return( 0 ); } /* Retrieves the allocated data size * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_get_allocated_data_size( libfsntfs_mft_attribute_t *mft_attribute, uint64_t *allocated_data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_get_allocated_data_size"; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( allocated_data_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid allocated data size.", function ); return( -1 ); } *allocated_data_size = mft_attribute->allocated_data_size; return( 1 ); } /* Retrieves the valid data size * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_get_valid_data_size( libfsntfs_mft_attribute_t *mft_attribute, uint64_t *valid_data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_get_valid_data_size"; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( valid_data_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid valid data size.", function ); return( -1 ); } *valid_data_size = mft_attribute->valid_data_size; return( 1 ); } /* Retrieves the size of the UTF-8 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_get_utf8_name_size( libfsntfs_mft_attribute_t *mft_attribute, size_t *utf8_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_get_utf8_name_size"; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( ( mft_attribute->name == NULL ) || ( mft_attribute->name_size == 0 ) ) { if( utf8_string_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-8 string size.", function ); return( -1 ); } *utf8_string_size = 0; } else { if( libuna_utf8_string_size_from_utf16_stream( mft_attribute->name, (size_t) mft_attribute->name_size, LIBUNA_ENDIAN_LITTLE, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 string size.", function ); return( -1 ); } } return( 1 ); } /* Retrieves the UTF-8 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_get_utf8_name( libfsntfs_mft_attribute_t *mft_attribute, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_get_utf8_name"; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( mft_attribute->name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid MFT attribute - missing name.", function ); return( -1 ); } if( libuna_utf8_string_copy_from_utf16_stream( utf8_string, utf8_string_size, mft_attribute->name, (size_t) mft_attribute->name_size, LIBUNA_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 string.", function ); return( -1 ); } return( 1 ); } /* Retrieves the size of the UTF-16 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_get_utf16_name_size( libfsntfs_mft_attribute_t *mft_attribute, size_t *utf16_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_get_utf16_name_size"; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( ( mft_attribute->name == NULL ) || ( mft_attribute->name_size == 0 ) ) { if( utf16_string_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-16 string size.", function ); return( -1 ); } *utf16_string_size = 0; } else { if( libuna_utf16_string_size_from_utf16_stream( mft_attribute->name, (size_t) mft_attribute->name_size, LIBUNA_ENDIAN_LITTLE, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 string size.", function ); return( -1 ); } } return( 1 ); } /* Retrieves the UTF-16 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_get_utf16_name( libfsntfs_mft_attribute_t *mft_attribute, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_get_utf16_name"; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( mft_attribute->name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid MFT attribute - missing name.", function ); return( -1 ); } if( libuna_utf16_string_copy_from_utf16_stream( utf16_string, utf16_string_size, mft_attribute->name, (size_t) mft_attribute->name_size, LIBUNA_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 string.", function ); return( -1 ); } return( 1 ); } /* Compares the name with an UTF-8 encoded string * Returns 1 if the strings are equal, 0 if not or -1 on error */ int libfsntfs_mft_attribute_compare_name_with_utf8_string( libfsntfs_mft_attribute_t *mft_attribute, const uint8_t *utf8_string, size_t utf8_string_length, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_compare_name_with_utf8_string"; int result = 0; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( mft_attribute->name == NULL ) { return( 0 ); } result = libfsntfs_name_compare_with_utf8_string( mft_attribute->name, mft_attribute->name_size, utf8_string, utf8_string_length, 0, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GENERIC, "%s: unable to compare UTF-8 string with name.", function ); return( -1 ); } else if( result == LIBUNA_COMPARE_EQUAL ) { return( 1 ); } return( 0 ); } /* Compares the name with an UTF-16 encoded string * Returns 1 if the strings are equal, 0 if not or -1 on error */ int libfsntfs_mft_attribute_compare_name_with_utf16_string( libfsntfs_mft_attribute_t *mft_attribute, const uint16_t *utf16_string, size_t utf16_string_length, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_compare_name_with_utf16_string"; int result = 0; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( mft_attribute->name == NULL ) { return( 0 ); } result = libfsntfs_name_compare_with_utf16_string( mft_attribute->name, mft_attribute->name_size, utf16_string, utf16_string_length, 0, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GENERIC, "%s: unable to compare UTF-16 string with name.", function ); return( -1 ); } else if( result == LIBUNA_COMPARE_EQUAL ) { return( 1 ); } return( 0 ); } /* Retrieves the compression unit size * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_get_compression_unit_size( libfsntfs_mft_attribute_t *mft_attribute, size_t *compression_unit_size, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_get_compression_unit_size"; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( compression_unit_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid compression unit size.", function ); return( -1 ); } *compression_unit_size = mft_attribute->compression_unit_size; return( 1 ); } /* Retrieves the resident data * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_get_resident_data( libfsntfs_mft_attribute_t *mft_attribute, uint8_t **resident_data, size_t *resident_data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_get_resident_data"; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( ( mft_attribute->non_resident_flag & 0x01 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: invalid MFT attribute - non-resident flag is set.", function ); return( -1 ); } if( mft_attribute->data_size > (uint64_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid MFT attribute - data size value out of bounds.", function ); return( -1 ); } if( resident_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid resident data.", function ); return( -1 ); } if( resident_data_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid resident data size.", function ); return( -1 ); } *resident_data = mft_attribute->data; *resident_data_size = (size_t) mft_attribute->data_size; return( 1 ); } /* Retrieves the number of data runs * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_get_number_of_data_runs( libfsntfs_mft_attribute_t *mft_attribute, int *number_of_data_runs, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_get_number_of_data_runs"; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( mft_attribute->data_runs_array == NULL ) { if( number_of_data_runs == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid number of data runs.", function ); return( -1 ); } *number_of_data_runs = 0; } else { if( libcdata_array_get_number_of_entries( mft_attribute->data_runs_array, number_of_data_runs, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of data runs.", function ); return( -1 ); } } return( 1 ); } /* Retrieves a specific data run * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_get_data_run_by_index( libfsntfs_mft_attribute_t *mft_attribute, int data_run_index, libfsntfs_data_run_t **data_run, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_get_data_run_by_index"; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( libcdata_array_get_entry_by_index( mft_attribute->data_runs_array, data_run_index, (intptr_t **) data_run, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data run: %d.", function, data_run_index ); return( -1 ); } return( 1 ); } /* Retrieves the data extents array * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_get_data_extents_array( libfsntfs_mft_attribute_t *mft_attribute, libfsntfs_io_handle_t *io_handle, libcdata_array_t **data_extents_array, libcerror_error_t **error ) { libcdata_array_t *safe_data_extents_array = NULL; libfsntfs_data_run_t *data_run = NULL; libfsntfs_extent_t *data_extent = NULL; static char *function = "libfsntfs_mft_attribute_get_data_extents_array"; size64_t attribute_data_vcn_size = 0; size64_t calculated_allocated_data_size = 0; size64_t stored_allocated_data_size = 0; off64_t attribute_data_vcn_offset = 0; off64_t calculated_attribute_data_vcn_offset = 0; int attribute_index = 0; int data_run_index = 0; int entry_index = 0; int number_of_data_runs = 0; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( io_handle->cluster_block_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid IO handle - cluster block size value out of bounds.", function ); return( -1 ); } if( data_extents_array == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data extents array.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_allocated_data_size( mft_attribute, &stored_allocated_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute allocated data size.", function ); goto on_error; } if( libcdata_array_initialize( &safe_data_extents_array, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create extents array.", function ); goto on_error; } while( mft_attribute != NULL ) { if( mft_attribute->data_runs_array != NULL ) { attribute_data_vcn_offset = mft_attribute->data_first_vcn; attribute_data_vcn_size = mft_attribute->data_last_vcn; if( attribute_data_vcn_size != 0xffffffffffffffffULL ) { if( (uint64_t) attribute_data_vcn_offset > (uint64_t) ( ( INT64_MAX / io_handle->cluster_block_size ) - 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data first VCN value out of bounds.", function ); goto on_error; } if( attribute_data_vcn_size > (size64_t) ( ( INT64_MAX / io_handle->cluster_block_size ) - 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data last VCN value out of bounds.", function ); goto on_error; } if( attribute_data_vcn_offset > (off64_t) attribute_data_vcn_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data first VCN value out of bounds.", function ); goto on_error; } attribute_data_vcn_size += 1; attribute_data_vcn_size -= attribute_data_vcn_offset; attribute_data_vcn_offset *= io_handle->cluster_block_size; attribute_data_vcn_size *= io_handle->cluster_block_size; if( ( calculated_attribute_data_vcn_offset != 0 ) && ( calculated_attribute_data_vcn_offset != attribute_data_vcn_offset ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attribute data VCN offset value out of bounds.", function ); goto on_error; } calculated_attribute_data_vcn_offset = attribute_data_vcn_offset + (off64_t) attribute_data_vcn_size; } if( libcdata_array_get_number_of_entries( mft_attribute->data_runs_array, &number_of_data_runs, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d number of data runs.", function, attribute_index ); goto on_error; } for( data_run_index = 0; data_run_index < number_of_data_runs; data_run_index++ ) { if( libcdata_array_get_entry_by_index( mft_attribute->data_runs_array, data_run_index, (intptr_t **) &data_run, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d data run: %d.", function, attribute_index, data_run_index ); goto on_error; } if( data_run == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing attribute: %d data run: %d.", function, attribute_index, data_run_index ); goto on_error; } if( libfsntfs_extent_initialize( &data_extent, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create data extent: %d.", function, data_run_index ); goto on_error; } data_extent->start_offset = data_run->start_offset; data_extent->size = data_run->size; data_extent->range_flags = 0; if( ( data_run->range_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) != 0 ) { data_extent->range_flags |= LIBFSNTFS_EXTENT_FLAG_IS_SPARSE; } if( ( data_run->range_flags & LIBFDATA_RANGE_FLAG_IS_COMPRESSED ) != 0 ) { data_extent->range_flags |= LIBFSNTFS_EXTENT_FLAG_IS_COMPRESSED; } if( libcdata_array_append_entry( safe_data_extents_array, &entry_index, (intptr_t *) data_extent, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append data extent: %d to array.", function, data_run_index ); goto on_error; } calculated_allocated_data_size += data_run->size; data_extent = NULL; } } attribute_index++; if( libfsntfs_mft_attribute_get_next_attribute( mft_attribute, &mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve next MFT attribute: %d.", function, attribute_index ); goto on_error; } } if( calculated_allocated_data_size != stored_allocated_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: size of data runs: %" PRIu64 " does not match allocated data size: %" PRIu64 ".", function, calculated_allocated_data_size, stored_allocated_data_size ); goto on_error; } *data_extents_array = safe_data_extents_array; return( 1 ); on_error: if( data_extent != NULL ) { libfsntfs_extent_free( &data_extent, NULL ); } if( safe_data_extents_array != NULL ) { libcdata_array_free( &safe_data_extents_array, (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_extent_free, NULL ); } return( -1 ); } /* Retrieves the next attribute * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_get_next_attribute( libfsntfs_mft_attribute_t *mft_attribute, libfsntfs_mft_attribute_t **next_attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_get_next_attribute"; if( mft_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( next_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid next attribute.", function ); return( -1 ); } *next_attribute = mft_attribute->next_attribute; return( 1 ); } /* Appends the attribute to the attribute chain * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_append_to_chain( libfsntfs_mft_attribute_t **first_attribute, libfsntfs_mft_attribute_t *additional_attribute, libcerror_error_t **error ) { libfsntfs_mft_attribute_t *mft_attribute = NULL; libfsntfs_mft_attribute_t *previous_attribute = NULL; static char *function = "libfsntfs_mft_attribute_append_to_chain"; if( first_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid first attribute.", function ); return( -1 ); } if( additional_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid additional attribute.", function ); return( -1 ); } mft_attribute = *first_attribute; if( mft_attribute != NULL ) { if( mft_attribute->type != additional_attribute->type ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: unable to chain attributes of different types.", function ); return( -1 ); } } while( mft_attribute != NULL ) { if( mft_attribute == additional_attribute ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid chained attribute value out of bounds.", function ); return( -1 ); } if( mft_attribute->data_first_vcn > additional_attribute->data_first_vcn ) { break; } previous_attribute = mft_attribute; mft_attribute = mft_attribute->next_attribute; } if( previous_attribute == NULL ) { additional_attribute->next_attribute = mft_attribute; *first_attribute = additional_attribute; } else { if( previous_attribute->next_attribute != NULL ) { additional_attribute->next_attribute = previous_attribute->next_attribute; } previous_attribute->next_attribute = additional_attribute; } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_mft_attribute.h ================================================ /* * Master File Table (MFT) attribute functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_MFT_ATTRIBUTE_H ) #define _LIBFSNTFS_MFT_ATTRIBUTE_H #include #include #include "libfsntfs_data_run.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_mft_attribute libfsntfs_mft_attribute_t; struct libfsntfs_mft_attribute { /* The type */ uint32_t type; /* The size */ uint32_t size; /* The non-resident flag */ uint8_t non_resident_flag; /* The name size */ uint16_t name_size; /* The data flags */ uint16_t data_flags; /* The identifier */ uint16_t identifier; /* The data size */ uint64_t data_size; /* The data offset */ uint16_t data_offset; /* The data first VCN */ uint64_t data_first_vcn; /* The data last VCN */ uint64_t data_last_vcn; /* The compression unit size */ size_t compression_unit_size; /* The allocated data size */ uint64_t allocated_data_size; /* The valid data size */ uint64_t valid_data_size; /* The name */ uint8_t *name; /* The data */ uint8_t *data; /* The data runs array */ libcdata_array_t *data_runs_array; /* The next attribute in an attribute chain */ libfsntfs_mft_attribute_t *next_attribute; }; int libfsntfs_mft_attribute_initialize( libfsntfs_mft_attribute_t **mft_attribute, libcerror_error_t **error ); int libfsntfs_mft_attribute_free( libfsntfs_mft_attribute_t **mft_attribute, libcerror_error_t **error ); int libfsntfs_mft_attribute_clone( libfsntfs_mft_attribute_t **destination_mft_attribute, libfsntfs_mft_attribute_t *source_mft_attribute, libcerror_error_t **error ); int libfsntfs_mft_attribute_read_data( libfsntfs_mft_attribute_t *mft_attribute, libfsntfs_io_handle_t *io_handle, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_mft_attribute_data_is_resident( libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ); int libfsntfs_mft_attribute_get_type( libfsntfs_mft_attribute_t *mft_attribute, uint32_t *type, libcerror_error_t **error ); int libfsntfs_mft_attribute_get_data_flags( libfsntfs_mft_attribute_t *mft_attribute, uint16_t *data_flags, libcerror_error_t **error ); int libfsntfs_mft_attribute_get_data_size( libfsntfs_mft_attribute_t *mft_attribute, uint64_t *data_size, libcerror_error_t **error ); int libfsntfs_mft_attribute_get_data_vcn_range( libfsntfs_mft_attribute_t *mft_attribute, uint64_t *data_first_vcn, uint64_t *data_last_vcn, libcerror_error_t **error ); int libfsntfs_mft_attribute_get_allocated_data_size( libfsntfs_mft_attribute_t *mft_attribute, uint64_t *allocated_data_size, libcerror_error_t **error ); int libfsntfs_mft_attribute_get_valid_data_size( libfsntfs_mft_attribute_t *mft_attribute, uint64_t *valid_data_size, libcerror_error_t **error ); int libfsntfs_mft_attribute_get_utf8_name_size( libfsntfs_mft_attribute_t *mft_attribute, size_t *utf8_string_size, libcerror_error_t **error ); int libfsntfs_mft_attribute_get_utf8_name( libfsntfs_mft_attribute_t *mft_attribute, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); int libfsntfs_mft_attribute_get_utf16_name_size( libfsntfs_mft_attribute_t *mft_attribute, size_t *utf16_string_size, libcerror_error_t **error ); int libfsntfs_mft_attribute_get_utf16_name( libfsntfs_mft_attribute_t *mft_attribute, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); int libfsntfs_mft_attribute_compare_name_with_utf8_string( libfsntfs_mft_attribute_t *mft_attribute, const uint8_t *utf8_string, size_t utf8_string_length, libcerror_error_t **error ); int libfsntfs_mft_attribute_compare_name_with_utf16_string( libfsntfs_mft_attribute_t *mft_attribute, const uint16_t *utf16_string, size_t utf16_string_length, libcerror_error_t **error ); int libfsntfs_mft_attribute_get_compression_unit_size( libfsntfs_mft_attribute_t *mft_attribute, size_t *compression_unit_size, libcerror_error_t **error ); int libfsntfs_mft_attribute_get_resident_data( libfsntfs_mft_attribute_t *mft_attribute, uint8_t **resident_data, size_t *resident_data_size, libcerror_error_t **error ); int libfsntfs_mft_attribute_get_number_of_data_runs( libfsntfs_mft_attribute_t *mft_attribute, int *number_of_data_runs, libcerror_error_t **error ); int libfsntfs_mft_attribute_get_data_run_by_index( libfsntfs_mft_attribute_t *mft_attribute, int data_run_index, libfsntfs_data_run_t **data_run, libcerror_error_t **error ); int libfsntfs_mft_attribute_get_data_extents_array( libfsntfs_mft_attribute_t *mft_attribute, libfsntfs_io_handle_t *io_handle, libcdata_array_t **data_extents_array, libcerror_error_t **error ); int libfsntfs_mft_attribute_get_next_attribute( libfsntfs_mft_attribute_t *mft_attribute, libfsntfs_mft_attribute_t **next_attribute, libcerror_error_t **error ); int libfsntfs_mft_attribute_append_to_chain( libfsntfs_mft_attribute_t **first_attribute, libfsntfs_mft_attribute_t *additional_attribute, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_MFT_ATTRIBUTE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_mft_attribute_list.c ================================================ /* * Attribute list attribute ($ATTRIBUTE_LIST) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_cluster_block.h" #include "libfsntfs_cluster_block_stream.h" #include "libfsntfs_definitions.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libfcache.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_mft_attribute_list.h" #include "libfsntfs_mft_attribute_list_entry.h" #include "fsntfs_mft_attribute_list.h" /* Creates attribute list * Make sure the value attribute_list is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_initialize( libfsntfs_mft_attribute_list_t **attribute_list, uint64_t base_record_file_reference, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_list_initialize"; if( attribute_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list.", function ); return( -1 ); } if( *attribute_list != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid attribute list value already set.", function ); return( -1 ); } *attribute_list = memory_allocate_structure( libfsntfs_mft_attribute_list_t ); if( *attribute_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create attribute list.", function ); goto on_error; } if( memory_set( *attribute_list, 0, sizeof( libfsntfs_mft_attribute_list_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear attribute list.", function ); memory_free( *attribute_list ); *attribute_list = NULL; return( -1 ); } if( libcdata_array_initialize( &( ( *attribute_list )->entries_array ), 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create entries array.", function ); goto on_error; } if( libcdata_array_initialize( &( ( *attribute_list )->file_references_array ), 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file references array.", function ); goto on_error; } ( *attribute_list )->base_record_file_reference = base_record_file_reference; return( 1 ); on_error: if( *attribute_list != NULL ) { if( ( *attribute_list )->entries_array != NULL ) { libcdata_array_free( &( ( *attribute_list )->entries_array ), NULL, NULL ); } memory_free( *attribute_list ); *attribute_list = NULL; } return( -1 ); } /* Frees attribute list * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_free( libfsntfs_mft_attribute_list_t **attribute_list, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_list_free"; int result = 1; if( attribute_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list.", function ); return( -1 ); } if( *attribute_list != NULL ) { if( libcdata_array_free( &( ( *attribute_list )->entries_array ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_list_entry_free, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free entries array.", function ); result = -1; } if( libcdata_array_free( &( ( *attribute_list )->file_references_array ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_list_file_reference_free, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file references array.", function ); result = -1; } memory_free( *attribute_list ); *attribute_list = NULL; } return( result ); } /* Frees attribute list file reference * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_file_reference_free( uint64_t **file_reference, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_list_file_reference_free"; if( file_reference == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file reference.", function ); return( -1 ); } if( *file_reference != NULL ) { memory_free( *file_reference ); *file_reference = NULL; } return( 1 ); } /* Reads the attribute list * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_read_data( libfsntfs_mft_attribute_list_t *attribute_list, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry = NULL; static char *function = "libfsntfs_mft_attribute_list_read_data"; size_t data_offset = 0; int attribute_index = 0; int entry_index = 0; if( attribute_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: attribute list data:\n", function ); libcnotify_print_data( data, data_size, 0 ); } #endif while( data_offset < data_size ) { if( libfsntfs_mft_attribute_list_entry_initialize( &mft_attribute_list_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create MFT attribute list entry.", function ); goto on_error; } if( libfsntfs_mft_attribute_list_entry_read_data( mft_attribute_list_entry, &( data[ data_offset ] ), data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read MFT attribute list entry: %d.", function, attribute_index ); goto on_error; } data_offset += mft_attribute_list_entry->size; if( libcdata_array_append_entry( attribute_list->entries_array, &entry_index, (intptr_t *) mft_attribute_list_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append MFT attribute list entry: %d to array.", function, attribute_index ); goto on_error; } mft_attribute_list_entry = NULL; attribute_index++; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( data_offset < data_size ) { libcnotify_printf( "%s: alignment padding:\n", function ); libcnotify_print_data( &( data[ data_offset ] ), data_size - data_offset, 0 ); } } #endif return( 1 ); on_error: if( mft_attribute_list_entry != NULL ) { libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, NULL ); } return( -1 ); } /* Reads the attribute list * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_read_from_attribute( libfsntfs_mft_attribute_list_t *attribute_list, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfsntfs_mft_attribute_t *list_attribute, libcerror_error_t **error ) { uint8_t data[ sizeof( fsntfs_mft_attribute_list_entry_header_t ) + 256 ]; libfdata_stream_t *cluster_block_stream = NULL; libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry = NULL; static char *function = "libfsntfs_mft_attribute_list_read_from_attribute"; size64_t data_size = 0; ssize_t read_count = 0; off64_t data_offset = 0; int attribute_index = 0; int entry_index = 0; if( attribute_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list.", function ); return( -1 ); } if( libfsntfs_cluster_block_stream_initialize( &cluster_block_stream, io_handle, list_attribute, NULL, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create cluster block stream.", function ); goto on_error; } if( libfdata_stream_get_size( cluster_block_stream, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size from cluster block stream.", function ); goto on_error; } while( (size64_t) data_offset < data_size ) { if( memory_set( data, 0, sizeof( fsntfs_mft_attribute_list_entry_header_t ) + 256 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear data.", function ); goto on_error; } read_count = libfdata_stream_read_buffer_at_offset( cluster_block_stream, (intptr_t *) file_io_handle, data, sizeof( fsntfs_mft_attribute_list_entry_header_t ) + 256, data_offset, 0, error ); if( read_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read attribute list entry: %d from cluster block stream at offset: %" PRIi64 " (0x%08" PRIx64 ").", function, attribute_index, data_offset, data_offset ); goto on_error; } if( libfsntfs_mft_attribute_list_entry_initialize( &mft_attribute_list_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create attribute list entry: %d.", function, attribute_index ); goto on_error; } if( libfsntfs_mft_attribute_list_entry_read_data( mft_attribute_list_entry, data, sizeof( fsntfs_mft_attribute_list_entry_header_t ) + 256, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read attribute list entry: %d.", function, attribute_index ); goto on_error; } data_offset += mft_attribute_list_entry->size; if( libcdata_array_append_entry( attribute_list->entries_array, &entry_index, (intptr_t *) mft_attribute_list_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append attribute list entry: %d to array.", function, attribute_index ); goto on_error; } mft_attribute_list_entry = NULL; attribute_index++; } if( libfdata_stream_free( &cluster_block_stream, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free cluster block stream.", function ); goto on_error; } return( 1 ); on_error: if( mft_attribute_list_entry != NULL ) { libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, NULL ); } if( cluster_block_stream != NULL ) { libfdata_stream_free( &cluster_block_stream, NULL ); } return( -1 ); } /* Retrieves the number of attribute list entries * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_get_number_of_entries( libfsntfs_mft_attribute_list_t *attribute_list, int *number_of_entries, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_list_get_number_of_entries"; if( attribute_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list.", function ); return( -1 ); } if( libcdata_array_get_number_of_entries( attribute_list->entries_array, number_of_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of entries from array.", function ); return( -1 ); } return( 1 ); } /* Retrieves a specific attribute list entry * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_get_entry_by_index( libfsntfs_mft_attribute_list_t *attribute_list, int entry_index, libfsntfs_mft_attribute_list_entry_t **mft_attribute_list_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_get_attribute_by_index"; if( attribute_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list.", function ); return( -1 ); } if( libcdata_array_get_entry_by_index( attribute_list->entries_array, entry_index, (intptr_t **) mft_attribute_list_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry: %d from array.", function, entry_index ); return( -1 ); } return( 1 ); } /* Compares attribute lists by their base record file reference * Returns LIBCDATA_COMPARE_LESS, LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error */ int libfsntfs_mft_attribute_list_compare_by_base_record_file_reference( libfsntfs_mft_attribute_list_t *first_attribute_list, libfsntfs_mft_attribute_list_t *second_attribute_list, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_list_compare_by_base_record_file_reference"; uint64_t first_mft_entry_index = 0; uint64_t second_mft_entry_index = 0; if( first_attribute_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid first attribute list.", function ); return( -1 ); } if( second_attribute_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid second attribute list.", function ); return( -1 ); } first_mft_entry_index = first_attribute_list->base_record_file_reference & 0xffffffffffffUL; second_mft_entry_index = second_attribute_list->base_record_file_reference & 0xffffffffffffUL; if( first_mft_entry_index < second_mft_entry_index ) { return( LIBCDATA_COMPARE_LESS ); } else if( first_mft_entry_index > second_mft_entry_index ) { return( LIBCDATA_COMPARE_GREATER ); } return( LIBCDATA_COMPARE_EQUAL ); } /* Retrieves the number of attribute list data file references * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_get_number_of_file_references( libfsntfs_mft_attribute_list_t *attribute_list, int *number_of_file_references, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_list_get_number_of_file_references"; if( attribute_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list.", function ); return( -1 ); } if( libcdata_array_get_number_of_entries( attribute_list->file_references_array, number_of_file_references, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of entries from array.", function ); return( -1 ); } return( 1 ); } /* Retrieves a specific attribute list data file reference * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_get_file_reference_by_index( libfsntfs_mft_attribute_list_t *attribute_list, int file_reference_index, uint64_t *file_reference, libcerror_error_t **error ) { uint64_t *safe_file_reference = NULL; static char *function = "libfsntfs_mft_attribute_list_get_file_reference_by_index"; if( attribute_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list.", function ); return( -1 ); } if( file_reference == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file reference.", function ); return( -1 ); } if( libcdata_array_get_entry_by_index( attribute_list->file_references_array, file_reference_index, (intptr_t **) &safe_file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry: %d from array.", function, file_reference_index ); return( -1 ); } *file_reference = *safe_file_reference; return( 1 ); } /* Compares attribute list data file references * Returns LIBCDATA_COMPARE_LESS, LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error */ int libfsntfs_mft_attribute_list_compare_file_reference( uint64_t *first_file_reference, uint64_t *second_file_reference, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_list_compare_file_reference"; uint64_t first_mft_entry_index = 0; uint64_t second_mft_entry_index = 0; if( first_file_reference == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid first file reference.", function ); return( -1 ); } if( second_file_reference == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid second file reference.", function ); return( -1 ); } first_mft_entry_index = *first_file_reference & 0xffffffffffffUL; second_mft_entry_index = *second_file_reference & 0xffffffffffffUL; if( first_mft_entry_index < second_mft_entry_index ) { return( LIBCDATA_COMPARE_LESS ); } else if( first_mft_entry_index > second_mft_entry_index ) { return( LIBCDATA_COMPARE_GREATER ); } return( LIBCDATA_COMPARE_EQUAL ); } /* Insert an attribute list data file reference * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_insert_file_reference( libfsntfs_mft_attribute_list_t *attribute_list, uint64_t file_reference, libcerror_error_t **error ) { uint64_t *safe_file_reference = NULL; static char *function = "libfsntfs_mft_attribute_list_insert_file_reference"; int entry_index = 0; int result = 0; if( attribute_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list.", function ); return( -1 ); } safe_file_reference = (uint64_t *) memory_allocate( sizeof( uint64_t ) ); if( safe_file_reference == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create file reference.", function ); goto on_error; } *safe_file_reference = file_reference; result = libcdata_array_insert_entry( attribute_list->file_references_array, &entry_index, (intptr_t *) safe_file_reference, (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_mft_attribute_list_compare_file_reference, LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to insert file reference in array.", function ); goto on_error; } else if( result == 0 ) { memory_free( safe_file_reference ); } return( 1 ); on_error: if( safe_file_reference != NULL ) { memory_free( safe_file_reference ); } return( -1 ); } ================================================ FILE: libfsntfs/libfsntfs_mft_attribute_list.h ================================================ /* * Attribute list attribute ($ATTRIBUTE_LIST) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_MFT_ATTRIBUTE_LIST_H ) #define _LIBFSNTFS_MFT_ATTRIBUTE_LIST_H #include #include #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_mft_attribute_list_entry.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_mft_attribute_list libfsntfs_mft_attribute_list_t; struct libfsntfs_mft_attribute_list { /* The base record file reference */ uint64_t base_record_file_reference; /* The attribute list entries array */ libcdata_array_t *entries_array; /* The attribute list data file references attary */ libcdata_array_t *file_references_array; }; int libfsntfs_mft_attribute_list_initialize( libfsntfs_mft_attribute_list_t **attribute_list, uint64_t base_record_file_reference, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_free( libfsntfs_mft_attribute_list_t **attribute_list, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_file_reference_free( uint64_t **file_reference, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_read_data( libfsntfs_mft_attribute_list_t *attribute_list, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_read_from_attribute( libfsntfs_mft_attribute_list_t *attribute_list, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfsntfs_mft_attribute_t *list_attribute, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_get_number_of_entries( libfsntfs_mft_attribute_list_t *attribute_list, int *number_of_entries, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_get_entry_by_index( libfsntfs_mft_attribute_list_t *attribute_list, int entry_index, libfsntfs_mft_attribute_list_entry_t **mft_attribute_list_entry, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_compare_by_base_record_file_reference( libfsntfs_mft_attribute_list_t *first_attribute_list, libfsntfs_mft_attribute_list_t *second_attribute_list, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_get_number_of_file_references( libfsntfs_mft_attribute_list_t *attribute_list, int *number_of_file_references, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_get_file_reference_by_index( libfsntfs_mft_attribute_list_t *attribute_list, int file_reference_index, uint64_t *file_reference, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_compare_file_reference( uint64_t *first_file_reference, uint64_t *second_file_reference, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_insert_file_reference( libfsntfs_mft_attribute_list_t *attribute_list, uint64_t file_reference, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_MFT_ATTRIBUTE_LIST_H ) */ ================================================ FILE: libfsntfs/libfsntfs_mft_attribute_list_entry.c ================================================ /* * Attribute list entry functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_debug.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libuna.h" #include "libfsntfs_mft_attribute_list_entry.h" #include "libfsntfs_name.h" #include "fsntfs_mft_attribute_list.h" /* Creates attribute list entry * Make sure the value attribute_list_entry is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_entry_initialize( libfsntfs_mft_attribute_list_entry_t **attribute_list_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_list_entry_initialize"; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list entry.", function ); return( -1 ); } if( *attribute_list_entry != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid attribute list entry value already set.", function ); return( -1 ); } *attribute_list_entry = memory_allocate_structure( libfsntfs_mft_attribute_list_entry_t ); if( *attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create attribute list entry.", function ); goto on_error; } if( memory_set( *attribute_list_entry, 0, sizeof( libfsntfs_mft_attribute_list_entry_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear attribute list entry.", function ); goto on_error; } return( 1 ); on_error: if( *attribute_list_entry != NULL ) { memory_free( *attribute_list_entry ); *attribute_list_entry = NULL; } return( -1 ); } /* Frees attribute list entry * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_entry_free( libfsntfs_mft_attribute_list_entry_t **attribute_list_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_list_entry_free"; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list entry.", function ); return( -1 ); } if( *attribute_list_entry != NULL ) { if( ( *attribute_list_entry )->name != NULL ) { memory_free( ( *attribute_list_entry )->name ); } memory_free( *attribute_list_entry ); *attribute_list_entry = NULL; } return( 1 ); } /* Reads the attribute list entry * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_entry_read_data( libfsntfs_mft_attribute_list_entry_t *attribute_list_entry, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_list_entry_read_data"; size_t data_offset = 0; uint8_t name_offset = 0; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list entry.", function ); return( -1 ); } if( attribute_list_entry->name != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid attribute list entry - name value already set.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: data size value exceeds maximum.", function ); return( -1 ); } if( data_size < sizeof( fsntfs_mft_attribute_list_entry_header_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: unsupported data size value too small.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: attribute list entry header data:\n", function ); libcnotify_print_data( data, sizeof( fsntfs_mft_attribute_list_entry_header_t ), 0 ); } #endif byte_stream_copy_to_uint32_little_endian( ( (fsntfs_mft_attribute_list_entry_header_t *) data )->type, attribute_list_entry->attribute_type ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mft_attribute_list_entry_header_t *) data )->size, attribute_list_entry->size ); attribute_list_entry->name_size = (uint16_t) ( (fsntfs_mft_attribute_list_entry_header_t *) data )->name_size; name_offset = ( (fsntfs_mft_attribute_list_entry_header_t *) data )->name_offset; byte_stream_copy_to_uint64_little_endian( ( (fsntfs_mft_attribute_list_entry_header_t *) data )->data_first_vcn, attribute_list_entry->data_first_vcn ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_mft_attribute_list_entry_header_t *) data )->file_reference, attribute_list_entry->file_reference ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mft_attribute_list_entry_header_t *) data )->identifier, attribute_list_entry->identifier ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: type\t\t\t: 0x%08" PRIx32 " (%s)\n", function, attribute_list_entry->attribute_type, libfsntfs_debug_print_attribute_type( attribute_list_entry->attribute_type ) ); libcnotify_printf( "%s: size\t\t\t: %" PRIu16 "\n", function, attribute_list_entry->size ); libcnotify_printf( "%s: name size\t\t\t: %" PRIu16 "\n", function, attribute_list_entry->name_size ); libcnotify_printf( "%s: name offset\t\t: %" PRIu8 "\n", function, name_offset ); libcnotify_printf( "%s: data first VCN\t\t: %" PRIu64 "\n", function, attribute_list_entry->data_first_vcn ); libcnotify_printf( "%s: file reference\t\t: %" PRIu64 "-%" PRIu64 "\n", function, attribute_list_entry->file_reference & 0xffffffffffffUL, attribute_list_entry->file_reference >> 48 ); libcnotify_printf( "%s: identifier\t\t: %" PRIu16 "\n", function, attribute_list_entry->identifier ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ data_offset = sizeof( fsntfs_mft_attribute_list_entry_header_t ); if( ( attribute_list_entry->size < sizeof( fsntfs_mft_attribute_list_entry_header_t ) ) || ( attribute_list_entry->size > data_size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: size value out of bounds.", function ); goto on_error; } attribute_list_entry->name_size *= 2; if( attribute_list_entry->name_size > 0 ) { if( ( name_offset < sizeof( fsntfs_mft_attribute_list_entry_header_t ) ) || ( name_offset >= attribute_list_entry->size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: name offset value out of bounds.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( data_offset < name_offset ) { libcnotify_printf( "%s: unknown data:\n", function ); libcnotify_print_data( &( data[ data_offset ] ), (size_t) name_offset - data_offset, 0 ); } } #endif if( attribute_list_entry->name_size > ( attribute_list_entry->size - name_offset ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: name size value out of bounds.", function ); goto on_error; } data_offset = (size_t) name_offset; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: name data:\n", function ); libcnotify_print_data( &( data[ data_offset ] ), (size_t) attribute_list_entry->name_size, 0 ); } #endif attribute_list_entry->name = (uint8_t *) memory_allocate( sizeof( uint8_t ) * (size_t) attribute_list_entry->name_size ); if( attribute_list_entry->name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create name.", function ); goto on_error; } if( memory_copy( attribute_list_entry->name, &( data[ data_offset ] ), (size_t) attribute_list_entry->name_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy name.", function ); goto on_error; } data_offset += (size_t) attribute_list_entry->name_size; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( libfsntfs_debug_print_utf16_string_value( function, "name\t\t\t", attribute_list_entry->name, (size_t) attribute_list_entry->name_size, LIBUNA_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print UTF-16 string value.", function ); goto on_error; } libcnotify_printf( "\n" ); } #endif } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( data_offset < attribute_list_entry->size ) { libcnotify_printf( "%s: trailing data:\n", function ); libcnotify_print_data( &( data[ data_offset ] ), (size_t) attribute_list_entry->size - data_offset, 0 ); } else { libcnotify_printf( "\n" ); } } #endif return( 1 ); on_error: if( attribute_list_entry->name != NULL ) { memory_free( attribute_list_entry->name ); attribute_list_entry->name = NULL; } attribute_list_entry->name_size = 0; return( -1 ); } /* Retrieves the attribute type * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_entry_get_attribute_type( libfsntfs_mft_attribute_list_entry_t *attribute_list_entry, uint32_t *attribute_type, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_list_entry_get_attribute_type"; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list entry.", function ); return( -1 ); } if( attribute_type == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute type.", function ); return( -1 ); } *attribute_type = attribute_list_entry->attribute_type; return( 1 ); } /* Retrieves the file references as an MFT entry index and sequence number * If the value sequence_number is NULL it will be ignored * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_entry_get_file_reference( libfsntfs_mft_attribute_list_entry_t *attribute_list_entry, uint64_t *file_reference, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_list_entry_get_file_reference"; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list entry.", function ); return( -1 ); } if( file_reference == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file reference.", function ); return( -1 ); } *file_reference = attribute_list_entry->file_reference; return( 1 ); } /* Retrieves the size of the UTF-8 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_entry_get_utf8_name_size( libfsntfs_mft_attribute_list_entry_t *attribute_list_entry, size_t *utf8_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_list_entry_get_utf8_name_size"; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list entry.", function ); return( -1 ); } if( ( attribute_list_entry->name == NULL ) || ( attribute_list_entry->name_size == 0 ) ) { if( utf8_string_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-8 string size.", function ); return( -1 ); } *utf8_string_size = 0; } else { if( libuna_utf8_string_size_from_utf16_stream( attribute_list_entry->name, (size_t) attribute_list_entry->name_size, LIBUNA_ENDIAN_LITTLE, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 string size.", function ); return( -1 ); } } return( 1 ); } /* Retrieves the UTF-8 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_entry_get_utf8_name( libfsntfs_mft_attribute_list_entry_t *attribute_list_entry, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_list_entry_get_utf8_name"; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list entry.", function ); return( -1 ); } if( attribute_list_entry->name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid attribute list entry - missing name.", function ); return( -1 ); } if( libuna_utf8_string_copy_from_utf16_stream( utf8_string, utf8_string_size, attribute_list_entry->name, (size_t) attribute_list_entry->name_size, LIBUNA_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 string.", function ); return( -1 ); } return( 1 ); } /* Retrieves the size of the UTF-16 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_entry_get_utf16_name_size( libfsntfs_mft_attribute_list_entry_t *attribute_list_entry, size_t *utf16_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_list_entry_get_utf16_name_size"; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list entry.", function ); return( -1 ); } if( ( attribute_list_entry->name == NULL ) || ( attribute_list_entry->name_size == 0 ) ) { if( utf16_string_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-16 string size.", function ); return( -1 ); } *utf16_string_size = 0; } else { if( libuna_utf16_string_size_from_utf16_stream( attribute_list_entry->name, (size_t) attribute_list_entry->name_size, LIBUNA_ENDIAN_LITTLE, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 string size.", function ); return( -1 ); } } return( 1 ); } /* Retrieves the UTF-16 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_mft_attribute_list_entry_get_utf16_name( libfsntfs_mft_attribute_list_entry_t *attribute_list_entry, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_list_entry_get_utf16_name"; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute list entry.", function ); return( -1 ); } if( attribute_list_entry->name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid attribute list entry - missing name.", function ); return( -1 ); } if( libuna_utf16_string_copy_from_utf16_stream( utf16_string, utf16_string_size, attribute_list_entry->name, (size_t) attribute_list_entry->name_size, LIBUNA_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 string.", function ); return( -1 ); } return( 1 ); } /* Compares the name with an UTF-8 encoded string * Returns 1 if the strings are equal, 0 if not or -1 on error */ int libfsntfs_mft_attribute_list_entry_compare_name_with_utf8_string( libfsntfs_mft_attribute_list_entry_t *attribute_list_entry, const uint8_t *utf8_string, size_t utf8_string_length, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_list_entry_compare_name_with_utf8_string"; int result = 0; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( attribute_list_entry->name == NULL ) { return( 0 ); } result = libfsntfs_name_compare_with_utf8_string( attribute_list_entry->name, attribute_list_entry->name_size, utf8_string, utf8_string_length, 0, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GENERIC, "%s: unable to compare UTF-8 string with name.", function ); return( -1 ); } else if( result == LIBUNA_COMPARE_EQUAL ) { return( 1 ); } return( 0 ); } /* Compares the name with an UTF-16 encoded string * Returns 1 if the strings are equal, 0 if not or -1 on error */ int libfsntfs_mft_attribute_list_entry_compare_name_with_utf16_string( libfsntfs_mft_attribute_list_entry_t *attribute_list_entry, const uint16_t *utf16_string, size_t utf16_string_length, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_attribute_list_entry_compare_name_with_utf16_string"; int result = 0; if( attribute_list_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT attribute.", function ); return( -1 ); } if( attribute_list_entry->name == NULL ) { return( 0 ); } result = libfsntfs_name_compare_with_utf16_string( attribute_list_entry->name, attribute_list_entry->name_size, utf16_string, utf16_string_length, 0, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GENERIC, "%s: unable to compare UTF-16 string with name.", function ); return( -1 ); } else if( result == LIBUNA_COMPARE_EQUAL ) { return( 1 ); } return( 0 ); } ================================================ FILE: libfsntfs/libfsntfs_mft_attribute_list_entry.h ================================================ /* * Attribute list entry functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_MFT_ATTRIBUTE_LIST_ENTRY_H ) #define _LIBFSNTFS_MFT_ATTRIBUTE_LIST_ENTRY_H #include #include #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_mft_attribute_list_entry libfsntfs_mft_attribute_list_entry_t; struct libfsntfs_mft_attribute_list_entry { /* The attribute type */ uint32_t attribute_type; /* The size */ uint16_t size; /* The name size */ uint16_t name_size; /* The data first VCN */ uint64_t data_first_vcn; /* The file reference */ uint64_t file_reference; /* The identifier */ uint16_t identifier; /* The name */ uint8_t *name; }; int libfsntfs_mft_attribute_list_entry_initialize( libfsntfs_mft_attribute_list_entry_t **attribute_list_entry, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_entry_free( libfsntfs_mft_attribute_list_entry_t **attribute_list_entry, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_entry_read_data( libfsntfs_mft_attribute_list_entry_t *attribute_list_entry, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_entry_get_attribute_type( libfsntfs_mft_attribute_list_entry_t *attribute_list_entry, uint32_t *type, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_entry_get_file_reference( libfsntfs_mft_attribute_list_entry_t *attribute_list_entry, uint64_t *file_reference, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_entry_get_utf8_name_size( libfsntfs_mft_attribute_list_entry_t *attribute_list_entry, size_t *utf8_string_size, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_entry_get_utf8_name( libfsntfs_mft_attribute_list_entry_t *attribute_list_entry, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_entry_get_utf16_name_size( libfsntfs_mft_attribute_list_entry_t *attribute_list_entry, size_t *utf16_string_size, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_entry_get_utf16_name( libfsntfs_mft_attribute_list_entry_t *attribute_list_entry, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_entry_compare_name_with_utf8_string( libfsntfs_mft_attribute_list_entry_t *attribute_list_entry, const uint8_t *utf8_string, size_t utf8_string_length, libcerror_error_t **error ); int libfsntfs_mft_attribute_list_entry_compare_name_with_utf16_string( libfsntfs_mft_attribute_list_entry_t *attribute_list_entry, const uint16_t *utf16_string, size_t utf16_string_length, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_MFT_ATTRIBUTE_LIST_ENTRY_H ) */ ================================================ FILE: libfsntfs/libfsntfs_mft_entry.c ================================================ /* * Master File Table (MFT) entry functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_debug.h" #include "libfsntfs_definitions.h" #include "libfsntfs_directory_entry.h" #include "libfsntfs_fixup_values.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libfcache.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_libuna.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_mft_attribute_list.h" #include "libfsntfs_mft_attribute_list_entry.h" #include "libfsntfs_mft_entry.h" #include "libfsntfs_mft_entry_header.h" #include "libfsntfs_standard_information_values.h" #include "libfsntfs_types.h" #include "libfsntfs_unused.h" #include "fsntfs_mft_entry.h" const char fsntfs_mft_entry_signature[ 4 ] = { 'F', 'I', 'L', 'E' }; /* Checks if a buffer containing the MFT entry is filled with 0-byte values (empty-block) * Returns 1 if empty, 0 if not or -1 on error */ int libfsntfs_mft_entry_check_for_empty_block( const uint8_t *data, size_t data_size, libcerror_error_t **error ) { libfsntfs_aligned_t *aligned_data_index = NULL; libfsntfs_aligned_t *aligned_data_start = NULL; uint8_t *data_index = NULL; uint8_t *data_start = NULL; static char *function = "libfsntfs_mft_entry_check_for_empty_block"; if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid data size value exceeds maximum.", function ); return( -1 ); } data_start = (uint8_t *) data; data_index = (uint8_t *) data + 1; data_size -= 1; /* Only optimize for data larger than the alignment */ if( data_size > ( 2 * sizeof( libfsntfs_aligned_t ) ) ) { /* Align the data start */ while( ( (intptr_t) data_start % sizeof( libfsntfs_aligned_t ) ) != 0 ) { if( *data_start != *data_index ) { return( 0 ); } data_start += 1; data_index += 1; data_size -= 1; } /* Align the data index */ while( ( (intptr_t) data_index % sizeof( libfsntfs_aligned_t ) ) != 0 ) { if( *data_start != *data_index ) { return( 0 ); } data_index += 1; data_size -= 1; } aligned_data_start = (libfsntfs_aligned_t *) data_start; aligned_data_index = (libfsntfs_aligned_t *) data_index; while( data_size > sizeof( libfsntfs_aligned_t ) ) { if( *aligned_data_start != *aligned_data_index ) { return( 0 ); } aligned_data_index += 1; data_size -= sizeof( libfsntfs_aligned_t ); } data_index = (uint8_t *) aligned_data_index; } while( data_size != 0 ) { if( *data_start != *data_index ) { return( 0 ); } data_index += 1; data_size -= 1; } return( 1 ); } /* Creates a MFT entry * Make sure the value mft_entry is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_initialize( libfsntfs_mft_entry_t **mft_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_initialize"; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( *mft_entry != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT entry value already set.", function ); return( -1 ); } *mft_entry = memory_allocate_structure( libfsntfs_mft_entry_t ); if( *mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create MFT entry.", function ); goto on_error; } if( memory_set( *mft_entry, 0, sizeof( libfsntfs_mft_entry_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear MFT entry.", function ); memory_free( *mft_entry ); *mft_entry = NULL; return( -1 ); } if( libcdata_array_initialize( &( ( *mft_entry )->attributes_array ), 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create attributes array.", function ); goto on_error; } if( libcdata_array_initialize( &( ( *mft_entry )->alternate_data_attributes_array ), 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create alternate data attributes array.", function ); goto on_error; } ( *mft_entry )->file_name_attribute_index = -1; ( *mft_entry )->reparse_point_attribute_index = -1; ( *mft_entry )->security_descriptor_attribute_index = -1; ( *mft_entry )->standard_information_attribute_index = -1; ( *mft_entry )->volume_information_attribute_index = -1; ( *mft_entry )->volume_name_attribute_index = -1; return( 1 ); on_error: if( *mft_entry != NULL ) { if( ( *mft_entry )->alternate_data_attributes_array != NULL ) { libcdata_array_free( &( ( *mft_entry )->alternate_data_attributes_array ), NULL, NULL ); } if( ( *mft_entry )->attributes_array != NULL ) { libcdata_array_free( &( ( *mft_entry )->attributes_array ), NULL, NULL ); } memory_free( *mft_entry ); *mft_entry = NULL; } return( -1 ); } /* Frees a MFT entry * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_free( libfsntfs_mft_entry_t **mft_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_free"; int result = 1; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( *mft_entry != NULL ) { if( ( *mft_entry )->header != NULL ) { if( libfsntfs_mft_entry_header_free( &( ( *mft_entry )->header ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free MFT entry header.", function ); result = -1; } } if( ( *mft_entry )->data != NULL ) { memory_free( ( *mft_entry )->data ); } /* The specific attribute references point to attributes in the array * and are freed by freeing the array and its values */ if( libcdata_array_free( &( ( *mft_entry )->attributes_array ), (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_free, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free attributes array.", function ); result = -1; } if( ( *mft_entry )->attribute_list != NULL ) { if( libfsntfs_mft_attribute_list_free( &( ( *mft_entry )->attribute_list ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free attribute list.", function ); result = -1; } } /* The alternate_data_attributes_array only contains references that are managed * by the attributes_array */ if( libcdata_array_free( &( ( *mft_entry )->alternate_data_attributes_array ), NULL, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free alternate data attributes array.", function ); result = -1; } memory_free( *mft_entry ); *mft_entry = NULL; } return( result ); } /* Reads the MFT entry * Returns 1 if successful, 0 if empty or marked as bad, or -1 on error */ int libfsntfs_mft_entry_read_data( libfsntfs_mft_entry_t *mft_entry, uint8_t *data, size_t data_size, uint32_t mft_entry_index, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_read_data"; size_t data_offset = 0; size_t unknown_data_size = 0; uint16_t attributes_offset = 0; uint16_t fixup_values_offset = 0; uint16_t number_of_fixup_values = 0; int result = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint32_t total_entry_size = 0; #endif if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( mft_entry->header != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT entry - header value already set.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid data size value exceeds maximum.", function ); return( -1 ); } result = libfsntfs_mft_entry_check_for_empty_block( data, data_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if MFT entry is empty.", function ); goto on_error; } else if( result != 0 ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: MFT entry: %" PRIu32 " is empty.\n", function, mft_entry_index ); } #endif mft_entry->is_empty = 1; return( 0 ); } if( libfsntfs_mft_entry_header_initialize( &( mft_entry->header ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create MFT entry header.", function ); goto on_error; } result = libfsntfs_mft_entry_header_read_data( mft_entry->header, data, data_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read MFT entry header.", function ); goto on_error; } else if( result == 0 ) { /* Note that an empty MFT data can contain arbitrary data */ mft_entry->is_empty = 1; return( 0 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( libfsntfs_mft_entry_header_get_total_entry_size( mft_entry->header, &total_entry_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve total entry size.", function ); goto on_error; } if( data_size != (size_t) total_entry_size ) { libcnotify_printf( "%s: mismatch in total MFT entry size (calculated: %" PRIzd ", stored: %" PRIu32 ").\n", function, data_size, total_entry_size ); } } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ if( libfsntfs_mft_entry_header_get_attributes_offset( mft_entry->header, &attributes_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attributes offset.", function ); goto on_error; } if( attributes_offset >= data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attributes offset value out of bounds.", function ); goto on_error; } if( libfsntfs_mft_entry_header_get_fixup_values_offset( mft_entry->header, &fixup_values_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve fix-up values offset.", function ); goto on_error; } if( fixup_values_offset > attributes_offset ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: fix-up values offset exceeds attributes offset.", function ); goto on_error; } if( fixup_values_offset > 42 ) { data_offset = sizeof( fsntfs_mft_entry_header_t ); } else { /* In NTFS 1.2 the fix-up values offset can point to wfixupPattern */ data_offset = 42; } if( data_offset < fixup_values_offset ) { unknown_data_size = (size_t) fixup_values_offset - data_offset; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: unknown data:\n", function ); libcnotify_print_data( &( data[ data_offset ] ), unknown_data_size, 0 ); } #endif data_offset += unknown_data_size; } if( libfsntfs_mft_entry_header_get_number_of_fixup_values( mft_entry->header, &number_of_fixup_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of fix-up values.", function ); goto on_error; } if( number_of_fixup_values > 0 ) { if( libfsntfs_fixup_values_apply( data, data_size, fixup_values_offset, number_of_fixup_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to apply fix-up values.", function ); goto on_error; } data_offset += 2 + ( (size_t) number_of_fixup_values * 2 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( data_offset < attributes_offset ) { libcnotify_printf( "%s: unknown data:\n", function ); libcnotify_print_data( &( data[ data_offset ] ), (size_t) attributes_offset - data_offset, 0 ); } } #endif mft_entry->is_empty = 0; mft_entry->index = mft_entry->header->index; if( mft_entry->index != mft_entry_index ) { mft_entry->index = mft_entry_index; } mft_entry->file_reference = ( (uint64_t) mft_entry->header->sequence << 48 ) | mft_entry->index; return( 1 ); on_error: if( mft_entry->header != NULL ) { libfsntfs_mft_entry_header_free( &( mft_entry->header ), NULL ); } return( -1 ); } /* Reads the MFT entry * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_read_file_io_handle( libfsntfs_mft_entry_t *mft_entry, libbfio_handle_t *file_io_handle, off64_t file_offset, uint32_t mft_entry_size, uint32_t mft_entry_index, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_read_file_io_handle"; ssize_t read_count = 0; int result = 0; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( mft_entry->data != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT entry - data value already set.", function ); return( -1 ); } if( ( (size_t) mft_entry_size <= 42 ) || ( (size_t) mft_entry_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid MFT entry size value out of bounds.", function ); goto on_error; } mft_entry->data = (uint8_t *) memory_allocate( (size_t) mft_entry_size ); if( mft_entry->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create MFT entry data.", function ); goto on_error; } mft_entry->data_size = (size_t) mft_entry_size; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading MFT entry at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, file_offset, file_offset ); } #endif read_count = libbfio_handle_read_buffer_at_offset( file_io_handle, mft_entry->data, mft_entry->data_size, file_offset, error ); if( read_count != (ssize_t) mft_entry->data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read MFT entry data at offset: %" PRIi64 " (0x%08" PRIx64 ").", function, file_offset, file_offset ); goto on_error; } result = libfsntfs_mft_entry_read_data( mft_entry, mft_entry->data, mft_entry->data_size, mft_entry_index, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read MFT entry data.", function ); goto on_error; } else if( result == 0 ) { memory_free( mft_entry->data ); mft_entry->data = NULL; mft_entry->data_size = 0; } return( 1 ); on_error: if( mft_entry->header != NULL ) { libfsntfs_mft_entry_header_free( &( mft_entry->header ), NULL ); } if( mft_entry->data != NULL ) { memory_free( mft_entry->data ); mft_entry->data = NULL; } mft_entry->data_size = 0; return( -1 ); } /* Reads the MFT attributes * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_read_attributes_data( libfsntfs_mft_entry_t *mft_entry, libfsntfs_io_handle_t *io_handle, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { libfsntfs_mft_attribute_t *mft_attribute = NULL; static char *function = "libfsntfs_mft_entry_read_attributes_data"; size_t data_offset = 0; uint32_t attribute_type = 0; uint16_t attributes_offset = 0; int attribute_index = 0; int entry_index = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint32_t used_entry_size = 0; #endif if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid data size value exceeds maximum.", function ); return( -1 ); } if( data_size < 4 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: unsupported data size value too small\n", function ); return( -1 ); } if( libfsntfs_mft_entry_header_get_attributes_offset( mft_entry->header, &attributes_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attributes offset.", function ); goto on_error; } data_offset = (size_t) attributes_offset; do { if( data_offset > ( data_size - 4 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid MFT entry - attribute offset: %d value out of bounds.", function, attribute_index ); goto on_error; } byte_stream_copy_to_uint32_little_endian( &( data[ data_offset ] ), attribute_type ); if( attribute_type == LIBFSNTFS_ATTRIBUTE_TYPE_END_OF_ATTRIBUTES ) { break; } if( libfsntfs_mft_attribute_initialize( &mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create MFT attribute: %d.", function, attribute_index ); goto on_error; } if( libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, &( data[ data_offset ] ), data_size - data_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read MFT attribute: %d of type: 0x%08" PRIx32 ".", function, attribute_index, attribute_type ); goto on_error; } data_offset += mft_attribute->size; if( attribute_type == LIBFSNTFS_ATTRIBUTE_TYPE_ATTRIBUTE_LIST ) { if( mft_entry->list_attribute != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT entry - list attribute value already set.", function ); goto on_error; } mft_entry->list_attribute = mft_attribute; } /* mft_entry->attributes_array takes over management of mft_attribute */ if( libcdata_array_append_entry( mft_entry->attributes_array, &entry_index, (intptr_t *) mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append attribute to array.", function ); goto on_error; } if( libfsntfs_mft_entry_set_attribute_helper_values( mft_entry, entry_index, mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set helper values for attribute: %d.", function, attribute_index ); mft_attribute = NULL; goto on_error; } mft_attribute = NULL; attribute_index++; } while( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_END_OF_ATTRIBUTES ); data_offset += 4; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( libfsntfs_mft_entry_header_get_used_entry_size( mft_entry->header, &used_entry_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve used entry size.", function ); goto on_error; } if( data_offset != (size_t) used_entry_size ) { libcnotify_printf( "%s: mismatch in used MFT entry size (calculated: %" PRIzd ", stored: %" PRIu32 ").\n", function, data_offset, used_entry_size ); } } #endif return( 1 ); on_error: if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } libcdata_array_empty( mft_entry->attributes_array, (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_free, NULL ); mft_entry->file_name_attribute_index = -1; mft_entry->reparse_point_attribute_index = -1; mft_entry->security_descriptor_attribute_index = -1; mft_entry->standard_information_attribute_index = -1; mft_entry->volume_information_attribute_index = -1; mft_entry->volume_name_attribute_index = -1; mft_entry->list_attribute = NULL; mft_entry->data_attribute = NULL; mft_entry->wof_compressed_data_attribute = NULL; return( -1 ); } /* Reads the MFT attributes * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_read_attributes( libfsntfs_mft_entry_t *mft_entry, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfdata_vector_t *mft_entry_vector, libcdata_btree_t *attribute_list_tree, uint8_t flags, libcerror_error_t **error ) { libcdata_tree_node_t *upper_node = NULL; libfsntfs_mft_attribute_list_t *attribute_list = NULL; libfsntfs_mft_attribute_list_t *lookup_attribute_list = NULL; static char *function = "libfsntfs_mft_entry_read_attributes"; int result = 0; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( mft_entry->attributes_read != 0 ) { return( 1 ); } if( mft_entry->is_empty == 0 ) { if( libfsntfs_mft_entry_read_attributes_data( mft_entry, io_handle, mft_entry->data, mft_entry->data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read attributes of MFT entry: %d.", function, mft_entry->index ); goto on_error; } if( mft_entry->list_attribute != NULL ) { if( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) != 0 ) { if( libfsntfs_mft_attribute_list_initialize( &lookup_attribute_list, mft_entry->file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create lookup attribute list.", function ); goto on_error; } result = libcdata_btree_get_value_by_value( attribute_list_tree, (intptr_t *) lookup_attribute_list, (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_mft_attribute_list_compare_by_base_record_file_reference, &upper_node, (intptr_t **) &attribute_list, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve path hint from tree.", function ); goto on_error; } if( libfsntfs_mft_attribute_list_free( &lookup_attribute_list, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free lookup attribute list.", function ); goto on_error; } } else { if( libfsntfs_mft_entry_read_attribute_list( mft_entry, io_handle, file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read attribute list.", function ); goto on_error; } attribute_list = mft_entry->attribute_list; } if( attribute_list != NULL ) { if( libfsntfs_mft_entry_read_attribute_list_data_mft_entries( mft_entry, attribute_list, io_handle, file_io_handle, mft_entry_vector, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read attribute list data MFT entries.", function ); goto on_error; } } else { mft_entry->is_corrupted = 1; } } } mft_entry->attributes_read = 1; return( 1 ); on_error: if( lookup_attribute_list != NULL ) { libfsntfs_mft_attribute_list_free( &lookup_attribute_list, NULL ); } if( mft_entry->attribute_list != NULL ) { libfsntfs_mft_attribute_list_free( &( mft_entry->attribute_list ), NULL ); } libcdata_array_empty( mft_entry->alternate_data_attributes_array, NULL, NULL ); libcdata_array_empty( mft_entry->attributes_array, (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_free, NULL ); return( -1 ); } /* Reads the attribute list * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_read_attribute_list( libfsntfs_mft_entry_t *mft_entry, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libcerror_error_t **error ) { libfsntfs_mft_attribute_list_entry_t *attribute_list_entry = NULL; static char *function = "libfsntfs_mft_entry_read_attribute_list"; uint64_t attribute_list_data_mft_entry_index = 0; uint64_t file_reference = 0; int attribute_list_entry_index = 0; int number_of_attribute_list_entries = 0; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( mft_entry->list_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid MFT entry - missing list attribute.", function ); return( -1 ); } if( mft_entry->attribute_list != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT entry - attribute list value already set.", function ); return( -1 ); } if( libfsntfs_mft_attribute_list_initialize( &( mft_entry->attribute_list ), mft_entry->file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create attribute list.", function ); goto on_error; } if( libfsntfs_mft_attribute_list_read_from_attribute( mft_entry->attribute_list, io_handle, file_io_handle, mft_entry->list_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read attribute list.", function ); goto on_error; } if( libfsntfs_mft_attribute_list_get_number_of_entries( mft_entry->attribute_list, &number_of_attribute_list_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of attribute list entries.", function ); goto on_error; } for( attribute_list_entry_index = 0; attribute_list_entry_index < number_of_attribute_list_entries; attribute_list_entry_index++ ) { if( libfsntfs_mft_attribute_list_get_entry_by_index( mft_entry->attribute_list, attribute_list_entry_index, &attribute_list_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute list entry: %d.", function, attribute_list_entry_index ); goto on_error; } if( libfsntfs_mft_attribute_list_entry_get_file_reference( attribute_list_entry, &file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute list entry: %d file reference.", function, attribute_list_entry_index ); goto on_error; } attribute_list_data_mft_entry_index = file_reference & 0xffffffffffffUL; if( attribute_list_data_mft_entry_index > (uint64_t) INT_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: attribute list data MFT entry reference value out of bounds.", function ); goto on_error; } /* Ignore the current MFT entry */ if( attribute_list_data_mft_entry_index == (uint64_t) mft_entry->index ) { continue; } if( libfsntfs_mft_attribute_list_insert_file_reference( mft_entry->attribute_list, file_reference, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to insert attribute list data file reference in attribute list.", function ); goto on_error; } } return( 1 ); on_error: if( mft_entry->attribute_list != NULL ) { libfsntfs_mft_attribute_list_free( &( mft_entry->attribute_list ), NULL ); } return( -1 ); } /* Reads a specific attribute list data MFT entry * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_mft_entry_read_attribute_list_data_mft_entry_by_index( libfsntfs_mft_entry_t *mft_entry, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfdata_vector_t *mft_entry_vector, libfcache_cache_t *mft_entry_cache, uint64_t file_reference, libcerror_error_t **error ) { libfsntfs_mft_attribute_t *data_mft_attribute = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; libfsntfs_mft_entry_t *data_mft_entry = NULL; static char *function = "libfsntfs_mft_entry_read_attribute_list_data_mft_entry_by_index"; uint64_t attribute_list_data_mft_entry = 0; uint64_t base_record_file_reference = 0; int attribute_index = 0; int entry_index = 0; int number_of_attributes = 0; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } attribute_list_data_mft_entry = file_reference & 0xffffffffffffUL; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading data file reference: %" PRIu64 "-%" PRIu16 "\n", function, attribute_list_data_mft_entry, (uint16_t) ( file_reference >> 48 ) ); libcnotify_printf( "\n" ); } #endif if( libfdata_vector_get_element_value_by_index( mft_entry_vector, (intptr_t *) file_io_handle, (libfdata_cache_t *) mft_entry_cache, (int) attribute_list_data_mft_entry, (intptr_t **) &data_mft_entry, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: %" PRIu64 ".", function, attribute_list_data_mft_entry ); return( -1 ); } if( data_mft_entry->header == NULL ) { return( 0 ); } if( libfsntfs_mft_entry_header_get_base_record_file_reference( data_mft_entry->header, &base_record_file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve base record file reference.", function ); return( -1 ); } if( mft_entry->file_reference != base_record_file_reference ) { return( 0 ); } if( libfsntfs_mft_entry_read_attributes_data( data_mft_entry, io_handle, data_mft_entry->data, data_mft_entry->data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read attributes.", function ); return( -1 ); } if( libcdata_array_get_number_of_entries( data_mft_entry->attributes_array, &number_of_attributes, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of attributes.", function ); return( -1 ); } for( attribute_index = 0; attribute_index < number_of_attributes; attribute_index++ ) { if( libcdata_array_get_entry_by_index( data_mft_entry->attributes_array, attribute_index, (intptr_t **) &mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute: %d from list MFT entry.", function, attribute_index ); return( -1 ); } if( libfsntfs_mft_attribute_clone( &data_mft_attribute, mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to clone MFT attribute: %d.", function, attribute_index ); return( -1 ); } /* mft_entry->attributes_array takes over management of data_mft_attribute */ if( libcdata_array_append_entry( mft_entry->attributes_array, &entry_index, (intptr_t *) data_mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append MFT attribute to array.", function ); libfsntfs_mft_attribute_free( &data_mft_attribute, NULL ); return( -1 ); } if( libfsntfs_mft_entry_set_attribute_helper_values( mft_entry, entry_index, data_mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set helper values for attribute: %d.", function, entry_index ); return( -1 ); } data_mft_attribute = NULL; } return( 1 ); } /* Reads the attribute list data MFT entries * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_read_attribute_list_data_mft_entries( libfsntfs_mft_entry_t *mft_entry, libfsntfs_mft_attribute_list_t *attribute_list, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfdata_vector_t *mft_entry_vector, libcerror_error_t **error ) { libfcache_cache_t *mft_entry_cache = NULL; static char *function = "libfsntfs_mft_entry_read_attribute_list_data_mft_entries"; uint64_t file_reference = 0; int file_reference_index = 0; int number_of_file_entries = 0; int result = 0; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } /* Read the list data MFT entries * Use a local cache to prevent cache outs */ if( libfcache_cache_initialize( &mft_entry_cache, 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create MFT entry cache.", function ); goto on_error; } if( libfsntfs_mft_attribute_list_get_number_of_file_references( attribute_list, &number_of_file_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of attribute list data MFT entries.", function ); goto on_error; } for( file_reference_index = 0; file_reference_index < number_of_file_entries; file_reference_index++ ) { if( libfsntfs_mft_attribute_list_get_file_reference_by_index( attribute_list, file_reference_index, &file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute list data MFT entry: %d.", function, file_reference_index ); goto on_error; } result = libfsntfs_mft_entry_read_attribute_list_data_mft_entry_by_index( mft_entry, io_handle, file_io_handle, mft_entry_vector, mft_entry_cache, file_reference, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read attribute list data MFT entry: %" PRIu64 "-%" PRIu64 ".", function, file_reference & 0xffffffffffffUL, file_reference >> 48 ); goto on_error; } else if( result == 0 ) { mft_entry->is_corrupted = 1; } } if( libfcache_cache_free( &mft_entry_cache, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free MFT entry cache.", function ); goto on_error; } return( 1 ); on_error: if( mft_entry_cache != NULL ) { libfcache_cache_free( &mft_entry_cache, NULL ); } return( -1 ); } /* Determines if the MFT entry is empty * Returns 1 if empty, 0 if not or -1 on error */ int libfsntfs_mft_entry_is_empty( libfsntfs_mft_entry_t *mft_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_is_empty"; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } return( (int) mft_entry->is_empty ); } /* Determines if the MFT entry is allocated (in use) * Returns 1 if allocated, 0 if not or -1 on error */ int libfsntfs_mft_entry_is_allocated( libfsntfs_mft_entry_t *mft_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_is_allocated"; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( mft_entry->header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid MFT entry - missing header.", function ); return( -1 ); } if( ( mft_entry->header->flags & LIBFSNTFS_MFT_ENTRY_FLAG_IN_USE ) != 0 ) { return( 1 ); } return( 0 ); } /* Determines if the MFT entry is corrupted * Returns 1 if corrupted, 0 if not or -1 on error */ int libfsntfs_mft_entry_is_corrupted( libfsntfs_mft_entry_t *mft_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_is_corrupted"; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } return( (int) mft_entry->is_corrupted ); } /* Retrieves the file reference * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_get_file_reference( libfsntfs_mft_entry_t *mft_entry, uint64_t *file_reference, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_get_file_reference"; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( file_reference == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file reference.", function ); return( -1 ); } *file_reference = mft_entry->file_reference; return( 1 ); } /* Retrieves the base record file reference * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_mft_entry_get_base_record_file_reference( libfsntfs_mft_entry_t *mft_entry, uint64_t *file_reference, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_get_base_record_file_reference"; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( mft_entry->header == NULL ) { return( 0 ); } if( libfsntfs_mft_entry_header_get_base_record_file_reference( mft_entry->header, file_reference, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve base record file reference.", function ); return( -1 ); } return( 1 ); } /* Retrieves the journal sequence number * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_get_journal_sequence_number( libfsntfs_mft_entry_t *mft_entry, uint64_t *journal_sequence_number, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_get_journal_sequence_number"; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( libfsntfs_mft_entry_header_get_journal_sequence_number( mft_entry->header, journal_sequence_number, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve journal sequence number.", function ); return( -1 ); } return( 1 ); } /* Retrieves the number of attributes * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_get_number_of_attributes( libfsntfs_mft_entry_t *mft_entry, int *number_of_attributes, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_get_number_of_attributes"; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( libcdata_array_get_number_of_entries( mft_entry->attributes_array, number_of_attributes, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of entries from attributes array.", function ); return( -1 ); } return( 1 ); } /* Retrieves a specific attribute * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_get_attribute_by_index( libfsntfs_mft_entry_t *mft_entry, int attribute_index, libfsntfs_mft_attribute_t **attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_get_attribute_by_index"; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( libcdata_array_get_entry_by_index( mft_entry->attributes_array, attribute_index, (intptr_t **) attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry: %d from attributes array.", function, attribute_index ); return( -1 ); } return( 1 ); } /* Retrieves the $STANDARD_INFORMATION attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_mft_entry_get_standard_information_attribute( libfsntfs_mft_entry_t *mft_entry, libfsntfs_mft_attribute_t **attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_get_standard_information_attribute"; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( mft_entry->standard_information_attribute_index == -1 ) { return( 0 ); } if( libcdata_array_get_entry_by_index( mft_entry->attributes_array, mft_entry->standard_information_attribute_index, (intptr_t **) attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry: %d from attributes array.", function, mft_entry->standard_information_attribute_index ); return( -1 ); } return( 1 ); } /* Retrieves the $VOLUME_INFORMATION attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_mft_entry_get_volume_information_attribute( libfsntfs_mft_entry_t *mft_entry, libfsntfs_mft_attribute_t **attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_get_volume_information_attribute"; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( mft_entry->volume_information_attribute_index == -1 ) { return( 0 ); } if( libcdata_array_get_entry_by_index( mft_entry->attributes_array, mft_entry->volume_information_attribute_index, (intptr_t **) attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry: %d from attributes array.", function, mft_entry->volume_information_attribute_index ); return( -1 ); } return( 1 ); } /* Retrieves the $VOLUME_NAME attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_mft_entry_get_volume_name_attribute( libfsntfs_mft_entry_t *mft_entry, libfsntfs_mft_attribute_t **attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_get_volume_name_attribute"; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( mft_entry->volume_name_attribute_index == -1 ) { return( 0 ); } if( libcdata_array_get_entry_by_index( mft_entry->attributes_array, mft_entry->volume_name_attribute_index, (intptr_t **) attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry: %d from attributes array.", function, mft_entry->volume_name_attribute_index ); return( -1 ); } return( 1 ); } /* Retrieves the number of alternate data attributes * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_get_number_of_alternate_data_attributes( libfsntfs_mft_entry_t *mft_entry, int *number_of_attributes, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_get_number_of_alternate_data_attributes"; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( libcdata_array_get_number_of_entries( mft_entry->alternate_data_attributes_array, number_of_attributes, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of entries from alternate data attributes array.", function ); return( -1 ); } return( 1 ); } /* Retrieves a specific alternate data attribute * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_get_alternate_data_attribute_by_index( libfsntfs_mft_entry_t *mft_entry, int attribute_index, libfsntfs_mft_attribute_t **attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_get_alternate_data_attribute_by_index"; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( libcdata_array_get_entry_by_index( mft_entry->alternate_data_attributes_array, attribute_index, (intptr_t **) attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry: %d from alternate data attributes array.", function, attribute_index ); return( -1 ); } return( 1 ); } /* Retrieves a specific alternate data attribute for an UTF-8 encoded name * Returns 1 if successful, 0 if no such alternate data attribute or -1 on error */ int libfsntfs_mft_entry_get_alternate_data_attribute_by_utf8_name( libfsntfs_mft_entry_t *mft_entry, const uint8_t *utf8_string, size_t utf8_string_length, libfsntfs_mft_attribute_t **attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_get_alternate_data_attribute_by_utf8_name"; int attribute_index = 0; int number_of_attributes = 0; int result = 0; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( libcdata_array_get_number_of_entries( mft_entry->alternate_data_attributes_array, &number_of_attributes, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of entries from alternate data attributes array.", function ); return( -1 ); } for( attribute_index = 0; attribute_index < number_of_attributes; attribute_index++ ) { if( libcdata_array_get_entry_by_index( mft_entry->alternate_data_attributes_array, attribute_index, (intptr_t **) attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry: %d from alternative data attributes array.", function, attribute_index ); return( -1 ); } result = libfsntfs_mft_attribute_compare_name_with_utf8_string( *attribute, utf8_string, utf8_string_length, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GENERIC, "%s: unable to compare UTF-8 string with alternative data attribute name.", function ); goto on_error; } else if( result == 1 ) { return( 1 ); } } *attribute = NULL; return( 0 ); on_error: *attribute = NULL; return( -1 ); } /* Retrieves a specific alternate data attribute for an UTF-16 encoded name * Returns 1 if successful, 0 if no such alternate data attribute or -1 on error */ int libfsntfs_mft_entry_get_alternate_data_attribute_by_utf16_name( libfsntfs_mft_entry_t *mft_entry, const uint16_t *utf16_string, size_t utf16_string_length, libfsntfs_mft_attribute_t **attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_get_alternate_data_attribute_by_utf16_name"; int attribute_index = 0; int number_of_attributes = 0; int result = 0; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( libcdata_array_get_number_of_entries( mft_entry->alternate_data_attributes_array, &number_of_attributes, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of entries from alternate data attributes array.", function ); return( -1 ); } for( attribute_index = 0; attribute_index < number_of_attributes; attribute_index++ ) { if( libcdata_array_get_entry_by_index( mft_entry->alternate_data_attributes_array, attribute_index, (intptr_t **) attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve entry: %d from alternative data attributes array.", function, attribute_index ); return( -1 ); } result = libfsntfs_mft_attribute_compare_name_with_utf16_string( *attribute, utf16_string, utf16_string_length, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GENERIC, "%s: unable to compare UTF-16 string with alternative data attribute name.", function ); goto on_error; } else if( result == 1 ) { return( 1 ); } } *attribute = NULL; return( 0 ); on_error: *attribute = NULL; return( -1 ); } /* Sets the attribute helper values for an attribute * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_set_attribute_helper_values( libfsntfs_mft_entry_t *mft_entry, int attribute_index, libfsntfs_mft_attribute_t *attribute, libcerror_error_t **error ) { uint8_t utf8_attribute_name[ 8 ]; static char *function = "libfsntfs_mft_entry_set_attribute_helper_values"; size_t utf8_attribute_name_size = 0; uint32_t attribute_type = 0; int result = 0; #if defined( HAVE_DEBUG_OUTPUT ) libfsntfs_standard_information_values_t *standard_information_values = NULL; #endif if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_utf8_name_size( attribute, &utf8_attribute_name_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 attribute name size.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_type( attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } switch( attribute_type ) { case LIBFSNTFS_ATTRIBUTE_TYPE_DATA: if( libfsntfs_mft_entry_set_data_attribute_helper_values( mft_entry, attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set data attribute helper values.", function ); return( -1 ); } break; case LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME: if( mft_entry->file_name_attribute_index == -1 ) { mft_entry->file_name_attribute_index = attribute_index; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ROOT: /* Only interested in attribute names that would match $I30 */ if( ( utf8_attribute_name_size == 0 ) || ( utf8_attribute_name_size > 8 ) ) { break; } if( libfsntfs_mft_attribute_get_utf8_name( attribute, utf8_attribute_name, utf8_attribute_name_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 attribute name.", function ); return( -1 ); } result = libuna_utf8_string_compare_with_utf8_stream( utf8_attribute_name, utf8_attribute_name_size, (uint8_t *) "$I30", 4, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GENERIC, "%s: unable to compare UTF-8 string with $I30.", function ); return( -1 ); } else if( result == LIBUNA_COMPARE_EQUAL ) { mft_entry->has_i30_index = 1; } break; case LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT: /* Assume only one reparse point attribute per MFT entry is allowed */ if( mft_entry->reparse_point_attribute_index != -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT entry - reparse point attribute index value already set.", function ); return( -1 ); } mft_entry->reparse_point_attribute_index = attribute_index; break; case LIBFSNTFS_ATTRIBUTE_TYPE_SECURITY_DESCRIPTOR: /* Assume only one security descriptor attribute per MFT entry is allowed */ if( mft_entry->security_descriptor_attribute_index != -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT entry - security descriptor attribute index value already set.", function ); return( -1 ); } mft_entry->security_descriptor_attribute_index = attribute_index; break; case LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION: #if defined( HAVE_DEBUG_OUTPUT ) if( libfsntfs_standard_information_values_initialize( &standard_information_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create standard information values.", function ); return( -1 ); } if( libfsntfs_standard_information_values_read_from_mft_attribute( standard_information_values, attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read standard information values from MFT attribute.", function ); libfsntfs_standard_information_values_free( &standard_information_values, NULL ); return( -1 ); } if( libfsntfs_standard_information_values_free( &standard_information_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free standard information values.", function ); return( -1 ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ /* Assume only one standard information attribute per MFT entry is allowed */ if( mft_entry->standard_information_attribute_index != -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT entry - standard information attribute index value already set.", function ); return( -1 ); } mft_entry->standard_information_attribute_index = attribute_index; break; case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_INFORMATION: /* Assume only one volume information attribute per MFT entry is allowed */ if( mft_entry->volume_information_attribute_index != -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT entry - volume information attribute index value already set.", function ); return( -1 ); } mft_entry->volume_information_attribute_index = attribute_index; break; case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME: /* Assume only one volume name attribute per MFT entry is allowed */ if( mft_entry->volume_name_attribute_index != -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT entry - volume name attribute index value already set.", function ); return( -1 ); } mft_entry->volume_name_attribute_index = attribute_index; break; default: break; } return( 1 ); } /* Sets the attribute helper values for a $DATA attribute * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_set_data_attribute_helper_values( libfsntfs_mft_entry_t *mft_entry, libfsntfs_mft_attribute_t *data_attribute, libcerror_error_t **error ) { libfsntfs_mft_attribute_t *existing_data_attribute = NULL; uint8_t *utf8_attribute_name = NULL; static char *function = "libfsntfs_mft_entry_set_data_attribute_helper_values"; size_t utf8_attribute_name_size = 0; int attribute_index = 0; int entry_index = 0; int result = 0; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_utf8_name_size( data_attribute, &utf8_attribute_name_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 attribute name size.", function ); goto on_error; } if( utf8_attribute_name_size <= 1 ) { if( libfsntfs_mft_attribute_append_to_chain( &( mft_entry->data_attribute ), data_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to chain attribute.", function ); goto on_error; } } else { if( utf8_attribute_name_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid UTF-8 attribute name size value out of bounds.", function ); goto on_error; } utf8_attribute_name = (uint8_t *) memory_allocate( (size_t) utf8_attribute_name_size ); if( utf8_attribute_name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create UTF-8 attribute name.", function ); goto on_error; } if( libfsntfs_mft_attribute_get_utf8_name( data_attribute, utf8_attribute_name, utf8_attribute_name_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 attribute name.", function ); goto on_error; } result = libfsntfs_mft_entry_get_data_attribute_by_utf8_name( mft_entry, utf8_attribute_name, utf8_attribute_name_size, &attribute_index, &existing_data_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data attribute.", function ); goto on_error; } else if( result == 0 ) { if( libcdata_array_append_entry( mft_entry->alternate_data_attributes_array, &entry_index, (intptr_t *) data_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append alternate data attribute to array.", function ); goto on_error; } existing_data_attribute = data_attribute; } else { if( libfsntfs_mft_attribute_append_to_chain( &existing_data_attribute, data_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to chain alternate data attribute.", function ); goto on_error; } if( libcdata_array_set_entry_by_index( mft_entry->alternate_data_attributes_array, attribute_index, (intptr_t *) existing_data_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to append set data attribute: %d in array.", function, attribute_index ); goto on_error; } } memory_free( utf8_attribute_name ); utf8_attribute_name = NULL; result = libfsntfs_mft_attribute_compare_name_with_utf8_string( data_attribute, (uint8_t *) "WofCompressedData", 17, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GENERIC, "%s: unable to compare UTF-8 string with alternative data attribute name.", function ); goto on_error; } else if( result == 1 ) { mft_entry->wof_compressed_data_attribute = existing_data_attribute; } } return( 1 ); on_error: if( utf8_attribute_name != NULL ) { memory_free( utf8_attribute_name ); } return( -1 ); } /* Retrieves a data attribute with the specified name * Returns 1 if successful, 0 if no attribute was found or -1 on error */ int libfsntfs_mft_entry_get_data_attribute_by_utf8_name( libfsntfs_mft_entry_t *mft_entry, const uint8_t *utf8_string, size_t utf8_string_length, int *attribute_index, libfsntfs_mft_attribute_t **attribute, libcerror_error_t **error ) { libfsntfs_mft_attribute_t *safe_attribute = NULL; static char *function = "libfsntfs_mft_entry_get_data_attribute_by_utf8_name"; int number_of_attributes = 0; int result = 0; int safe_attribute_index = 0; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( utf8_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-8 string.", function ); return( -1 ); } if( utf8_string_length > (size_t) ( SSIZE_MAX - 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-8 string length value exceeds maximum.", function ); return( -1 ); } if( attribute_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute index.", function ); return( -1 ); } if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( libcdata_array_get_number_of_entries( mft_entry->alternate_data_attributes_array, &number_of_attributes, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of alternate data attributes.", function ); return( -1 ); } for( safe_attribute_index = 0; safe_attribute_index < number_of_attributes; safe_attribute_index++ ) { if( libcdata_array_get_entry_by_index( mft_entry->alternate_data_attributes_array, safe_attribute_index, (intptr_t **) &safe_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve alternate data attribute: %d.", function, safe_attribute_index ); return( -1 ); } result = libfsntfs_mft_attribute_compare_name_with_utf8_string( safe_attribute, utf8_string, utf8_string_length, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GENERIC, "%s: unable to compare UTF-8 string with alternative data attribute: %d name.", function, safe_attribute_index ); return( -1 ); } else if( result != 0 ) { break; } } if( result != 0 ) { *attribute_index = safe_attribute_index; *attribute = safe_attribute; } else { *attribute_index = 0; *attribute = NULL; } return( result ); } /* Determines if the file entry has the directory entries ($I30) index * Returns 1 if the default data stream, 0 if not or -1 on error */ int libfsntfs_mft_entry_has_directory_entries_index( libfsntfs_mft_entry_t *mft_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_has_directory_entries_index"; if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } return( (int) mft_entry->has_i30_index ); } /* Reads the MFT entry * Callback function for the MFT entry vector * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_read_element_data( intptr_t *data_handle LIBFSNTFS_ATTRIBUTE_UNUSED, libbfio_handle_t *file_io_handle, libfdata_vector_t *vector, libfdata_cache_t *cache, int element_index, int element_data_file_index LIBFSNTFS_ATTRIBUTE_UNUSED, off64_t element_data_offset, size64_t element_data_size, uint32_t element_flags LIBFSNTFS_ATTRIBUTE_UNUSED, uint8_t read_flags LIBFSNTFS_ATTRIBUTE_UNUSED, libcerror_error_t **error ) { libfsntfs_mft_entry_t *mft_entry = NULL; static char *function = "libfsntfs_mft_entry_read_element_data"; LIBFSNTFS_UNREFERENCED_PARAMETER( data_handle ) LIBFSNTFS_UNREFERENCED_PARAMETER( element_data_file_index ) LIBFSNTFS_UNREFERENCED_PARAMETER( element_flags ) LIBFSNTFS_UNREFERENCED_PARAMETER( read_flags ) #if ( SIZEOF_INT <= 4 ) if( element_index < 0 ) #else if( ( element_index < 0 ) || ( (int64_t) element_index > (int64_t) UINT32_MAX ) ) #endif { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid element index value out of bounds.", function ); return( -1 ); } if( element_data_size > (size64_t) UINT32_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid element data size value out of bounds.", function ); return( -1 ); } if( libfsntfs_mft_entry_initialize( &mft_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create MFT entry.", function ); goto on_error; } if( libfsntfs_mft_entry_read_file_io_handle( mft_entry, file_io_handle, element_data_offset, (uint32_t) element_data_size, (uint32_t) element_index, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read MFT entry: %d.", function, element_index ); goto on_error; } if( libfdata_vector_set_element_value_by_index( vector, (intptr_t *) file_io_handle, cache, element_index, (intptr_t *) mft_entry, (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_entry_free, LIBFDATA_VECTOR_ELEMENT_VALUE_FLAG_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set MFT entry as element value.", function ); goto on_error; } return( 1 ); on_error: if( mft_entry != NULL ) { libfsntfs_mft_entry_free( &mft_entry, NULL ); } return( -1 ); } ================================================ FILE: libfsntfs/libfsntfs_mft_entry.h ================================================ /* * Master File Table (MFT) entry functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_MFT_ENTRY_H ) #define _LIBFSNTFS_MFT_ENTRY_H #include #include #include "libfsntfs_directory_entry.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfcache.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_mft_attribute_list.h" #include "libfsntfs_mft_entry_header.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_mft_entry libfsntfs_mft_entry_t; struct libfsntfs_mft_entry { /* The MFT entry header */ libfsntfs_mft_entry_header_t *header; /* The data */ uint8_t *data; /* The data size */ size_t data_size; /* The index */ uint32_t index; /* The file reference */ uint64_t file_reference; /* The attributes array */ libcdata_array_t *attributes_array; /* The (attribute) list attribute */ libfsntfs_mft_attribute_t *list_attribute; /* The attribute list */ libfsntfs_mft_attribute_list_t *attribute_list; /* The default (nameless) $DATA attribute */ libfsntfs_mft_attribute_t *data_attribute; /* The WofCompressedData $DATA attribute */ libfsntfs_mft_attribute_t *wof_compressed_data_attribute; /* The alternate data attributes array */ libcdata_array_t *alternate_data_attributes_array; /* The index of the (first) file name attribute or -1 if not set */ int file_name_attribute_index; /* The index of the reparse point attribute or -1 if not set */ int reparse_point_attribute_index; /* The index of the security descriptor attribute or -1 if not set */ int security_descriptor_attribute_index; /* The index of the standard information attribute or -1 if not set */ int standard_information_attribute_index; /* The index of the volume information attribute or -1 if not set */ int volume_information_attribute_index; /* The index of the volume name attribute or -1 if not set */ int volume_name_attribute_index; /* Value to indicate the MFT entry is empty */ uint8_t is_empty; /* Value to indicate the MFT entry is corrupted */ uint8_t is_corrupted; /* Value to indicate the MFT entry has an $I30 index */ uint8_t has_i30_index; /* Value to indicate the attributes have been read */ uint8_t attributes_read; }; int libfsntfs_mft_entry_check_for_empty_block( const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_mft_entry_initialize( libfsntfs_mft_entry_t **mft_entry, libcerror_error_t **error ); int libfsntfs_mft_entry_free( libfsntfs_mft_entry_t **mft_entry, libcerror_error_t **error ); int libfsntfs_mft_entry_read_data( libfsntfs_mft_entry_t *mft_entry, uint8_t *data, size_t data_size, uint32_t mft_entry_index, libcerror_error_t **error ); int libfsntfs_mft_entry_read_file_io_handle( libfsntfs_mft_entry_t *mft_entry, libbfio_handle_t *file_io_handle, off64_t file_offset, uint32_t mft_entry_size, uint32_t mft_entry_index, libcerror_error_t **error ); int libfsntfs_mft_entry_read_attributes_data( libfsntfs_mft_entry_t *mft_entry, libfsntfs_io_handle_t *io_handle, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_mft_entry_read_attributes( libfsntfs_mft_entry_t *mft_entry, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfdata_vector_t *mft_entry_vector, libcdata_btree_t *attribute_list_tree, uint8_t flags, libcerror_error_t **error ); int libfsntfs_mft_entry_read_attribute_list( libfsntfs_mft_entry_t *mft_entry, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libcerror_error_t **error ); int libfsntfs_mft_entry_read_attribute_list_data_mft_entry_by_index( libfsntfs_mft_entry_t *mft_entry, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfdata_vector_t *mft_entry_vector, libfcache_cache_t *mft_entry_cache, uint64_t file_reference, libcerror_error_t **error ); int libfsntfs_mft_entry_read_attribute_list_data_mft_entries( libfsntfs_mft_entry_t *mft_entry, libfsntfs_mft_attribute_list_t *attribute_list, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfdata_vector_t *mft_entry_vector, libcerror_error_t **error ); int libfsntfs_mft_entry_is_empty( libfsntfs_mft_entry_t *mft_entry, libcerror_error_t **error ); int libfsntfs_mft_entry_is_allocated( libfsntfs_mft_entry_t *mft_entry, libcerror_error_t **error ); int libfsntfs_mft_entry_is_corrupted( libfsntfs_mft_entry_t *mft_entry, libcerror_error_t **error ); int libfsntfs_mft_entry_get_file_reference( libfsntfs_mft_entry_t *mft_entry, uint64_t *file_reference, libcerror_error_t **error ); int libfsntfs_mft_entry_get_base_record_file_reference( libfsntfs_mft_entry_t *mft_entry, uint64_t *file_reference, libcerror_error_t **error ); int libfsntfs_mft_entry_get_journal_sequence_number( libfsntfs_mft_entry_t *mft_entry, uint64_t *journal_sequence_number, libcerror_error_t **error ); int libfsntfs_mft_entry_get_number_of_attributes( libfsntfs_mft_entry_t *mft_entry, int *number_of_attributes, libcerror_error_t **error ); int libfsntfs_mft_entry_get_attribute_by_index( libfsntfs_mft_entry_t *mft_entry, int attribute_index, libfsntfs_mft_attribute_t **attribute, libcerror_error_t **error ); int libfsntfs_mft_entry_get_standard_information_attribute( libfsntfs_mft_entry_t *mft_entry, libfsntfs_mft_attribute_t **attribute, libcerror_error_t **error ); int libfsntfs_mft_entry_get_volume_information_attribute( libfsntfs_mft_entry_t *mft_entry, libfsntfs_mft_attribute_t **attribute, libcerror_error_t **error ); int libfsntfs_mft_entry_get_volume_name_attribute( libfsntfs_mft_entry_t *mft_entry, libfsntfs_mft_attribute_t **attribute, libcerror_error_t **error ); int libfsntfs_mft_entry_set_attribute_by_index( libfsntfs_mft_entry_t *mft_entry, int attribute_index, libfsntfs_mft_attribute_t *attribute, libcerror_error_t **error ); int libfsntfs_mft_entry_get_number_of_alternate_data_attributes( libfsntfs_mft_entry_t *mft_entry, int *number_of_attributes, libcerror_error_t **error ); int libfsntfs_mft_entry_get_alternate_data_attribute_by_index( libfsntfs_mft_entry_t *mft_entry, int attribute_index, libfsntfs_mft_attribute_t **attribute, libcerror_error_t **error ); int libfsntfs_mft_entry_get_alternate_data_attribute_by_utf8_name( libfsntfs_mft_entry_t *mft_entry, const uint8_t *utf8_string, size_t utf8_string_length, libfsntfs_mft_attribute_t **attribute, libcerror_error_t **error ); int libfsntfs_mft_entry_get_alternate_data_attribute_by_utf16_name( libfsntfs_mft_entry_t *mft_entry, const uint16_t *utf16_string, size_t utf16_string_length, libfsntfs_mft_attribute_t **attribute, libcerror_error_t **error ); int libfsntfs_mft_entry_set_attribute_helper_values( libfsntfs_mft_entry_t *mft_entry, int attribute_index, libfsntfs_mft_attribute_t *attribute, libcerror_error_t **error ); int libfsntfs_mft_entry_set_data_attribute_helper_values( libfsntfs_mft_entry_t *mft_entry, libfsntfs_mft_attribute_t *data_attribute, libcerror_error_t **error ); int libfsntfs_mft_entry_get_data_attribute_by_utf8_name( libfsntfs_mft_entry_t *mft_entry, const uint8_t *utf8_string, size_t utf8_string_length, int *attribute_index, libfsntfs_mft_attribute_t **attribute, libcerror_error_t **error ); int libfsntfs_mft_entry_has_directory_entries_index( libfsntfs_mft_entry_t *mft_entry, libcerror_error_t **error ); int libfsntfs_mft_entry_read_element_data( intptr_t *data_handle, libbfio_handle_t *file_io_handle, libfdata_vector_t *vector, libfdata_cache_t *cache, int element_index, int element_data_file_index, off64_t element_data_offset, size64_t element_data_size, uint32_t element_flags, uint8_t read_flags, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_MFT_ENTRY_H ) */ ================================================ FILE: libfsntfs/libfsntfs_mft_entry_header.c ================================================ /* * Master File Table (MFT) entry header functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_debug.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_mft_entry_header.h" #include "fsntfs_mft_entry.h" /* Creates MFT entry header * Make sure the value mft_entry_header is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_header_initialize( libfsntfs_mft_entry_header_t **mft_entry_header, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_header_initialize"; if( mft_entry_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry header.", function ); return( -1 ); } if( *mft_entry_header != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT entry header value already set.", function ); return( -1 ); } *mft_entry_header = memory_allocate_structure( libfsntfs_mft_entry_header_t ); if( *mft_entry_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create MFT entry header.", function ); goto on_error; } if( memory_set( *mft_entry_header, 0, sizeof( libfsntfs_mft_entry_header_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear MFT entry header.", function ); goto on_error; } return( 1 ); on_error: if( *mft_entry_header != NULL ) { memory_free( *mft_entry_header ); *mft_entry_header = NULL; } return( -1 ); } /* Frees MFT entry header * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_header_free( libfsntfs_mft_entry_header_t **mft_entry_header, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_header_free"; if( mft_entry_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry header.", function ); return( -1 ); } if( *mft_entry_header != NULL ) { memory_free( *mft_entry_header ); *mft_entry_header = NULL; } return( 1 ); } /* Reads the MFT entry header * Returns 1 if successful, 0 if FILE signature is not present or -1 on error */ int libfsntfs_mft_entry_header_read_data( libfsntfs_mft_entry_header_t *mft_entry_header, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_header_read_data"; size_t header_data_size = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint16_t value_16bit = 0; #endif if( mft_entry_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry header.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( ( data_size < 2 ) || ( data_size > (size_t) SSIZE_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mft_entry_header_t *) data )->fixup_values_offset, mft_entry_header->fixup_values_offset ); if( mft_entry_header->fixup_values_offset > 42 ) { header_data_size = sizeof( fsntfs_mft_entry_header_t ); } else { header_data_size = 42; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: MFT entry header data:\n", function ); libcnotify_print_data( data, header_data_size, 0 ); } #endif if( data_size < header_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } if( memory_compare( ( (fsntfs_mft_entry_header_t *) data )->signature, "BAAD", 4 ) == 0 ) { mft_entry_header->is_bad = 1; return( 0 ); } mft_entry_header->is_bad = 0; if( memory_compare( ( (fsntfs_mft_entry_header_t *) data )->signature, "FILE", 4 ) != 0 ) { return( 0 ); } byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mft_entry_header_t *) data )->number_of_fixup_values, mft_entry_header->number_of_fixup_values ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_mft_entry_header_t *) data )->journal_sequence_number, mft_entry_header->journal_sequence_number ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mft_entry_header_t *) data )->sequence, mft_entry_header->sequence ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mft_entry_header_t *) data )->reference_count, mft_entry_header->reference_count ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mft_entry_header_t *) data )->attributes_offset, mft_entry_header->attributes_offset ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mft_entry_header_t *) data )->flags, mft_entry_header->flags ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_mft_entry_header_t *) data )->used_entry_size, mft_entry_header->used_entry_size ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_mft_entry_header_t *) data )->total_entry_size, mft_entry_header->total_entry_size ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_mft_entry_header_t *) data )->base_record_file_reference, mft_entry_header->base_record_file_reference ); if( header_data_size > 42 ) { byte_stream_copy_to_uint32_little_endian( ( (fsntfs_mft_entry_header_t *) data )->index, mft_entry_header->index ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: signature\t\t\t\t\t: %c%c%c%c\n", function, ( (fsntfs_mft_entry_header_t *) data )->signature[ 0 ], ( (fsntfs_mft_entry_header_t *) data )->signature[ 1 ], ( (fsntfs_mft_entry_header_t *) data )->signature[ 2 ], ( (fsntfs_mft_entry_header_t *) data )->signature[ 3 ] ); libcnotify_printf( "%s: fix-up values offset\t\t\t: %" PRIu16 "\n", function, mft_entry_header->fixup_values_offset ); libcnotify_printf( "%s: number of fix-up values\t\t\t: %" PRIu16 "\n", function, mft_entry_header->number_of_fixup_values ); libcnotify_printf( "%s: journal sequence number\t\t\t: %" PRIu64 "\n", function, mft_entry_header->journal_sequence_number ); libcnotify_printf( "%s: sequence\t\t\t\t\t: %" PRIu16 "\n", function, mft_entry_header->sequence ); libcnotify_printf( "%s: reference count\t\t\t\t: %" PRIu16 "\n", function, mft_entry_header->reference_count ); libcnotify_printf( "%s: attributes offset\t\t\t\t: %" PRIu16 "\n", function, mft_entry_header->attributes_offset ); libcnotify_printf( "%s: flags\t\t\t\t\t: 0x%04" PRIx16 "\n", function, mft_entry_header->flags ); libfsntfs_debug_print_mft_entry_flags( mft_entry_header->flags ); libcnotify_printf( "\n" ); libcnotify_printf( "%s: used entry size\t\t\t\t: %" PRIu32 "\n", function, mft_entry_header->used_entry_size ); libcnotify_printf( "%s: total entry size\t\t\t\t: %" PRIu32 "\n", function, mft_entry_header->total_entry_size ); libcnotify_printf( "%s: base record file reference\t\t: %" PRIu64 "-%" PRIu64 "\n", function, mft_entry_header->base_record_file_reference & 0xffffffffffffUL, mft_entry_header->base_record_file_reference >> 48 ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mft_entry_header_t *) data )->first_available_attribute_identifier, value_16bit ); libcnotify_printf( "%s: first available attribute identifier\t: %" PRIu16 "\n", function, value_16bit ); if( header_data_size > 42 ) { byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mft_entry_header_t *) data )->unknown1, value_16bit ); libcnotify_printf( "%s: unknown1\t\t\t\t\t: 0x%04" PRIu16 "\n", function, value_16bit ); libcnotify_printf( "%s: index\t\t\t\t\t: %" PRIu32 "\n", function, mft_entry_header->index ); } libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ if( mft_entry_header->fixup_values_offset < header_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid fix-up values offset value out of bounds.", function ); return( -1 ); } if( mft_entry_header->attributes_offset < header_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid attributes offset value out of bounds.", function ); return( -1 ); } return( 1 ); } /* Retrieves the fix-up values offset * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_header_get_fixup_values_offset( libfsntfs_mft_entry_header_t *mft_entry_header, uint16_t *fixup_values_offset, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_header_get_fixup_values_offset"; if( mft_entry_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry header.", function ); return( -1 ); } if( fixup_values_offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid fix-up values offset.", function ); return( -1 ); } *fixup_values_offset = mft_entry_header->fixup_values_offset; return( 1 ); } /* Retrieves the number of fix-up values * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_header_get_number_of_fixup_values( libfsntfs_mft_entry_header_t *mft_entry_header, uint16_t *number_of_fixup_values, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_header_get_number_of_fixup_values"; if( mft_entry_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry header.", function ); return( -1 ); } if( number_of_fixup_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid number of fix-up values.", function ); return( -1 ); } *number_of_fixup_values = mft_entry_header->number_of_fixup_values; return( 1 ); } /* Retrieves the journal sequence number * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_header_get_journal_sequence_number( libfsntfs_mft_entry_header_t *mft_entry_header, uint64_t *journal_sequence_number, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_header_get_journal_sequence_number"; if( mft_entry_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry header.", function ); return( -1 ); } if( journal_sequence_number == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid journal sequence number.", function ); return( -1 ); } *journal_sequence_number = mft_entry_header->journal_sequence_number; return( 1 ); } /* Retrieves the reference count * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_header_get_reference_count( libfsntfs_mft_entry_header_t *mft_entry_header, uint16_t *reference_count, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_header_get_reference_count"; if( mft_entry_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry header.", function ); return( -1 ); } if( reference_count == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid reference count.", function ); return( -1 ); } *reference_count = mft_entry_header->reference_count; return( 1 ); } /* Retrieves the attributes offset * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_header_get_attributes_offset( libfsntfs_mft_entry_header_t *mft_entry_header, uint16_t *attributes_offset, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_header_get_attributes_offset"; if( mft_entry_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry header.", function ); return( -1 ); } if( attributes_offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attributes offset.", function ); return( -1 ); } *attributes_offset = mft_entry_header->attributes_offset; return( 1 ); } /* Retrieves the used entry size * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_header_get_used_entry_size( libfsntfs_mft_entry_header_t *mft_entry_header, uint32_t *used_entry_size, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_header_get_used_entry_size"; if( mft_entry_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry header.", function ); return( -1 ); } if( used_entry_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid used entry size.", function ); return( -1 ); } *used_entry_size = mft_entry_header->used_entry_size; return( 1 ); } /* Retrieves the total entry size * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_header_get_total_entry_size( libfsntfs_mft_entry_header_t *mft_entry_header, uint32_t *total_entry_size, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_header_get_total_entry_size"; if( mft_entry_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry header.", function ); return( -1 ); } if( total_entry_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid total entry size.", function ); return( -1 ); } *total_entry_size = mft_entry_header->total_entry_size; return( 1 ); } /* Retrieves the base record file reference * Returns 1 if successful or -1 on error */ int libfsntfs_mft_entry_header_get_base_record_file_reference( libfsntfs_mft_entry_header_t *mft_entry_header, uint64_t *base_record_file_reference, libcerror_error_t **error ) { static char *function = "libfsntfs_mft_entry_header_get_base_record_file_reference"; if( mft_entry_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry header.", function ); return( -1 ); } if( base_record_file_reference == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid base record file reference.", function ); return( -1 ); } *base_record_file_reference = mft_entry_header->base_record_file_reference; return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_mft_entry_header.h ================================================ /* * Master File Table (MFT) entry header functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_MFT_ENTRY_HEADER_H ) #define _LIBFSNTFS_MFT_ENTRY_HEADER_H #include #include #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_mft_entry_header libfsntfs_mft_entry_header_t; struct libfsntfs_mft_entry_header { /* The fix-up values offset */ uint16_t fixup_values_offset; /* The number of fix-up values */ uint16_t number_of_fixup_values; /* The journal sequence number */ uint64_t journal_sequence_number; /* The sequence */ uint16_t sequence; /* The reference count */ uint16_t reference_count; /* The attributes offset */ uint16_t attributes_offset; /* The flags */ uint16_t flags; /* The used entry size */ uint32_t used_entry_size; /* The total entry size */ uint32_t total_entry_size; /* The base record file reference */ uint64_t base_record_file_reference; /* The index */ uint32_t index; /* Value to indicate if the MFT entry is bad * The signature is set to "BAAD" */ uint8_t is_bad; }; int libfsntfs_mft_entry_header_initialize( libfsntfs_mft_entry_header_t **mft_entry_header, libcerror_error_t **error ); int libfsntfs_mft_entry_header_free( libfsntfs_mft_entry_header_t **mft_entry_header, libcerror_error_t **error ); int libfsntfs_mft_entry_header_read_data( libfsntfs_mft_entry_header_t *mft_entry_header, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_mft_entry_header_get_fixup_values_offset( libfsntfs_mft_entry_header_t *mft_entry_header, uint16_t *fixup_values_offset, libcerror_error_t **error ); int libfsntfs_mft_entry_header_get_number_of_fixup_values( libfsntfs_mft_entry_header_t *mft_entry_header, uint16_t *number_of_fixup_values, libcerror_error_t **error ); int libfsntfs_mft_entry_header_get_journal_sequence_number( libfsntfs_mft_entry_header_t *mft_entry_header, uint64_t *journal_sequence_number, libcerror_error_t **error ); int libfsntfs_mft_entry_header_get_reference_count( libfsntfs_mft_entry_header_t *mft_entry_header, uint16_t *reference_count, libcerror_error_t **error ); int libfsntfs_mft_entry_header_get_attributes_offset( libfsntfs_mft_entry_header_t *mft_entry_header, uint16_t *attributes_offset, libcerror_error_t **error ); int libfsntfs_mft_entry_header_get_used_entry_size( libfsntfs_mft_entry_header_t *mft_entry_header, uint32_t *used_entry_size, libcerror_error_t **error ); int libfsntfs_mft_entry_header_get_total_entry_size( libfsntfs_mft_entry_header_t *mft_entry_header, uint32_t *total_entry_size, libcerror_error_t **error ); int libfsntfs_mft_entry_header_get_base_record_file_reference( libfsntfs_mft_entry_header_t *mft_entry_header, uint64_t *base_record_file_reference, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_MFT_ENTRY_HEADER_H ) */ ================================================ FILE: libfsntfs/libfsntfs_mft_metadata_file.c ================================================ /* * $MFT metadata file functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include "libfsntfs_attribute.h" #include "libfsntfs_debug.h" #include "libfsntfs_definitions.h" #include "libfsntfs_file_entry.h" #include "libfsntfs_file_name_values.h" #include "libfsntfs_file_system.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libuna.h" #include "libfsntfs_mft_entry.h" #include "libfsntfs_mft_metadata_file.h" #include "libfsntfs_types.h" #include "libfsntfs_volume_information_attribute.h" #include "libfsntfs_volume_name_attribute.h" /* Creates a MFT metadata file * Make sure the value mft_metadata_file is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_mft_metadata_file_initialize( libfsntfs_mft_metadata_file_t **mft_metadata_file, libcerror_error_t **error ) { libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file = NULL; static char *function = "libfsntfs_mft_metadata_file_initialize"; if( mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } if( *mft_metadata_file != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT metadata file value already set.", function ); return( -1 ); } internal_mft_metadata_file = memory_allocate_structure( libfsntfs_internal_mft_metadata_file_t ); if( internal_mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create MFT metadata file.", function ); goto on_error; } if( memory_set( internal_mft_metadata_file, 0, sizeof( libfsntfs_internal_mft_metadata_file_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear MFT metadata file.", function ); memory_free( internal_mft_metadata_file ); return( -1 ); } if( libfsntfs_io_handle_initialize( &( internal_mft_metadata_file->io_handle ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create IO handle.", function ); goto on_error; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_initialize( &( internal_mft_metadata_file->read_write_lock ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize read/write lock.", function ); goto on_error; } #endif *mft_metadata_file = (libfsntfs_mft_metadata_file_t *) internal_mft_metadata_file; return( 1 ); on_error: if( internal_mft_metadata_file != NULL ) { if( internal_mft_metadata_file->io_handle != NULL ) { libfsntfs_io_handle_free( &( internal_mft_metadata_file->io_handle ), NULL ); } memory_free( internal_mft_metadata_file ); } return( -1 ); } /* Frees a MFT metadata file * Returns 1 if successful or -1 on error */ int libfsntfs_mft_metadata_file_free( libfsntfs_mft_metadata_file_t **mft_metadata_file, libcerror_error_t **error ) { libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file = NULL; static char *function = "libfsntfs_mft_metadata_file_free"; int result = 1; if( mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } if( *mft_metadata_file != NULL ) { internal_mft_metadata_file = (libfsntfs_internal_mft_metadata_file_t *) *mft_metadata_file; if( internal_mft_metadata_file->file_io_handle != NULL ) { if( libfsntfs_mft_metadata_file_close( *mft_metadata_file, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close MFT metadata file.", function ); result = -1; } } *mft_metadata_file = NULL; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_free( &( internal_mft_metadata_file->read_write_lock ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free read/write lock.", function ); result = -1; } #endif if( libfsntfs_io_handle_free( &( internal_mft_metadata_file->io_handle ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free IO handle.", function ); result = -1; } memory_free( internal_mft_metadata_file ); } return( result ); } /* Signals the mft_metadata_file to abort its current activity * Returns 1 if successful or -1 on error */ int libfsntfs_mft_metadata_file_signal_abort( libfsntfs_mft_metadata_file_t *mft_metadata_file, libcerror_error_t **error ) { libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file = NULL; static char *function = "libfsntfs_mft_metadata_file_signal_abort"; if( mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } internal_mft_metadata_file = (libfsntfs_internal_mft_metadata_file_t *) mft_metadata_file; if( internal_mft_metadata_file->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid MFT metadata file - missing IO handle.", function ); return( -1 ); } internal_mft_metadata_file->io_handle->abort = 1; return( 1 ); } /* Opens a MFT metadata file * Returns 1 if successful or -1 on error */ int libfsntfs_mft_metadata_file_open( libfsntfs_mft_metadata_file_t *mft_metadata_file, const char *filename, int access_flags, libcerror_error_t **error ) { libbfio_handle_t *file_io_handle = NULL; libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file = NULL; static char *function = "libfsntfs_mft_metadata_file_open"; if( mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } internal_mft_metadata_file = (libfsntfs_internal_mft_metadata_file_t *) mft_metadata_file; if( filename == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid filename.", function ); return( -1 ); } if( ( ( access_flags & LIBFSNTFS_ACCESS_FLAG_READ ) == 0 ) && ( ( access_flags & LIBFSNTFS_ACCESS_FLAG_WRITE ) == 0 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported access flags.", function ); return( -1 ); } if( ( access_flags & LIBFSNTFS_ACCESS_FLAG_WRITE ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: write access currently not supported.", function ); return( -1 ); } if( libbfio_file_initialize( &file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file IO handle.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libbfio_handle_set_track_offsets_read( file_io_handle, 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set track offsets read in file IO handle.", function ); goto on_error; } #endif if( libbfio_file_set_name( file_io_handle, filename, narrow_string_length( filename ) + 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set filename in file IO handle.", function ); goto on_error; } if( libfsntfs_mft_metadata_file_open_file_io_handle( mft_metadata_file, file_io_handle, access_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open MFT metadata file: %s.", function, filename ); goto on_error; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); goto on_error; } #endif internal_mft_metadata_file->file_io_handle_created_in_library = 1; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); internal_mft_metadata_file->file_io_handle_created_in_library = 0; goto on_error; } #endif return( 1 ); on_error: if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } return( -1 ); } #if defined( HAVE_WIDE_CHARACTER_TYPE ) /* Opens a MFT metadata file * Returns 1 if successful or -1 on error */ int libfsntfs_mft_metadata_file_open_wide( libfsntfs_mft_metadata_file_t *mft_metadata_file, const wchar_t *filename, int access_flags, libcerror_error_t **error ) { libbfio_handle_t *file_io_handle = NULL; libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file = NULL; static char *function = "libfsntfs_mft_metadata_file_open_wide"; if( mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } internal_mft_metadata_file = (libfsntfs_internal_mft_metadata_file_t *) mft_metadata_file; if( filename == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid filename.", function ); return( -1 ); } if( ( ( access_flags & LIBFSNTFS_ACCESS_FLAG_READ ) == 0 ) && ( ( access_flags & LIBFSNTFS_ACCESS_FLAG_WRITE ) == 0 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported access flags.", function ); return( -1 ); } if( ( access_flags & LIBFSNTFS_ACCESS_FLAG_WRITE ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: write access currently not supported.", function ); return( -1 ); } if( libbfio_file_initialize( &file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file IO handle.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libbfio_handle_set_track_offsets_read( file_io_handle, 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set track offsets read in file IO handle.", function ); goto on_error; } #endif if( libbfio_file_set_name_wide( file_io_handle, filename, wide_string_length( filename ) + 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set filename in file IO handle.", function ); goto on_error; } if( libfsntfs_mft_metadata_file_open_file_io_handle( mft_metadata_file, file_io_handle, access_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open MFT metadata file: %ls.", function, filename ); goto on_error; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); goto on_error; } #endif internal_mft_metadata_file->file_io_handle_created_in_library = 1; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); internal_mft_metadata_file->file_io_handle_created_in_library = 0; goto on_error; } #endif return( 1 ); on_error: if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } return( -1 ); } #endif /* #if defined( HAVE_WIDE_CHARACTER_TYPE ) */ /* Opens a MFT metadata file using a Basic File IO (bfio) handle * Returns 1 if successful or -1 on error */ int libfsntfs_mft_metadata_file_open_file_io_handle( libfsntfs_mft_metadata_file_t *mft_metadata_file, libbfio_handle_t *file_io_handle, int access_flags, libcerror_error_t **error ) { libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file = NULL; static char *function = "libfsntfs_volume_open_file_io_handle"; int bfio_access_flags = 0; int file_io_handle_is_open = 0; uint8_t file_io_handle_opened_in_library = 0; if( mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } internal_mft_metadata_file = (libfsntfs_internal_mft_metadata_file_t *) mft_metadata_file; if( internal_mft_metadata_file->file_io_handle != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT metadata file - file IO handle already set.", function ); return( -1 ); } if( file_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file IO handle.", function ); return( -1 ); } if( ( ( access_flags & LIBFSNTFS_ACCESS_FLAG_READ ) == 0 ) && ( ( access_flags & LIBFSNTFS_ACCESS_FLAG_WRITE ) == 0 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported access flags.", function ); return( -1 ); } if( ( access_flags & LIBFSNTFS_ACCESS_FLAG_WRITE ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: write access currently not supported.", function ); return( -1 ); } if( ( access_flags & LIBFSNTFS_ACCESS_FLAG_READ ) != 0 ) { bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ; } file_io_handle_is_open = libbfio_handle_is_open( file_io_handle, error ); if( file_io_handle_is_open == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open volume.", function ); goto on_error; } else if( file_io_handle_is_open == 0 ) { if( libbfio_handle_open( file_io_handle, bfio_access_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open file IO handle.", function ); goto on_error; } file_io_handle_opened_in_library = 1; } if( libfsntfs_internal_mft_metadata_file_open_read( internal_mft_metadata_file, file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read from file IO handle.", function ); goto on_error; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); goto on_error; } #endif internal_mft_metadata_file->file_io_handle = file_io_handle; internal_mft_metadata_file->file_io_handle_opened_in_library = file_io_handle_opened_in_library; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); internal_mft_metadata_file->file_io_handle = NULL; internal_mft_metadata_file->file_io_handle_opened_in_library = 0; goto on_error; } #endif return( 1 ); on_error: if( file_io_handle_opened_in_library != 0 ) { libbfio_handle_close( file_io_handle, error ); } return( -1 ); } /* Closes a MFT metadata file * Returns 0 if successful or -1 on error */ int libfsntfs_mft_metadata_file_close( libfsntfs_mft_metadata_file_t *mft_metadata_file, libcerror_error_t **error ) { libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file = NULL; static char *function = "libfsntfs_mft_metadata_file_close"; int result = 0; if( mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } internal_mft_metadata_file = (libfsntfs_internal_mft_metadata_file_t *) mft_metadata_file; if( internal_mft_metadata_file->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid MFT metadata file - missing IO handle.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( internal_mft_metadata_file->file_io_handle_created_in_library != 0 ) { if( libfsntfs_debug_print_read_offsets( internal_mft_metadata_file->file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print the read offsets.", function ); result = -1; } } } #endif if( internal_mft_metadata_file->file_io_handle_opened_in_library != 0 ) { if( libbfio_handle_close( internal_mft_metadata_file->file_io_handle, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close file IO handle.", function ); result = -1; } internal_mft_metadata_file->file_io_handle_opened_in_library = 0; } if( internal_mft_metadata_file->file_io_handle_created_in_library != 0 ) { if( libbfio_handle_free( &( internal_mft_metadata_file->file_io_handle ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file IO handle.", function ); result = -1; } internal_mft_metadata_file->file_io_handle_created_in_library = 0; } internal_mft_metadata_file->file_io_handle = NULL; if( libfsntfs_io_handle_clear( internal_mft_metadata_file->io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to clear IO handle.", function ); result = -1; } if( internal_mft_metadata_file->file_system != NULL ) { if( libfsntfs_file_system_free( &( internal_mft_metadata_file->file_system ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file system.", function ); result = -1; } } if( internal_mft_metadata_file->volume_mft_entry != NULL ) { if( libfsntfs_mft_entry_free( &( internal_mft_metadata_file->volume_mft_entry ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free volume MFT entry.", function ); result = -1; } } if( internal_mft_metadata_file->volume_information_attribute != NULL ) { if( libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &( internal_mft_metadata_file->volume_information_attribute ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free volume information attribute.", function ); result = -1; } } if( internal_mft_metadata_file->volume_name_attribute != NULL ) { if( libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &( internal_mft_metadata_file->volume_name_attribute ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free volume name attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Opens a MFT metadata file for reading * Returns 1 if successful or -1 on error */ int libfsntfs_internal_mft_metadata_file_open_read( libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file, libbfio_handle_t *file_io_handle, libcerror_error_t **error ) { static char *function = "libfsntfs_internal_mft_metadata_file_open_read"; if( internal_mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } if( internal_mft_metadata_file->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid MFT metadata file - missing IO handle.", function ); return( -1 ); } if( internal_mft_metadata_file->file_system != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid MFT metadata file - file system value already set.", function ); return( -1 ); } /* TODO allow to set the values */ /* TODO scan for signature to determine MFT entry size */ internal_mft_metadata_file->io_handle->bytes_per_sector = 512; /* TODO if not set FILE signature try scan? */ internal_mft_metadata_file->io_handle->mft_entry_size = 1024; /* TODO if not set INDX signature try scan? */ internal_mft_metadata_file->io_handle->index_entry_size = 4096; internal_mft_metadata_file->io_handle->cluster_block_size = 4096; if( libfsntfs_file_system_initialize( &( internal_mft_metadata_file->file_system ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file system.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "Reading MFT entry: 0:\n" ); } #endif if( libfsntfs_file_system_read_mft( internal_mft_metadata_file->file_system, internal_mft_metadata_file->io_handle, file_io_handle, 0, LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read MFT (MFT entry: 0).", function ); goto on_error; } if( libfsntfs_mft_read_list_data_mft_entries( internal_mft_metadata_file->file_system->mft, file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read list data MFT entries.", function ); goto on_error; } return( 1 ); on_error: if( internal_mft_metadata_file->file_system != NULL ) { libfsntfs_file_system_free( &( internal_mft_metadata_file->file_system ), NULL ); } return( -1 ); } /* Retrieves the $VOLUME_INFORMATION attribute from MFT entry 3 * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_internal_mft_metadata_file_get_volume_information_attribute( libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file, libfsntfs_attribute_t **attribute, libcerror_error_t **error ) { libfsntfs_mft_attribute_t *mft_attribute = NULL; static char *function = "libfsntfs_internal_mft_metadata_file_get_volume_information_attribute"; int result = 0; if( internal_mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( internal_mft_metadata_file->volume_mft_entry == NULL ) { if( libfsntfs_file_system_get_mft_entry_by_index_no_cache( internal_mft_metadata_file->file_system, internal_mft_metadata_file->file_io_handle, LIBFSNTFS_MFT_ENTRY_INDEX_VOLUME, &( internal_mft_metadata_file->volume_mft_entry ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: %d.", function, LIBFSNTFS_MFT_ENTRY_INDEX_VOLUME ); return( -1 ); } } if( internal_mft_metadata_file->volume_information_attribute == NULL ) { result = libfsntfs_mft_entry_get_volume_information_attribute( internal_mft_metadata_file->volume_mft_entry, &mft_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve $VOLUME_INFORMATION attribute.", function ); return( -1 ); } else if( result == 0 ) { return( 0 ); } if( libfsntfs_attribute_initialize( &( internal_mft_metadata_file->volume_information_attribute ), mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create $VOLUME_INFORMATION attribute.", function ); return( -1 ); } if( libfsntfs_internal_attribute_read_value( (libfsntfs_internal_attribute_t *) internal_mft_metadata_file->volume_information_attribute, internal_mft_metadata_file->io_handle, internal_mft_metadata_file->file_io_handle, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read value of $VOLUME_INFORMATION attribute.", function ); return( -1 ); } } *attribute = internal_mft_metadata_file->volume_information_attribute; return( 1 ); } /* Retrieves the $VOLUME_NAME attribute from MFT entry 3 * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_internal_mft_metadata_file_get_volume_name_attribute( libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file, libfsntfs_attribute_t **attribute, libcerror_error_t **error ) { libfsntfs_mft_attribute_t *mft_attribute = NULL; static char *function = "libfsntfs_internal_mft_metadata_file_get_volume_name_attribute"; int result = 0; if( internal_mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( internal_mft_metadata_file->volume_mft_entry == NULL ) { if( libfsntfs_file_system_get_mft_entry_by_index_no_cache( internal_mft_metadata_file->file_system, internal_mft_metadata_file->file_io_handle, LIBFSNTFS_MFT_ENTRY_INDEX_VOLUME, &( internal_mft_metadata_file->volume_mft_entry ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: %d.", function, LIBFSNTFS_MFT_ENTRY_INDEX_VOLUME ); return( -1 ); } } if( internal_mft_metadata_file->volume_name_attribute == NULL ) { result = libfsntfs_mft_entry_get_volume_name_attribute( internal_mft_metadata_file->volume_mft_entry, &mft_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve $VOLUME_NAME attribute.", function ); return( -1 ); } else if( result == 0 ) { return( 0 ); } if( libfsntfs_attribute_initialize( &( internal_mft_metadata_file->volume_name_attribute ), mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create $VOLUME_NAME attribute.", function ); return( -1 ); } if( libfsntfs_internal_attribute_read_value( (libfsntfs_internal_attribute_t *) internal_mft_metadata_file->volume_name_attribute, internal_mft_metadata_file->io_handle, internal_mft_metadata_file->file_io_handle, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read value of $VOLUME_NAME attribute.", function ); return( -1 ); } } *attribute = internal_mft_metadata_file->volume_name_attribute; return( 1 ); } /* Retrieves the size of the UTF-8 encoded name * The returned size includes the end of string character * This value is retrieved from the $VOLUME_NAME attribute of the $Volume metadata file * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_mft_metadata_file_get_utf8_volume_name_size( libfsntfs_mft_metadata_file_t *mft_metadata_file, size_t *utf8_string_size, libcerror_error_t **error ) { libfsntfs_attribute_t *volume_name_attribute = NULL; libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file = NULL; static char *function = "libfsntfs_mft_metadata_file_get_utf8_volume_name_size"; int result = 0; if( mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } internal_mft_metadata_file = (libfsntfs_internal_mft_metadata_file_t *) mft_metadata_file; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_mft_metadata_file_get_volume_name_attribute( internal_mft_metadata_file, &volume_name_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve volume name attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_volume_name_attribute_get_utf8_name_size( volume_name_attribute, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-8 name from volume name attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the UTF-8 encoded name * The size should include the end of string character * This value is retrieved from the $VOLUME_NAME attribute of the $Volume metadata file * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_mft_metadata_file_get_utf8_volume_name( libfsntfs_mft_metadata_file_t *mft_metadata_file, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { libfsntfs_attribute_t *volume_name_attribute = NULL; libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file = NULL; static char *function = "libfsntfs_mft_metadata_file_get_utf8_volume_name"; int result = 0; if( mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } internal_mft_metadata_file = (libfsntfs_internal_mft_metadata_file_t *) mft_metadata_file; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_mft_metadata_file_get_volume_name_attribute( internal_mft_metadata_file, &volume_name_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve volume name attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_volume_name_attribute_get_utf8_name( volume_name_attribute, utf8_string, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 name from volume name attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the size of the UTF-16 encoded name * The returned size includes the end of string character * This value is retrieved from the $VOLUME_NAME attribute of the $Volume metadata file * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_mft_metadata_file_get_utf16_volume_name_size( libfsntfs_mft_metadata_file_t *mft_metadata_file, size_t *utf16_string_size, libcerror_error_t **error ) { libfsntfs_attribute_t *volume_name_attribute = NULL; libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file = NULL; static char *function = "libfsntfs_mft_metadata_file_get_utf16_volume_name_size"; int result = 0; if( mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } internal_mft_metadata_file = (libfsntfs_internal_mft_metadata_file_t *) mft_metadata_file; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_mft_metadata_file_get_volume_name_attribute( internal_mft_metadata_file, &volume_name_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve volume name attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_volume_name_attribute_get_utf16_name_size( volume_name_attribute, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-16 name from volume name attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the UTF-16 encoded name * The size should include the end of string character * This value is retrieved from the $VOLUME_NAME attribute of the $Volume metadata file * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_mft_metadata_file_get_utf16_volume_name( libfsntfs_mft_metadata_file_t *mft_metadata_file, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { libfsntfs_attribute_t *volume_name_attribute = NULL; libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file = NULL; static char *function = "libfsntfs_mft_metadata_file_get_utf16_volume_name"; int result = 0; if( mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } internal_mft_metadata_file = (libfsntfs_internal_mft_metadata_file_t *) mft_metadata_file; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_mft_metadata_file_get_volume_name_attribute( internal_mft_metadata_file, &volume_name_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve volume name attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_volume_name_attribute_get_utf16_name( volume_name_attribute, utf16_string, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 name from volume name attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the volume version * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_mft_metadata_file_get_volume_version( libfsntfs_mft_metadata_file_t *mft_metadata_file, uint8_t *major_version, uint8_t *minor_version, libcerror_error_t **error ) { libfsntfs_attribute_t *volume_information_attribute = NULL; libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file = NULL; static char *function = "libfsntfs_mft_metadata_file_get_volume_version"; int result = 0; if( mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } internal_mft_metadata_file = (libfsntfs_internal_mft_metadata_file_t *) mft_metadata_file; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_mft_metadata_file_get_volume_information_attribute( internal_mft_metadata_file, &volume_information_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve volume information attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_volume_information_attribute_get_version( volume_information_attribute, major_version, minor_version, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve version from volume information attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the volume flags * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_mft_metadata_file_get_volume_flags( libfsntfs_mft_metadata_file_t *mft_metadata_file, uint16_t *flags, libcerror_error_t **error ) { libfsntfs_attribute_t *volume_information_attribute = NULL; libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file = NULL; static char *function = "libfsntfs_mft_metadata_file_get_volume_flags"; int result = 0; if( mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } internal_mft_metadata_file = (libfsntfs_internal_mft_metadata_file_t *) mft_metadata_file; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_mft_metadata_file_get_volume_information_attribute( internal_mft_metadata_file, &volume_information_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve volume information attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_volume_information_attribute_get_flags( volume_information_attribute, flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve flags from volume information attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the number of file entries (MFT entries) * Returns 1 if successful or -1 on error */ int libfsntfs_mft_metadata_file_get_number_of_file_entries( libfsntfs_mft_metadata_file_t *mft_metadata_file, uint64_t *number_of_file_entries, libcerror_error_t **error ) { libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file = NULL; static char *function = "libfsntfs_mft_metadata_file_get_number_of_file_entries"; int result = 1; if( mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } internal_mft_metadata_file = (libfsntfs_internal_mft_metadata_file_t *) mft_metadata_file; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_file_system_get_number_of_mft_entries( internal_mft_metadata_file->file_system, number_of_file_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of MFT entries.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the file entry of a specific MFT entry index * Returns 1 if successful or -1 on error */ int libfsntfs_mft_metadata_file_get_file_entry_by_index( libfsntfs_mft_metadata_file_t *mft_metadata_file, uint64_t mft_entry_index, libfsntfs_file_entry_t **file_entry, libcerror_error_t **error ) { libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file = NULL; static char *function = "libfsntfs_mft_metadata_file_get_file_entry_by_index"; int result = 1; if( mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } internal_mft_metadata_file = (libfsntfs_internal_mft_metadata_file_t *) mft_metadata_file; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( *file_entry != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file entry value already set.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif if( libfsntfs_file_entry_initialize( file_entry, internal_mft_metadata_file->io_handle, internal_mft_metadata_file->file_io_handle, internal_mft_metadata_file->file_system, mft_entry_index, NULL, LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file entry from MFT entry: %" PRIu64 ".", function, mft_entry_index ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_mft_metadata_file->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } ================================================ FILE: libfsntfs/libfsntfs_mft_metadata_file.h ================================================ /* * $MFT metadata file functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_MFT_METADATA_FILE_H ) #define _LIBFSNTFS_MFT_METADATA_FILE_H #include #include #include "libfsntfs_extern.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_file_system.h" #include "libfsntfs_types.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_internal_mft_metadata_file libfsntfs_internal_mft_metadata_file_t; struct libfsntfs_internal_mft_metadata_file { /* The file IO handle */ libbfio_handle_t *file_io_handle; /* Value to indicate if the file IO handle was created inside the library */ uint8_t file_io_handle_created_in_library; /* Value to indicate if the file IO handle was opened inside the library */ uint8_t file_io_handle_opened_in_library; /* The IO handle */ libfsntfs_io_handle_t *io_handle; /* The file system */ libfsntfs_file_system_t *file_system; /* The volume MFT entry */ libfsntfs_mft_entry_t *volume_mft_entry; /* The volume information ($VOLUME_INFORMATION) attribute */ libfsntfs_attribute_t *volume_information_attribute; /* The volume name ($VOLUME_NAME) attribute */ libfsntfs_attribute_t *volume_name_attribute; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) /* The read/write lock */ libcthreads_read_write_lock_t *read_write_lock; #endif }; LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_initialize( libfsntfs_mft_metadata_file_t **mft_metadata_file, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_free( libfsntfs_mft_metadata_file_t **mft_metadata_file, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_signal_abort( libfsntfs_mft_metadata_file_t *mft_metadata_file, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_open( libfsntfs_mft_metadata_file_t *mft_metadata_file, const char *filename, int access_flags, libcerror_error_t **error ); #if defined( HAVE_WIDE_CHARACTER_TYPE ) LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_open_wide( libfsntfs_mft_metadata_file_t *mft_metadata_file, const wchar_t *filename, int access_flags, libcerror_error_t **error ); #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */ LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_open_file_io_handle( libfsntfs_mft_metadata_file_t *mft_metadata_file, libbfio_handle_t *file_io_handle, int access_flags, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_close( libfsntfs_mft_metadata_file_t *mft_metadata_file, libcerror_error_t **error ); int libfsntfs_internal_mft_metadata_file_open_read( libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file, libbfio_handle_t *file_io_handle, libcerror_error_t **error ); int libfsntfs_internal_mft_metadata_file_get_volume_information_attribute( libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file, libfsntfs_attribute_t **attribute, libcerror_error_t **error ); int libfsntfs_internal_mft_metadata_file_get_volume_name_attribute( libfsntfs_internal_mft_metadata_file_t *internal_mft_metadata_file, libfsntfs_attribute_t **attribute, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_get_utf8_volume_name_size( libfsntfs_mft_metadata_file_t *mft_metadata_file, size_t *utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_get_utf8_volume_name( libfsntfs_mft_metadata_file_t *mft_metadata_file, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_get_utf16_volume_name_size( libfsntfs_mft_metadata_file_t *mft_metadata_file, size_t *utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_get_utf16_volume_name( libfsntfs_mft_metadata_file_t *mft_metadata_file, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_get_volume_version( libfsntfs_mft_metadata_file_t *mft_metadata_file, uint8_t *major_version, uint8_t *minor_version, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_get_volume_flags( libfsntfs_mft_metadata_file_t *mft_metadata_file, uint16_t *flags, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_get_number_of_file_entries( libfsntfs_mft_metadata_file_t *mft_metadata_file, uint64_t *number_of_file_entries, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_get_file_entry_by_index( libfsntfs_mft_metadata_file_t *mft_metadata_file, uint64_t mft_entry_index, libfsntfs_file_entry_t **file_entry, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_MFT_METADATA_FILE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_name.c ================================================ /* * Name functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_WCTYPE_H ) #include #endif #include "libfsntfs_libcerror.h" #include "libfsntfs_libuna.h" #include "libfsntfs_name.h" /* Compares an (other) UTF-16 encoded name with an UTF-16 encoded name * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error */ int libfsntfs_name_compare( const uint8_t *name, size_t name_size, const uint8_t *other_name, size_t other_name_size, uint8_t use_case_folding, libcerror_error_t **error ) { static char *function = "libfsntfs_name_compare"; libuna_unicode_character_t name_character = 0; libuna_unicode_character_t other_name_character = 0; size_t name_index = 0; size_t other_name_index = 0; if( name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-16 encoded name.", function ); return( -1 ); } if( name_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-16 encoded name size value exceeds maximum.", function ); return( -1 ); } if( name_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS, "%s: missing UTF-16 encoded name value.", function ); return( -1 ); } if( other_name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-16 encoded other name.", function ); return( -1 ); } if( other_name_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-16 encoded other name size value exceeds maximum.", function ); return( -1 ); } if( other_name_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS, "%s: missing UTF-16 encoded other name value.", function ); return( -1 ); } /* Check if the UTF-16 streams are terminated with zero bytes */ if( ( name_size >= 2 ) && ( name[ name_size - 2 ] == 0 ) && ( name[ name_size - 1 ] == 0 ) ) { name_size -= 2; } if( ( other_name_size >= 2 ) && ( other_name[ other_name_size - 2 ] == 0 ) && ( other_name[ other_name_size - 1 ] == 0 ) ) { other_name_size -= 2; } while( ( name_index < name_size ) && ( other_name_index < other_name_size ) ) { if( libuna_unicode_character_copy_from_utf16_stream( &name_character, name, name_size, &name_index, LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy UTF-16 encoded name to Unicode character.", function ); return( -1 ); } if( libuna_unicode_character_copy_from_utf16_stream( &other_name_character, other_name, other_name_size, &other_name_index, LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy UTF-16 encoded other name to Unicode character.", function ); return( -1 ); } if( use_case_folding != 0 ) { name_character = (libuna_unicode_character_t) towupper( (wint_t) name_character ); other_name_character = (libuna_unicode_character_t) towupper( (wint_t) other_name_character ); } if( other_name_character < name_character ) { return( LIBUNA_COMPARE_LESS ); } else if( other_name_character > name_character ) { return( LIBUNA_COMPARE_GREATER ); } } if( other_name_index < other_name_size ) { return( LIBUNA_COMPARE_GREATER ); } else if( name_index < name_size ) { return( LIBUNA_COMPARE_LESS ); } return( LIBUNA_COMPARE_EQUAL ); } /* Compares an UTF-16 encoded short name with an UTF-16 encoded (long) name * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error */ int libfsntfs_name_compare_short( const uint8_t *name, size_t name_size, const uint8_t *short_name, size_t short_name_size, libcerror_error_t **error ) { static char *function = "libfsntfs_name_compare_short"; libuna_unicode_character_t name_character = 0; libuna_unicode_character_t short_name_character = 0; size_t last_match_name_index = 0; size_t last_match_short_name_index = 0; size_t name_index = 0; size_t short_name_index = 0; if( name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-16 encoded name.", function ); return( -1 ); } if( name_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-16 encoded name size value exceeds maximum.", function ); return( -1 ); } if( name_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS, "%s: missing UTF-16 encoded name value.", function ); return( -1 ); } if( short_name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-16 encoded short name.", function ); return( -1 ); } if( short_name_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-16 encoded short name size value exceeds maximum.", function ); return( -1 ); } if( short_name_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS, "%s: missing UTF-16 encoded short name value.", function ); return( -1 ); } /* Check if the UTF-16 streams are terminated with zero bytes */ if( ( name_size >= 2 ) && ( name[ name_size - 2 ] == 0 ) && ( name[ name_size - 1 ] == 0 ) ) { name_size -= 2; } if( ( short_name_size >= 2 ) && ( short_name[ short_name_size - 2 ] == 0 ) && ( short_name[ short_name_size - 1 ] == 0 ) ) { short_name_size -= 2; } while( ( name_index < name_size ) && ( short_name_index < short_name_size ) ) { if( libuna_unicode_character_copy_from_utf16_stream( &name_character, name, name_size, &name_index, LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy UTF-16 encoded name to Unicode character.", function ); return( -1 ); } /* Ignore: * control characters and space * '"' '*' '+' ',' '.' '/' ':' ';' '<' '=' '>' '?' '\' * non 7-bit ASCII characters */ if( ( name_character <= 0x20 ) || ( name_character == 0x22 ) || ( ( name_character >= 0x2a ) && ( name_character <= 0x2c ) ) || ( name_character == 0x2e ) || ( name_character == 0x2f ) || ( ( name_character >= 0x3a ) && ( name_character <= 0x3f ) ) || ( name_character == 0x5c ) || ( name_character >= 0x80 ) ) { continue; } /* The [ and ] characters are replaced by an underscore (_) */ if( ( name_character == 0x5b ) || ( name_character == 0x5d ) ) { name_character = 0x5f; } if( libuna_unicode_character_copy_from_utf16_stream( &short_name_character, short_name, short_name_size, &short_name_index, LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy UTF-16 encoded short name to Unicode character.", function ); return( -1 ); } if( short_name_character == 0x7e ) { break; } name_character = (libuna_unicode_character_t) towupper( (wint_t) name_character ); short_name_character = (libuna_unicode_character_t) towupper( (wint_t) short_name_character ); if( last_match_short_name_index < 4 ) { if( short_name_character < name_character ) { return( LIBUNA_COMPARE_LESS ); } else if( short_name_character > name_character ) { return( LIBUNA_COMPARE_GREATER ); } } else if( short_name_character != name_character ) { /* TODO handle hex notation */ break; } last_match_name_index = name_index; last_match_short_name_index = short_name_index; } while( ( short_name_index < short_name_size ) && ( short_name_character != 0x7e ) ) { if( libuna_unicode_character_copy_from_utf16_stream( &short_name_character, short_name, short_name_size, &short_name_index, LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy UTF-16 encoded short name to Unicode character.", function ); return( -1 ); } } if( short_name_character != 0x7e ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: invalid short name - missing tilde character\n", function ); return( -1 ); } while( short_name_index < short_name_size ) { if( libuna_unicode_character_copy_from_utf16_stream( &short_name_character, short_name, short_name_size, &short_name_index, LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy UTF-16 encoded short name to Unicode character.", function ); return( -1 ); } if( short_name_character == 0x2e ) { break; } /* The ~ suffix should only consist of the numeric characters 0 - 9 */ if( ( short_name_character < 0x30 ) || ( short_name_character > 0x39 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: invalid short name - non-numeric character in tilde suffix.", function ); return( -1 ); } } if( short_name_character == 0x2e ) { name_index = name_size; while( name_index >= 2 ) { name_index -= 2; if( libuna_unicode_character_copy_from_utf16_stream( &name_character, name, name_size, &name_index, LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy UTF-16 encoded name to Unicode character.", function ); return( -1 ); } if( name_character == 0x2e ) { break; } name_index -= 2; } } if( name_character == 0x2e ) { while( ( name_index < name_size ) && ( short_name_index < short_name_size ) ) { if( libuna_unicode_character_copy_from_utf16_stream( &name_character, name, name_size, &name_index, LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy UTF-16 encoded name to Unicode character.", function ); return( -1 ); } /* Ignore: * control characters and space * '"' '*' '+' ',' '/' ':' ';' '<' '=' '>' '?' '\' * non 7-bit ASCII characters */ if( ( name_character <= 0x20 ) || ( name_character == 0x22 ) || ( ( name_character >= 0x2a ) && ( name_character <= 0x2c ) ) || ( name_character == 0x2f ) || ( ( name_character >= 0x3a ) && ( name_character <= 0x3f ) ) || ( name_character == 0x5c ) || ( name_character >= 0x80 ) ) { continue; } if( libuna_unicode_character_copy_from_utf16_stream( &short_name_character, short_name, short_name_size, &short_name_index, LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy UTF-16 encoded short name to Unicode character.", function ); return( -1 ); } name_character = (libuna_unicode_character_t) towupper( (wint_t) name_character ); short_name_character = (libuna_unicode_character_t) towupper( (wint_t) short_name_character ); if( short_name_character != name_character ) { break; } } } if( short_name_index < short_name_size ) { name_index = last_match_name_index; short_name_index = last_match_short_name_index; /* The name was shorter than the short name */ if( name_index >= name_size ) { return( LIBUNA_COMPARE_GREATER ); } /* Compare the remainder of the name and short name as a case-insenstive string */ while( ( name_index < name_size ) && ( short_name_index < short_name_size ) ) { if( libuna_unicode_character_copy_from_utf16_stream( &name_character, name, name_size, &name_index, LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy UTF-16 encoded name to Unicode character.", function ); return( -1 ); } if( libuna_unicode_character_copy_from_utf16_stream( &short_name_character, short_name, short_name_size, &short_name_index, LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy UTF-16 encoded short name to Unicode character.", function ); return( -1 ); } name_character = (libuna_unicode_character_t) towupper( (wint_t) name_character ); short_name_character = (libuna_unicode_character_t) towupper( (wint_t) short_name_character ); if( short_name_character < name_character ) { return( LIBUNA_COMPARE_LESS ); } else if( short_name_character > name_character ) { return( LIBUNA_COMPARE_GREATER ); } } } return( LIBUNA_COMPARE_EQUAL ); } /* Compares an UTF-8 string with an UTF-16 encoded name * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error */ int libfsntfs_name_compare_with_utf8_string( const uint8_t *name, size_t name_size, const libuna_utf8_character_t *utf8_string, size_t utf8_string_length, uint8_t use_case_folding, libcerror_error_t **error ) { static char *function = "libfsntfs_name_compare_with_utf8_string"; libuna_unicode_character_t name_character = 0; libuna_unicode_character_t string_character = 0; size_t name_index = 0; size_t utf8_string_index = 0; if( name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-16 encoded name.", function ); return( -1 ); } if( name_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-16 encoded name size value exceeds maximum.", function ); return( -1 ); } if( name_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS, "%s: missing UTF-16 encoded name value.", function ); return( -1 ); } if( utf8_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-8 string.", function ); return( -1 ); } if( utf8_string_length > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-8 string length value exceeds maximum.", function ); return( -1 ); } /* Check if the UTF-16 stream is terminated with zero bytes */ if( ( name_size >= 2 ) && ( name[ name_size - 2 ] == 0 ) && ( name[ name_size - 1 ] == 0 ) ) { name_size -= 2; } if( ( utf8_string_length >= 1 ) && ( utf8_string[ utf8_string_length - 1 ] == 0 ) ) { utf8_string_length -= 1; } while( ( name_index < name_size ) && ( utf8_string_index < utf8_string_length ) ) { if( libuna_unicode_character_copy_from_utf16_stream( &name_character, name, name_size, &name_index, LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy UTF-16 encoded name to Unicode character.", function ); return( -1 ); } /* Using RFC 2279 UTF-8 to support unpaired UTF-16 surrogates */ if( libuna_unicode_character_copy_from_utf8_rfc2279( &string_character, utf8_string, utf8_string_length, &utf8_string_index, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy UTF-8 RFC 2279 string to Unicode character.", function ); return( -1 ); } if( use_case_folding != 0 ) { name_character = (libuna_unicode_character_t) towupper( (wint_t) name_character ); string_character = (libuna_unicode_character_t) towupper( (wint_t) string_character ); } if( string_character < name_character ) { return( LIBUNA_COMPARE_LESS ); } else if( string_character > name_character ) { return( LIBUNA_COMPARE_GREATER ); } } if( utf8_string_index < utf8_string_length ) { return( LIBUNA_COMPARE_GREATER ); } else if( name_index < name_size ) { return( LIBUNA_COMPARE_LESS ); } return( LIBUNA_COMPARE_EQUAL ); } /* Compares an UTF-16 string with an UTF-16 encoded name * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error */ int libfsntfs_name_compare_with_utf16_string( const uint8_t *name, size_t name_size, const libuna_utf16_character_t *utf16_string, size_t utf16_string_length, uint8_t use_case_folding, libcerror_error_t **error ) { static char *function = "libfsntfs_name_compare_with_utf16_string"; libuna_unicode_character_t name_character = 0; libuna_unicode_character_t string_character = 0; size_t name_index = 0; size_t utf16_string_index = 0; if( name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-16 encoded name.", function ); return( -1 ); } if( name_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-16 encoded name size value exceeds maximum.", function ); return( -1 ); } if( name_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS, "%s: missing UTF-16 encoded name value.", function ); return( -1 ); } if( utf16_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-16 string.", function ); return( -1 ); } if( utf16_string_length > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-16 string length value exceeds maximum.", function ); return( -1 ); } /* Check if the UTF-16 stream is terminated with zero bytes */ if( ( name_size >= 2 ) && ( name[ name_size - 2 ] == 0 ) && ( name[ name_size - 1 ] == 0 ) ) { name_size -= 2; } if( ( utf16_string_length >= 1 ) && ( utf16_string[ utf16_string_length - 1 ] == 0 ) ) { utf16_string_length -= 1; } while( ( name_index < name_size ) && ( utf16_string_index < utf16_string_length ) ) { if( libuna_unicode_character_copy_from_utf16_stream( &name_character, name, name_size, &name_index, LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy UTF-16 encoded name to Unicode character.", function ); return( -1 ); } /* Using UCS-2 to support unpaired UTF-16 surrogates */ if( libuna_unicode_character_copy_from_ucs2( &string_character, utf16_string, utf16_string_length, &utf16_string_index, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy UCS-2 string to Unicode character.", function ); return( -1 ); } if( use_case_folding != 0 ) { name_character = (libuna_unicode_character_t) towupper( (wint_t) name_character ); string_character = (libuna_unicode_character_t) towupper( (wint_t) string_character ); } if( string_character < name_character ) { return( LIBUNA_COMPARE_LESS ); } else if( string_character > name_character ) { return( LIBUNA_COMPARE_GREATER ); } } if( utf16_string_index < utf16_string_length ) { return( LIBUNA_COMPARE_GREATER ); } else if( name_index < name_size ) { return( LIBUNA_COMPARE_LESS ); } return( LIBUNA_COMPARE_EQUAL ); } ================================================ FILE: libfsntfs/libfsntfs_name.h ================================================ /* * Name functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_NAME_H ) #define _LIBFSNTFS_NAME_H #include #include #include "libfsntfs_libcerror.h" #include "libfsntfs_libuna.h" #if defined( __cplusplus ) extern "C" { #endif int libfsntfs_name_compare( const uint8_t *name, size_t name_size, const uint8_t *other_name, size_t other_name_size, uint8_t use_case_folding, libcerror_error_t **error ); int libfsntfs_name_compare_short( const uint8_t *name, size_t name_size, const uint8_t *short_name, size_t short_name_size, libcerror_error_t **error ); int libfsntfs_name_compare_with_utf8_string( const uint8_t *name, size_t name_size, const libuna_utf8_character_t *utf8_string, size_t utf8_string_length, uint8_t use_case_folding, libcerror_error_t **error ); int libfsntfs_name_compare_with_utf16_string( const uint8_t *name, size_t name_size, const libuna_utf16_character_t *utf16_string, size_t utf16_string_length, uint8_t use_case_folding, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_NAME_H ) */ ================================================ FILE: libfsntfs/libfsntfs_notify.c ================================================ /* * Notification functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_notify.h" #if !defined( HAVE_LOCAL_LIBFSNTFS ) /* Sets the verbose notification */ void libfsntfs_notify_set_verbose( int verbose ) { libcnotify_verbose_set( verbose ); } /* Sets the notification stream * Returns 1 if successful or -1 on error */ int libfsntfs_notify_set_stream( FILE *stream, libcerror_error_t **error ) { static char *function = "libfsntfs_notify_set_stream"; if( libcnotify_stream_set( stream, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set stream.", function ); return( -1 ); } return( 1 ); } /* Opens the notification stream using a filename * The stream is opened in append mode * Returns 1 if successful or -1 on error */ int libfsntfs_notify_stream_open( const char *filename, libcerror_error_t **error ) { static char *function = "libfsntfs_notify_stream_open"; if( libcnotify_stream_open( filename, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open stream.", function ); return( -1 ); } return( 1 ); } /* Closes the notification stream if opened using a filename * Returns 0 if successful or -1 on error */ int libfsntfs_notify_stream_close( libcerror_error_t **error ) { static char *function = "libfsntfs_notify_stream_close"; if( libcnotify_stream_close( error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open stream.", function ); return( -1 ); } return( 0 ); } #endif /* !defined( HAVE_LOCAL_LIBFSNTFS ) */ ================================================ FILE: libfsntfs/libfsntfs_notify.h ================================================ /* * Notification functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_NOTIFY_H ) #define _LIBFSNTFS_NOTIFY_H #include #include #include #include "libfsntfs_extern.h" #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif #if !defined( HAVE_LOCAL_LIBFSNTFS ) LIBFSNTFS_EXTERN \ void libfsntfs_notify_set_verbose( int verbose ); LIBFSNTFS_EXTERN \ int libfsntfs_notify_set_stream( FILE *stream, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_notify_stream_open( const char *filename, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_notify_stream_close( libcerror_error_t **error ); #endif /* !defined( HAVE_LOCAL_LIBFSNTFS ) */ #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_NOTIFY_H ) */ ================================================ FILE: libfsntfs/libfsntfs_object_identifier_attribute.c ================================================ /* * Object identifier attribute ($OBJECT_ID) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_attribute.h" #include "libfsntfs_definitions.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_object_identifier_attribute.h" #include "libfsntfs_object_identifier_values.h" #include "libfsntfs_types.h" /* Retrieves the droid file identifier * Returns 1 if successful or -1 on error */ int libfsntfs_object_identifier_attribute_get_droid_file_identifier( libfsntfs_attribute_t *attribute, uint8_t *guid, size_t size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; libfsntfs_object_identifier_values_t *object_identifier_values = NULL; static char *function = "libfsntfs_object_identifier_attribute_get_droid_file_identifier"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( internal_attribute->value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid attribute - missing value.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_OBJECT_IDENTIFIER ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } object_identifier_values = (libfsntfs_object_identifier_values_t *) internal_attribute->value; if( guid == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid GUID.", function ); return( -1 ); } if( size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid size value exceeds maximum.", function ); return( -1 ); } if( size < 16 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: size is too small.", function ); return( -1 ); } if( memory_copy( guid, object_identifier_values->droid_file_identifier, 16 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy droid file identifier.", function ); return( -1 ); } return( 1 ); } /* Retrieves the birth droid volume identifier * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_object_identifier_attribute_get_birth_droid_volume_identifier( libfsntfs_attribute_t *attribute, uint8_t *guid, size_t size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; libfsntfs_object_identifier_values_t *object_identifier_values = NULL; static char *function = "libfsntfs_object_identifier_attribute_get_birth_droid_volume_identifier"; uint64_t attribute_data_size = 0; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( internal_attribute->value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid attribute - missing value.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_OBJECT_IDENTIFIER ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } object_identifier_values = (libfsntfs_object_identifier_values_t *) internal_attribute->value; if( guid == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid GUID.", function ); return( -1 ); } if( size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid size value exceeds maximum.", function ); return( -1 ); } if( size < 16 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: size is too small.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_data_size( internal_attribute, &attribute_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data from attribute.", function ); return( -1 ); } if( attribute_data_size < 64 ) { return( 0 ); } if( memory_copy( guid, object_identifier_values->birth_droid_volume_identifier, 16 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy birth droid volume identifier.", function ); return( -1 ); } return( 1 ); } /* Retrieves the birth droid file identifier * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_object_identifier_attribute_get_birth_droid_file_identifier( libfsntfs_attribute_t *attribute, uint8_t *guid, size_t size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; libfsntfs_object_identifier_values_t *object_identifier_values = NULL; static char *function = "libfsntfs_object_identifier_attribute_get_birth_droid_file_identifier"; uint64_t attribute_data_size = 0; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( internal_attribute->value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid attribute - missing value.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_OBJECT_IDENTIFIER ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } object_identifier_values = (libfsntfs_object_identifier_values_t *) internal_attribute->value; if( guid == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid GUID.", function ); return( -1 ); } if( size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid size value exceeds maximum.", function ); return( -1 ); } if( size < 16 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: size is too small.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_data_size( internal_attribute, &attribute_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data from attribute.", function ); return( -1 ); } if( attribute_data_size < 64 ) { return( 0 ); } if( memory_copy( guid, object_identifier_values->birth_droid_file_identifier, 16 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy birth droid file identifier.", function ); return( -1 ); } return( 1 ); } /* Retrieves the birth droid domain identifier * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_object_identifier_attribute_get_birth_droid_domain_identifier( libfsntfs_attribute_t *attribute, uint8_t *guid, size_t size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; libfsntfs_object_identifier_values_t *object_identifier_values = NULL; static char *function = "libfsntfs_object_identifier_attribute_get_birth_droid_domain_identifier"; uint64_t attribute_data_size = 0; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( internal_attribute->value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid attribute - missing value.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_OBJECT_IDENTIFIER ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } object_identifier_values = (libfsntfs_object_identifier_values_t *) internal_attribute->value; if( guid == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid GUID.", function ); return( -1 ); } if( size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid size value exceeds maximum.", function ); return( -1 ); } if( size < 16 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: size is too small.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_data_size( internal_attribute, &attribute_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data from attribute.", function ); return( -1 ); } if( attribute_data_size < 64 ) { return( 0 ); } if( memory_copy( guid, object_identifier_values->birth_droid_domain_identifier, 16 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy birth droid domain identifier.", function ); return( -1 ); } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_object_identifier_attribute.h ================================================ /* * Object identifier attribute ($OBJECT_IDENTIFIER) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_OBJECT_IDENTIFIER_ATTRIBUTE_H ) #define _LIBFSNTFS_OBJECT_IDENTIFIER_ATTRIBUTE_H #include #include #include "libfsntfs_extern.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_types.h" #if defined( __cplusplus ) extern "C" { #endif LIBFSNTFS_EXTERN \ int libfsntfs_object_identifier_attribute_get_droid_file_identifier( libfsntfs_attribute_t *attribute, uint8_t *guid, size_t size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_object_identifier_attribute_get_birth_droid_volume_identifier( libfsntfs_attribute_t *attribute, uint8_t *guid, size_t size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_object_identifier_attribute_get_birth_droid_file_identifier( libfsntfs_attribute_t *attribute, uint8_t *guid, size_t size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_object_identifier_attribute_get_birth_droid_domain_identifier( libfsntfs_attribute_t *attribute, uint8_t *guid, size_t size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_OBJECT_IDENTIFIER_ATTRIBUTE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_object_identifier_values.c ================================================ /* * Object identifier attribute ($OBJECT_ID) values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include "libfsntfs_debug.h" #include "libfsntfs_definitions.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libfguid.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_object_identifier_values.h" #include "fsntfs_object_identifier.h" /* Creates object identifier values * Make sure the value object_identifier_values is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_object_identifier_values_initialize( libfsntfs_object_identifier_values_t **object_identifier_values, libcerror_error_t **error ) { static char *function = "libfsntfs_object_identifier_values_initialize"; if( object_identifier_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid object identifier values.", function ); return( -1 ); } if( *object_identifier_values != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid object identifier values values value already set.", function ); return( -1 ); } *object_identifier_values = memory_allocate_structure( libfsntfs_object_identifier_values_t ); if( *object_identifier_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create object identifier values.", function ); goto on_error; } if( memory_set( *object_identifier_values, 0, sizeof( libfsntfs_object_identifier_values_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear object identifier values.", function ); goto on_error; } return( 1 ); on_error: if( *object_identifier_values != NULL ) { memory_free( *object_identifier_values ); *object_identifier_values = NULL; } return( -1 ); } /* Frees object identifier values * Returns 1 if successful or -1 on error */ int libfsntfs_object_identifier_values_free( libfsntfs_object_identifier_values_t **object_identifier_values, libcerror_error_t **error ) { static char *function = "libfsntfs_object_identifier_values_free"; if( object_identifier_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid object identifier values.", function ); return( -1 ); } if( *object_identifier_values != NULL ) { memory_free( *object_identifier_values ); *object_identifier_values = NULL; } return( 1 ); } /* Reads the object identifier values * Returns 1 if successful or -1 on error */ int libfsntfs_object_identifier_values_read_data( libfsntfs_object_identifier_values_t *object_identifier_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_object_identifier_read_data"; if( object_identifier_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid object identifier values.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: object identifier data:\n", function ); libcnotify_print_data( data, data_size, 0 ); } #endif if( ( data_size != 16 ) && ( data_size != 64 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported object identifier data size: %" PRIzd "\n", function, data_size ); return( -1 ); } if( memory_copy( object_identifier_values->droid_file_identifier, ( (fsntfs_object_identifier_t *) data )->droid_file_identifier, 16 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy droid file identifier.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( libfsntfs_debug_print_guid_value( function, "droid file identifier\t\t\t", object_identifier_values->droid_file_identifier, 16, LIBFGUID_ENDIAN_LITTLE, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print GUID value.", function ); return( -1 ); } } #endif if( data_size > 16 ) { if( memory_copy( object_identifier_values->birth_droid_volume_identifier, ( (fsntfs_object_identifier_t *) data )->birth_droid_volume_identifier, 16 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy birth droid volume identifier.", function ); return( -1 ); } if( memory_copy( object_identifier_values->birth_droid_file_identifier, ( (fsntfs_object_identifier_t *) data )->birth_droid_file_identifier, 16 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy birth droid file identifier.", function ); return( -1 ); } if( memory_copy( object_identifier_values->birth_droid_domain_identifier, ( (fsntfs_object_identifier_t *) data )->birth_droid_domain_identifier, 16 ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy birth droid domain identifier.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( libfsntfs_debug_print_guid_value( function, "birth droid volume identifier\t\t", object_identifier_values->birth_droid_volume_identifier, 16, LIBFGUID_ENDIAN_LITTLE, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print GUID value.", function ); return( -1 ); } if( libfsntfs_debug_print_guid_value( function, "birth droid file identifier\t\t", object_identifier_values->birth_droid_file_identifier, 16, LIBFGUID_ENDIAN_LITTLE, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print GUID value.", function ); return( -1 ); } if( libfsntfs_debug_print_guid_value( function, "birth droid domain identifier\t\t", object_identifier_values->birth_droid_domain_identifier, 16, LIBFGUID_ENDIAN_LITTLE, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print GUID value.", function ); return( -1 ); } } #endif } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "\n" ); } #endif return( 1 ); } /* Reads the object identifier values from an MFT attribute * Returns 1 if successful or -1 on error */ int libfsntfs_object_identifier_values_read_from_mft_attribute( libfsntfs_object_identifier_values_t *object_identifier_values, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ) { uint8_t *data = NULL; static char *function = "libfsntfs_object_identifier_values_read_from_mft_attribute"; size_t data_size = 0; uint32_t attribute_type = 0; int result = 0; if( object_identifier_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid object identifier values.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_type( mft_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve type from attribute.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_OBJECT_IDENTIFIER ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_mft_attribute_data_is_resident( mft_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if attribute data is resident.", function ); return( -1 ); } else if( result == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported non-resident attribute.", function ); return( 1 ); } if( libfsntfs_mft_attribute_get_resident_data( mft_attribute, &data, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve resident data from attribute.", function ); return( -1 ); } if( libfsntfs_object_identifier_values_read_data( object_identifier_values, data, data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read object identifier values.", function ); return( -1 ); } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_object_identifier_values.h ================================================ /* * Object identifier attribute ($OBJECT_ID) values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_OBJECT_IDENTIFIER_VALUES_H ) #define _LIBFSNTFS_OBJECT_IDENTIFIER_VALUES_H #include #include #include "libfsntfs_libcerror.h" #include "libfsntfs_mft_attribute.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_object_identifier_values libfsntfs_object_identifier_values_t; struct libfsntfs_object_identifier_values { /* Droid file identifier */ uint8_t droid_file_identifier[ 16 ]; /* Birth droid volume identifier */ uint8_t birth_droid_volume_identifier[ 16 ]; /* Birth droid file identifier */ uint8_t birth_droid_file_identifier[ 16 ]; /* Birth droid domain identifier */ uint8_t birth_droid_domain_identifier[ 16 ]; }; int libfsntfs_object_identifier_values_initialize( libfsntfs_object_identifier_values_t **object_identifier_values, libcerror_error_t **error ); int libfsntfs_object_identifier_values_free( libfsntfs_object_identifier_values_t **object_identifier_values, libcerror_error_t **error ); int libfsntfs_object_identifier_values_read_data( libfsntfs_object_identifier_values_t *object_identifier_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_object_identifier_values_read_from_mft_attribute( libfsntfs_object_identifier_values_t *object_identifier_values, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_OBJECT_IDENTIFIER_VALUES_H ) */ ================================================ FILE: libfsntfs/libfsntfs_path_hint.c ================================================ /* * Path hint functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libuna.h" #include "libfsntfs_path_hint.h" /* Creates a path hint * Make sure the value path_hint is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_path_hint_initialize( libfsntfs_path_hint_t **path_hint, libcerror_error_t **error ) { static char *function = "libfsntfs_path_hint_initialize"; if( path_hint == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path hint.", function ); return( -1 ); } if( *path_hint != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid path hint value already set.", function ); return( -1 ); } *path_hint = memory_allocate_structure( libfsntfs_path_hint_t ); if( *path_hint == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create path hint.", function ); goto on_error; } if( memory_set( *path_hint, 0, sizeof( libfsntfs_path_hint_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear path hint.", function ); goto on_error; } return( 1 ); on_error: if( *path_hint != NULL ) { memory_free( *path_hint ); *path_hint = NULL; } return( -1 ); } /* Frees a path hint * Returns 1 if successful or -1 on error */ int libfsntfs_path_hint_free( libfsntfs_path_hint_t **path_hint, libcerror_error_t **error ) { static char *function = "libfsntfs_path_hint_free"; if( path_hint == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid path hint.", function ); return( -1 ); } if( *path_hint != NULL ) { if( ( *path_hint )->path != NULL ) { memory_free( ( *path_hint )->path ); } memory_free( *path_hint ); *path_hint = NULL; } return( 1 ); } /* Compares 2 path hints by file reference * Returns LIBCDATA_COMPARE_LESS, LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error */ int libfsntfs_path_hint_compare_by_file_reference( libfsntfs_path_hint_t *first_path_hint, libfsntfs_path_hint_t *second_path_hint, libcerror_error_t **error ) { static char *function = "libfsntfs_path_hint_compare_by_file_reference"; uint64_t first_mft_entry_index = 0; uint64_t second_mft_entry_index = 0; uint16_t first_sequence_number = 0; uint16_t second_sequence_number = 0; if( first_path_hint == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid first path hint.", function ); return( -1 ); } if( second_path_hint == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid second path hint.", function ); return( -1 ); } first_mft_entry_index = first_path_hint->file_reference & 0xffffffffffffUL; second_mft_entry_index = second_path_hint->file_reference & 0xffffffffffffUL; if( first_mft_entry_index < second_mft_entry_index ) { return( LIBCDATA_COMPARE_LESS ); } else if( first_mft_entry_index > second_mft_entry_index ) { return( LIBCDATA_COMPARE_GREATER ); } first_sequence_number = (uint16_t) ( first_path_hint->file_reference >> 48 ); second_sequence_number = (uint16_t) ( second_path_hint->file_reference >> 48 ); if( first_sequence_number < second_sequence_number ) { return( LIBCDATA_COMPARE_LESS ); } else if( first_sequence_number > second_sequence_number ) { return( LIBCDATA_COMPARE_GREATER ); } return( LIBCDATA_COMPARE_EQUAL ); } /* Retrieves the size of the UTF-8 encoded path * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_path_hint_get_utf8_path_size( libfsntfs_path_hint_t *path_hint, size_t *utf8_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_path_hint_get_utf8_path_size"; if( path_hint == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file path values.", function ); return( -1 ); } if( libuna_utf8_string_size_from_utf8_stream( path_hint->path, path_hint->path_size, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 string size.", function ); return( -1 ); } return( 1 ); } /* Retrieves the UTF-8 encoded path * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_path_hint_get_utf8_path( libfsntfs_path_hint_t *path_hint, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_path_hint_get_utf8_path"; if( path_hint == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file path values.", function ); return( -1 ); } if( libuna_utf8_string_copy_from_utf8_stream( utf8_string, utf8_string_size, path_hint->path, path_hint->path_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 string.", function ); return( -1 ); } return( 1 ); } /* Retrieves the size of the UTF-16 encoded path * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_path_hint_get_utf16_path_size( libfsntfs_path_hint_t *path_hint, size_t *utf16_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_path_hint_get_utf16_path_size"; if( path_hint == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file path values.", function ); return( -1 ); } if( libuna_utf16_string_size_from_utf8_stream( path_hint->path, path_hint->path_size, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 string size.", function ); return( -1 ); } return( 1 ); } /* Retrieves the UTF-16 encoded path * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_path_hint_get_utf16_path( libfsntfs_path_hint_t *path_hint, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_path_hint_get_utf16_path"; if( path_hint == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file path values.", function ); return( -1 ); } if( libuna_utf16_string_copy_from_utf8_stream( utf16_string, utf16_string_size, path_hint->path, path_hint->path_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 string.", function ); return( -1 ); } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_path_hint.h ================================================ /* * Path hint functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_PATH_HINT_H ) #define _LIBFSNTFS_PATH_HINT_H #include #include #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_path_hint libfsntfs_path_hint_t; struct libfsntfs_path_hint { /* The file reference */ uint64_t file_reference; /* The path */ uint8_t *path; /* The path size */ size_t path_size; }; int libfsntfs_path_hint_initialize( libfsntfs_path_hint_t **path_hint, libcerror_error_t **error ); int libfsntfs_path_hint_free( libfsntfs_path_hint_t **path_hint, libcerror_error_t **error ); int libfsntfs_path_hint_compare_by_file_reference( libfsntfs_path_hint_t *first_path_hint, libfsntfs_path_hint_t *second_path_hint, libcerror_error_t **error ); int libfsntfs_path_hint_get_utf8_path_size( libfsntfs_path_hint_t *path_hint, size_t *utf8_string_size, libcerror_error_t **error ); int libfsntfs_path_hint_get_utf8_path( libfsntfs_path_hint_t *path_hint, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); int libfsntfs_path_hint_get_utf16_path_size( libfsntfs_path_hint_t *path_hint, size_t *utf16_string_size, libcerror_error_t **error ); int libfsntfs_path_hint_get_utf16_path( libfsntfs_path_hint_t *path_hint, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_PATH_HINT_H ) */ ================================================ FILE: libfsntfs/libfsntfs_profiler.c ================================================ /* * The profiler functions * * Copyright (C) 2018-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_SYS_TIME_H ) #include #endif #include #include "libfsntfs_libcerror.h" #include "libfsntfs_profiler.h" #if defined( HAVE_PROFILER ) /* Creates a profiler * Make sure the value profiler is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_profiler_initialize( libfsntfs_profiler_t **profiler, libcerror_error_t **error ) { static char *function = "libfsntfs_profiler_initialize"; if( profiler == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid profiler.", function ); return( -1 ); } if( *profiler != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid profiler value already set.", function ); return( -1 ); } *profiler = memory_allocate_structure( libfsntfs_profiler_t ); if( *profiler == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create profiler.", function ); goto on_error; } if( memory_set( *profiler, 0, sizeof( libfsntfs_profiler_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear profiler.", function ); memory_free( *profiler ); *profiler = NULL; return( -1 ); } return( 1 ); on_error: if( *profiler != NULL ) { memory_free( *profiler ); *profiler = NULL; } return( -1 ); } /* Frees a profiler * Returns 1 if successful or -1 on error */ int libfsntfs_profiler_free( libfsntfs_profiler_t **profiler, libcerror_error_t **error ) { static char *function = "libfsntfs_profiler_free"; if( profiler == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid profiler.", function ); return( -1 ); } if( *profiler != NULL ) { memory_free( *profiler ); *profiler = NULL; } return( 1 ); } /* Opens the profiler * Returns 1 if successful or -1 on error */ int libfsntfs_profiler_open( libfsntfs_profiler_t *profiler, const char *filename, libcerror_error_t **error ) { static char *function = "libfsntfs_profiler_open"; if( profiler == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid profiler.", function ); return( -1 ); } if( profiler->output_stream != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid profiler - output stream value already set.", function ); return( -1 ); } profiler->output_stream = file_stream_open( filename, "w" ); if( profiler->output_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open profiler.", function ); goto on_error; } if( fprintf( profiler->output_stream, "timestamp,name,offset,size,duration\n" ) <= -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_WRITE_FAILED, "%s: unable to write header.", function ); goto on_error; } return( 1 ); on_error: if( profiler->output_stream != NULL ) { file_stream_close( profiler->output_stream ); profiler->output_stream = NULL; } return( -1 ); } /* Closes the profiler * Returns 0 if successful or -1 on error */ int libfsntfs_profiler_close( libfsntfs_profiler_t *profiler, libcerror_error_t **error ) { static char *function = "libfsntfs_profiler_close"; if( profiler == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid profiler.", function ); return( -1 ); } if( profiler->output_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid profiler - missing output stream.", function ); return( -1 ); } if( file_stream_close( profiler->output_stream ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close profiler.", function ); return( -1 ); } profiler->output_stream = NULL; return( 0 ); } /* Starts timing * Returns 1 if successful or -1 on error */ int libfsntfs_profiler_start_timing( libfsntfs_profiler_t *profiler, int64_t *start_timestamp, libcerror_error_t **error ) { struct timespec start_time; static char *function = "libfsntfs_profiler_start_timing"; if( profiler == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid profiler.", function ); return( -1 ); } if( start_timestamp == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid start timestamp.", function ); return( -1 ); } if( clock_gettime( CLOCK_REALTIME, &start_time ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve start time.", function ); return( -1 ); } *start_timestamp = ( (int64_t) start_time.tv_sec * 1000000000 ) + start_time.tv_nsec; return( 1 ); } /* Stops timing * Returns 1 if successful or -1 on error */ int libfsntfs_profiler_stop_timing( libfsntfs_profiler_t *profiler, int64_t start_timestamp, const char *name, off64_t offset, size64_t size, libcerror_error_t **error ) { struct timespec stop_time; static char *function = "libfsntfs_profiler_start_timing"; int64_t sample_time = 0; if( profiler == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid profiler.", function ); return( -1 ); } if( profiler->output_stream == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid profiler - missing output stream.", function ); return( -1 ); } if( clock_gettime( CLOCK_REALTIME, &stop_time ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve stop time.", function ); return( -1 ); } sample_time = ( (int64_t) stop_time.tv_sec * 1000000000 ) + stop_time.tv_nsec; sample_time -= start_timestamp; if( fprintf( profiler->output_stream, "%" PRIi64 ",%s,%" PRIi64 ",%" PRIu64 ",%" PRIi64 "\n", start_timestamp, name, offset, size, sample_time ) <= -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_WRITE_FAILED, "%s: unable to write sample.", function ); return( -1 ); } return( 1 ); } #endif /* defined( HAVE_PROFILER ) */ ================================================ FILE: libfsntfs/libfsntfs_profiler.h ================================================ /* * The profiler functions * * Copyright (C) 2018-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_PROFILER_H ) #define _LIBFSNTFS_PROFILER_H #include #include #include #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif #if defined( HAVE_PROFILER ) typedef struct libfsntfs_profiler libfsntfs_profiler_t; struct libfsntfs_profiler { /* The output stream */ FILE *output_stream; }; int libfsntfs_profiler_initialize( libfsntfs_profiler_t **profiler, libcerror_error_t **error ); int libfsntfs_profiler_free( libfsntfs_profiler_t **profiler, libcerror_error_t **error ); int libfsntfs_profiler_open( libfsntfs_profiler_t *profiler, const char *filename, libcerror_error_t **error ); int libfsntfs_profiler_close( libfsntfs_profiler_t *profiler, libcerror_error_t **error ); int libfsntfs_profiler_start_timing( libfsntfs_profiler_t *profiler, int64_t *start_timestamp, libcerror_error_t **error ); int libfsntfs_profiler_stop_timing( libfsntfs_profiler_t *profiler, int64_t start_timestamp, const char *name, off64_t offset, size64_t size, libcerror_error_t **error ); #endif /* defined( HAVE_PROFILER ) */ #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_PROFILER_H ) */ ================================================ FILE: libfsntfs/libfsntfs_reparse_point_attribute.c ================================================ /* * Reparse point attribute ($REPARSE_POINT) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_attribute.h" #include "libfsntfs_definitions.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_reparse_point_attribute.h" #include "libfsntfs_reparse_point_values.h" #include "libfsntfs_types.h" /* Retrieves the tag * The tag is a combination of the type and flags * Returns 1 if successful or -1 on error */ int libfsntfs_reparse_point_attribute_get_tag( libfsntfs_attribute_t *attribute, uint32_t *tag, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_reparse_point_attribute_get_tag"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } if( libfsntfs_reparse_point_values_get_tag( (libfsntfs_reparse_point_values_t *) internal_attribute->value, tag, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve compression method.", function ); return( -1 ); } return( 1 ); } /* Retrieves the Windows Overlay Filter (WOF) compression_method * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_reparse_point_attribute_get_compression_method( libfsntfs_attribute_t *attribute, uint32_t *compression_method, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_reparse_point_attribute_get_compression_method"; uint32_t attribute_type = 0; int result = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_reparse_point_values_get_compression_method( (libfsntfs_reparse_point_values_t *) internal_attribute->value, compression_method, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve compression method.", function ); return( -1 ); } return( result ); } /* Retrieves the size of the UTF-8 encoded substitute name * The returned size includes the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_reparse_point_attribute_get_utf8_substitute_name_size( libfsntfs_attribute_t *attribute, size_t *utf8_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_reparse_point_attribute_get_utf8_substitute_name_size"; uint32_t attribute_type = 0; int result = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_reparse_point_values_get_utf8_substitute_name_size( (libfsntfs_reparse_point_values_t *) internal_attribute->value, utf8_string_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-8 substitute name.", function ); return( -1 ); } return( result ); } /* Retrieves the UTF-8 encoded substitute name * The size should include the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_reparse_point_attribute_get_utf8_substitute_name( libfsntfs_attribute_t *attribute, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_reparse_point_attribute_get_utf8_substitute_name"; uint32_t attribute_type = 0; int result = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_reparse_point_values_get_utf8_substitute_name( (libfsntfs_reparse_point_values_t *) internal_attribute->value, utf8_string, utf8_string_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 substitute name.", function ); return( -1 ); } return( result ); } /* Retrieves the size of the UTF-16 encoded substitute name * The returned size includes the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_reparse_point_attribute_get_utf16_substitute_name_size( libfsntfs_attribute_t *attribute, size_t *utf16_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_reparse_point_attribute_get_utf16_substitute_name_size"; uint32_t attribute_type = 0; int result = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_reparse_point_values_get_utf16_substitute_name_size( (libfsntfs_reparse_point_values_t *) internal_attribute->value, utf16_string_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-16 substitute name.", function ); return( -1 ); } return( result ); } /* Retrieves the UTF-16 encoded substitute name * The size should include the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_reparse_point_attribute_get_utf16_substitute_name( libfsntfs_attribute_t *attribute, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_reparse_point_attribute_get_utf16_substitute_name"; uint32_t attribute_type = 0; int result = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_reparse_point_values_get_utf16_substitute_name( (libfsntfs_reparse_point_values_t *) internal_attribute->value, utf16_string, utf16_string_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 substitute name.", function ); return( -1 ); } return( result ); } /* Retrieves the size of the UTF-8 encoded print name * The returned size includes the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_reparse_point_attribute_get_utf8_print_name_size( libfsntfs_attribute_t *attribute, size_t *utf8_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_reparse_point_attribute_get_utf8_print_name_size"; uint32_t attribute_type = 0; int result = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_reparse_point_values_get_utf8_print_name_size( (libfsntfs_reparse_point_values_t *) internal_attribute->value, utf8_string_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-8 print name.", function ); return( -1 ); } return( result ); } /* Retrieves the UTF-8 encoded print name * The size should include the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_reparse_point_attribute_get_utf8_print_name( libfsntfs_attribute_t *attribute, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_reparse_point_attribute_get_utf8_print_name"; uint32_t attribute_type = 0; int result = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_reparse_point_values_get_utf8_print_name( (libfsntfs_reparse_point_values_t *) internal_attribute->value, utf8_string, utf8_string_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 print name.", function ); return( -1 ); } return( result ); } /* Retrieves the size of the UTF-16 encoded print name * The returned size includes the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_reparse_point_attribute_get_utf16_print_name_size( libfsntfs_attribute_t *attribute, size_t *utf16_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_reparse_point_attribute_get_utf16_print_name_size"; uint32_t attribute_type = 0; int result = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_reparse_point_values_get_utf16_print_name_size( (libfsntfs_reparse_point_values_t *) internal_attribute->value, utf16_string_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-16 print name.", function ); return( -1 ); } return( result ); } /* Retrieves the UTF-16 encoded print name * The size should include the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_reparse_point_attribute_get_utf16_print_name( libfsntfs_attribute_t *attribute, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_reparse_point_attribute_get_utf16_print_name"; uint32_t attribute_type = 0; int result = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_reparse_point_values_get_utf16_print_name( (libfsntfs_reparse_point_values_t *) internal_attribute->value, utf16_string, utf16_string_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 print name.", function ); return( -1 ); } return( result ); } ================================================ FILE: libfsntfs/libfsntfs_reparse_point_attribute.h ================================================ /* * Reparse point attribute ($REPARSE_POINT) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_REPARSE_POINT_ATTRIBUTE_H ) #define _LIBFSNTFS_REPARSE_POINT_ATTRIBUTE_H #include #include #include "libfsntfs_extern.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_types.h" #if defined( __cplusplus ) extern "C" { #endif LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_tag( libfsntfs_attribute_t *attribute, uint32_t *tag, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_compression_method( libfsntfs_attribute_t *attribute, uint32_t *compression_method, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_utf8_substitute_name_size( libfsntfs_attribute_t *attribute, size_t *utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_utf8_substitute_name( libfsntfs_attribute_t *attribute, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_utf16_substitute_name_size( libfsntfs_attribute_t *attribute, size_t *utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_utf16_substitute_name( libfsntfs_attribute_t *attribute, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_utf8_print_name_size( libfsntfs_attribute_t *attribute, size_t *utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_utf8_print_name( libfsntfs_attribute_t *attribute, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_utf16_print_name_size( libfsntfs_attribute_t *attribute, size_t *utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_reparse_point_attribute_get_utf16_print_name( libfsntfs_attribute_t *attribute, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_REPARSE_POINT_ATTRIBUTE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_reparse_point_values.c ================================================ /* * Reparse point attribute ($REPARSE_POINT) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include "libfsntfs_debug.h" #include "libfsntfs_definitions.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libuna.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_reparse_point_values.h" #include "fsntfs_reparse_point.h" /* Creates reparse point values * Make sure the value reparse_point_values is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_reparse_point_values_initialize( libfsntfs_reparse_point_values_t **reparse_point_values, libcerror_error_t **error ) { static char *function = "libfsntfs_reparse_point_values_initialize"; if( reparse_point_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid reparse point values.", function ); return( -1 ); } if( *reparse_point_values != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid reparse point values value already set.", function ); return( -1 ); } *reparse_point_values = memory_allocate_structure( libfsntfs_reparse_point_values_t ); if( *reparse_point_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create reparse point values.", function ); goto on_error; } if( memory_set( *reparse_point_values, 0, sizeof( libfsntfs_reparse_point_values_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear reparse point values.", function ); goto on_error; } return( 1 ); on_error: if( *reparse_point_values != NULL ) { memory_free( *reparse_point_values ); *reparse_point_values = NULL; } return( -1 ); } /* Frees reparse point values * Returns 1 if successful or -1 on error */ int libfsntfs_reparse_point_values_free( libfsntfs_reparse_point_values_t **reparse_point_values, libcerror_error_t **error ) { static char *function = "libfsntfs_reparse_point_values_free"; if( reparse_point_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid reparse point values.", function ); return( -1 ); } if( *reparse_point_values != NULL ) { if( ( *reparse_point_values )->reparse_data != NULL ) { memory_free( ( *reparse_point_values )->reparse_data ); } memory_free( *reparse_point_values ); *reparse_point_values = NULL; } return( 1 ); } /* Reads the reparse point values * Returns 1 if successful or -1 on error */ int libfsntfs_reparse_point_values_read_data( libfsntfs_reparse_point_values_t *reparse_point_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_reparse_point_values_read_data"; uint32_t flags = 0; #if defined( HAVE_DEBUG_OUTPUT ) system_character_t *value_string = NULL; size_t value_string_size = 0; uint32_t value_32bit = 0; int result = 0; #endif if( reparse_point_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid reparse point values.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reparse point data:\n", function ); libcnotify_print_data( data, data_size, 0 ); } #endif byte_stream_copy_to_uint32_little_endian( ( (fsntfs_reparse_point_t *) data )->tag, reparse_point_values->tag ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_reparse_point_t *) data )->reparse_data_size, reparse_point_values->reparse_data_size ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: tag\t\t\t\t: 0x%08" PRIx32 "\n", function, reparse_point_values->tag ); libfsntfs_debug_print_reparse_point_tag( reparse_point_values->tag ); libcnotify_printf( "\n" ); libcnotify_printf( "%s: reparse data size\t\t: %" PRIu16 "\n", function, reparse_point_values->reparse_data_size ); libcnotify_printf( "\n" ); } #endif if( reparse_point_values->reparse_data_size > 0 ) { if( ( sizeof( fsntfs_reparse_point_t ) > data_size ) || ( (size_t) reparse_point_values->reparse_data_size > ( data_size - sizeof( fsntfs_reparse_point_t ) ) ) || ( (size_t) reparse_point_values->reparse_data_size > MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid reparse data size value out of bounds.", function ); goto on_error; } reparse_point_values->reparse_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * reparse_point_values->reparse_data_size ); if( reparse_point_values->reparse_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create reparse data.", function ); goto on_error; } if( memory_copy( reparse_point_values->reparse_data, &( data[ sizeof( fsntfs_reparse_point_t ) ] ), (size_t) reparse_point_values->reparse_data_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy reparse data.", function ); goto on_error; } } if( reparse_point_values->tag == 0x80000017 ) { byte_stream_copy_to_uint32_little_endian( &( reparse_point_values->reparse_data[ 12 ] ), reparse_point_values->compression_method ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { byte_stream_copy_to_uint32_little_endian( &( reparse_point_values->reparse_data[ 0 ] ), value_32bit ); libcnotify_printf( "%s: external version\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( &( reparse_point_values->reparse_data[ 4 ] ), value_32bit ); libcnotify_printf( "%s: external provider\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( &( reparse_point_values->reparse_data[ 8 ] ), value_32bit ); libcnotify_printf( "%s: internal version\t\t: %" PRIu32 "\n", function, value_32bit ); libcnotify_printf( "%s: compression method\t\t: %" PRIu32 " (%s)\n", function, reparse_point_values->compression_method, libfsntfs_debug_print_compression_method( reparse_point_values->compression_method ) ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ } else if( ( reparse_point_values->tag == 0xa0000003 ) || ( reparse_point_values->tag == 0xa000000c ) ) { byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mount_point_reparse_data_t *) reparse_point_values->reparse_data )->substitute_name_offset, reparse_point_values->substitute_name_offset ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mount_point_reparse_data_t *) reparse_point_values->reparse_data )->substitute_name_size, reparse_point_values->substitute_name_size ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mount_point_reparse_data_t *) reparse_point_values->reparse_data )->print_name_offset, reparse_point_values->print_name_offset ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_mount_point_reparse_data_t *) reparse_point_values->reparse_data )->print_name_size, reparse_point_values->print_name_size ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: substitute name offset\t: 0x%04" PRIx16 "\n", function, reparse_point_values->substitute_name_offset ); libcnotify_printf( "%s: substitute name size\t\t: %" PRIu16 "\n", function, reparse_point_values->substitute_name_size ); libcnotify_printf( "%s: print name offset\t\t: 0x%04" PRIx16 "\n", function, reparse_point_values->print_name_offset ); libcnotify_printf( "%s: print name size\t\t: %" PRIu16 "\n", function, reparse_point_values->print_name_size ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ } if( reparse_point_values->tag == 0xa0000003 ) { reparse_point_values->substitute_name_offset += sizeof( fsntfs_mount_point_reparse_data_t ); reparse_point_values->print_name_offset += sizeof( fsntfs_mount_point_reparse_data_t ); } else if( reparse_point_values->tag == 0xa000000c ) { byte_stream_copy_to_uint32_little_endian( ( (fsntfs_symbolic_link_reparse_data_t *) reparse_point_values->reparse_data )->flags, flags ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: flags\t\t\t\t: 0x%08" PRIx32 "\n", function, flags ); } #endif reparse_point_values->substitute_name_offset += sizeof( fsntfs_symbolic_link_reparse_data_t ); reparse_point_values->print_name_offset += sizeof( fsntfs_symbolic_link_reparse_data_t ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( ( reparse_point_values->tag != 0x80000017 ) && ( reparse_point_values->tag != 0xa0000003 ) && ( reparse_point_values->tag != 0xa000000c ) ) { libcnotify_printf( "%s: unusupported reparse point tag: 0x%08" PRIx32 "\n", function, reparse_point_values->tag ); } } #endif if( reparse_point_values->substitute_name_size > 0 ) { if( reparse_point_values->substitute_name_offset >= reparse_point_values->reparse_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid substitute name offset value out of bounds.", function ); goto on_error; } if( reparse_point_values->substitute_name_size > ( reparse_point_values->reparse_data_size - reparse_point_values->substitute_name_offset ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid substitute name size value out of bounds.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libuna_utf16_string_size_from_utf16_stream( &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ), (size_t) reparse_point_values->substitute_name_size, LIBUNA_ENDIAN_LITTLE, &value_string_size, error ); #else result = libuna_utf8_string_size_from_utf16_stream( &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ), (size_t) reparse_point_values->substitute_name_size, LIBUNA_ENDIAN_LITTLE, &value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine size of substitute name string.", function ); goto on_error; } value_string = system_string_allocate( value_string_size ); if( value_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create substitute name string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libuna_utf16_string_copy_from_utf16_stream( (libuna_utf16_character_t *) value_string, value_string_size, &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ), (size_t) reparse_point_values->substitute_name_size, LIBUNA_ENDIAN_LITTLE, error ); #else result = libuna_utf8_string_copy_from_utf16_stream( (libuna_utf8_character_t *) value_string, value_string_size, &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ), (size_t) reparse_point_values->substitute_name_size, LIBUNA_ENDIAN_LITTLE, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set substitute name string.", function ); goto on_error; } libcnotify_printf( "%s: substitute name\t\t: %" PRIs_SYSTEM "\n", function, value_string ); memory_free( value_string ); value_string = NULL; } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ } if( reparse_point_values->print_name_size > 0 ) { if( reparse_point_values->print_name_offset >= reparse_point_values->reparse_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid print name offset value out of bounds.", function ); goto on_error; } if( reparse_point_values->print_name_size > ( reparse_point_values->reparse_data_size - reparse_point_values->print_name_offset ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid print name size value out of bounds.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libuna_utf16_string_size_from_utf16_stream( &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ), (size_t) reparse_point_values->print_name_size, LIBUNA_ENDIAN_LITTLE, &value_string_size, error ); #else result = libuna_utf8_string_size_from_utf16_stream( &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ), (size_t) reparse_point_values->print_name_size, LIBUNA_ENDIAN_LITTLE, &value_string_size, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine size of print name string.", function ); goto on_error; } value_string = system_string_allocate( value_string_size ); if( value_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create print name string.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libuna_utf16_string_copy_from_utf16_stream( (libuna_utf16_character_t *) value_string, value_string_size, &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ), (size_t) reparse_point_values->print_name_size, LIBUNA_ENDIAN_LITTLE, error ); #else result = libuna_utf8_string_copy_from_utf16_stream( (libuna_utf8_character_t *) value_string, value_string_size, &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ), (size_t) reparse_point_values->print_name_size, LIBUNA_ENDIAN_LITTLE, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set print name string.", function ); goto on_error; } libcnotify_printf( "%s: print name\t\t\t: %" PRIs_SYSTEM "\n", function, value_string ); memory_free( value_string ); value_string = NULL; } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "\n" ); } #endif return( 1 ); on_error: #if defined( HAVE_DEBUG_OUTPUT ) if( value_string != NULL ) { memory_free( value_string ); } #endif if( reparse_point_values->reparse_data != NULL ) { memory_free( reparse_point_values->reparse_data ); reparse_point_values->reparse_data = NULL; } reparse_point_values->reparse_data_size = 0; return( -1 ); } /* Reads the reparse point values from an MFT attribute * Returns 1 if successful or -1 on error */ int libfsntfs_reparse_point_values_read_from_mft_attribute( libfsntfs_reparse_point_values_t *reparse_point_values, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ) { uint8_t *data = NULL; static char *function = "libfsntfs_reparse_point_values_read_from_mft_attribute"; size_t data_size = 0; uint32_t attribute_type = 0; int result = 0; if( reparse_point_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid reparse point values.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_type( mft_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve type from attribute.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_mft_attribute_data_is_resident( mft_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if attribute data is resident.", function ); return( -1 ); } else if( result == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported non-resident attribute.", function ); return( 1 ); } if( libfsntfs_mft_attribute_get_resident_data( mft_attribute, &data, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve resident data from attribute.", function ); return( -1 ); } if( libfsntfs_reparse_point_values_read_data( reparse_point_values, data, data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read reparse point values.", function ); return( -1 ); } return( 1 ); } /* Retrieves the tag * The tag is a combination of the type and flags * Returns 1 if successful or -1 on error */ int libfsntfs_reparse_point_values_get_tag( libfsntfs_reparse_point_values_t *reparse_point_values, uint32_t *tag, libcerror_error_t **error ) { static char *function = "libfsntfs_reparse_point_values_get_tag"; if( reparse_point_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid reparse point values.", function ); return( -1 ); } if( tag == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid tag.", function ); return( -1 ); } *tag = reparse_point_values->tag; return( 1 ); } /* Retrieves the Windows Overlay Filter (WOF) compression method * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_reparse_point_values_get_compression_method( libfsntfs_reparse_point_values_t *reparse_point_values, uint32_t *compression_method, libcerror_error_t **error ) { static char *function = "libfsntfs_reparse_point_values_get_compression_method"; if( reparse_point_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid reparse point values.", function ); return( -1 ); } if( compression_method == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid compression method.", function ); return( -1 ); } if( reparse_point_values->tag == 0x80000017 ) { *compression_method = reparse_point_values->compression_method; return( 1 ); } return( 0 ); } /* Retrieves the size of the UTF-8 encoded substitute name * The returned size includes the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_reparse_point_values_get_utf8_substitute_name_size( libfsntfs_reparse_point_values_t *reparse_point_values, size_t *utf8_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_reparse_point_values_get_utf8_substitute_name_size"; if( reparse_point_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid reparse point values.", function ); return( -1 ); } if( reparse_point_values->substitute_name_size == 0 ) { return( 0 ); } if( libuna_utf8_string_size_from_utf16_stream( &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ), (size_t) reparse_point_values->substitute_name_size, LIBUNA_ENDIAN_LITTLE, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 string size.", function ); return( -1 ); } return( 1 ); } /* Retrieves the UTF-8 encoded substitute name * The size should include the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_reparse_point_values_get_utf8_substitute_name( libfsntfs_reparse_point_values_t *reparse_point_values, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_reparse_point_values_get_utf8_substitute_name"; if( reparse_point_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid reparse point values.", function ); return( -1 ); } if( reparse_point_values->substitute_name_size == 0 ) { return( 0 ); } if( libuna_utf8_string_copy_from_utf16_stream( utf8_string, utf8_string_size, &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ), (size_t) reparse_point_values->substitute_name_size, LIBUNA_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 string.", function ); return( -1 ); } return( 1 ); } /* Retrieves the size of the UTF-16 encoded substitute name * The returned size includes the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_reparse_point_values_get_utf16_substitute_name_size( libfsntfs_reparse_point_values_t *reparse_point_values, size_t *utf16_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_reparse_point_values_get_utf16_substitute_name_size"; if( reparse_point_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid reparse point values.", function ); return( -1 ); } if( reparse_point_values->substitute_name_size == 0 ) { return( 0 ); } if( libuna_utf16_string_size_from_utf16_stream( &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ), (size_t) reparse_point_values->substitute_name_size, LIBUNA_ENDIAN_LITTLE, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 string size.", function ); return( -1 ); } return( 1 ); } /* Retrieves the UTF-16 encoded substitute name * The size should include the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_reparse_point_values_get_utf16_substitute_name( libfsntfs_reparse_point_values_t *reparse_point_values, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_reparse_point_values_get_utf16_substitute_name"; if( reparse_point_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid reparse point values.", function ); return( -1 ); } if( reparse_point_values->substitute_name_size == 0 ) { return( 0 ); } if( libuna_utf16_string_copy_from_utf16_stream( utf16_string, utf16_string_size, &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ), (size_t) reparse_point_values->substitute_name_size, LIBUNA_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 string.", function ); return( -1 ); } return( 1 ); } /* Retrieves the size of the UTF-8 encoded print name * The returned size includes the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_reparse_point_values_get_utf8_print_name_size( libfsntfs_reparse_point_values_t *reparse_point_values, size_t *utf8_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_reparse_point_values_get_utf8_print_name_size"; if( reparse_point_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid reparse point values.", function ); return( -1 ); } if( reparse_point_values->print_name_size == 0 ) { return( 0 ); } if( libuna_utf8_string_size_from_utf16_stream( &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ), (size_t) reparse_point_values->print_name_size, LIBUNA_ENDIAN_LITTLE, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 string size.", function ); return( -1 ); } return( 1 ); } /* Retrieves the UTF-8 encoded print name * The size should include the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_reparse_point_values_get_utf8_print_name( libfsntfs_reparse_point_values_t *reparse_point_values, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_reparse_point_values_get_utf8_print_name"; if( reparse_point_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid reparse point values.", function ); return( -1 ); } if( reparse_point_values->print_name_size == 0 ) { return( 0 ); } if( libuna_utf8_string_copy_from_utf16_stream( utf8_string, utf8_string_size, &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ), (size_t) reparse_point_values->print_name_size, LIBUNA_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 string.", function ); return( -1 ); } return( 1 ); } /* Retrieves the size of the UTF-16 encoded print name * The returned size includes the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_reparse_point_values_get_utf16_print_name_size( libfsntfs_reparse_point_values_t *reparse_point_values, size_t *utf16_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_reparse_point_values_get_utf16_print_name_size"; if( reparse_point_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid reparse point values.", function ); return( -1 ); } if( reparse_point_values->print_name_size == 0 ) { return( 0 ); } if( libuna_utf16_string_size_from_utf16_stream( &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ), (size_t) reparse_point_values->print_name_size, LIBUNA_ENDIAN_LITTLE, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 string size.", function ); return( -1 ); } return( 1 ); } /* Retrieves the UTF-16 encoded print name * The size should include the end of string character * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_reparse_point_values_get_utf16_print_name( libfsntfs_reparse_point_values_t *reparse_point_values, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_reparse_point_values_get_utf16_print_name"; if( reparse_point_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid reparse point values.", function ); return( -1 ); } if( reparse_point_values->print_name_size == 0 ) { return( 0 ); } if( libuna_utf16_string_copy_from_utf16_stream( utf16_string, utf16_string_size, &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ), (size_t) reparse_point_values->print_name_size, LIBUNA_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 string.", function ); return( -1 ); } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_reparse_point_values.h ================================================ /* * Reparse point attribute ($REPARSE_POINT) values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_REPARSE_POINT_VALUES_H ) #define _LIBFSNTFS_REPARSE_POINT_VALUES_H #include #include #include "libfsntfs_libcerror.h" #include "libfsntfs_mft_attribute.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_reparse_point_values libfsntfs_reparse_point_values_t; struct libfsntfs_reparse_point_values { /* The tag */ uint32_t tag; /* The compression method */ uint32_t compression_method; /* The substitute name offset */ uint16_t substitute_name_offset; /* The substitute name size */ uint16_t substitute_name_size; /* The print name offset */ uint16_t print_name_offset; /* The print name size */ uint16_t print_name_size; /* The reparse data */ uint8_t *reparse_data; /* The reparse data size */ size_t reparse_data_size; }; int libfsntfs_reparse_point_values_initialize( libfsntfs_reparse_point_values_t **reparse_point_values, libcerror_error_t **error ); int libfsntfs_reparse_point_values_free( libfsntfs_reparse_point_values_t **reparse_point_values, libcerror_error_t **error ); int libfsntfs_reparse_point_values_read_data( libfsntfs_reparse_point_values_t *reparse_point_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_reparse_point_values_read_from_mft_attribute( libfsntfs_reparse_point_values_t *reparse_point_values, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ); int libfsntfs_reparse_point_values_get_tag( libfsntfs_reparse_point_values_t *reparse_point_values, uint32_t *tag, libcerror_error_t **error ); int libfsntfs_reparse_point_values_get_compression_method( libfsntfs_reparse_point_values_t *reparse_point_values, uint32_t *compression_method, libcerror_error_t **error ); int libfsntfs_reparse_point_values_get_utf8_substitute_name_size( libfsntfs_reparse_point_values_t *reparse_point_values, size_t *utf8_string_size, libcerror_error_t **error ); int libfsntfs_reparse_point_values_get_utf8_substitute_name( libfsntfs_reparse_point_values_t *reparse_point_values, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); int libfsntfs_reparse_point_values_get_utf16_substitute_name_size( libfsntfs_reparse_point_values_t *reparse_point_values, size_t *utf16_string_size, libcerror_error_t **error ); int libfsntfs_reparse_point_values_get_utf16_substitute_name( libfsntfs_reparse_point_values_t *reparse_point_values, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); int libfsntfs_reparse_point_values_get_utf8_print_name_size( libfsntfs_reparse_point_values_t *reparse_point_values, size_t *utf8_string_size, libcerror_error_t **error ); int libfsntfs_reparse_point_values_get_utf8_print_name( libfsntfs_reparse_point_values_t *reparse_point_values, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); int libfsntfs_reparse_point_values_get_utf16_print_name_size( libfsntfs_reparse_point_values_t *reparse_point_values, size_t *utf16_string_size, libcerror_error_t **error ); int libfsntfs_reparse_point_values_get_utf16_print_name( libfsntfs_reparse_point_values_t *reparse_point_values, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_REPARSE_POINT_VALUES_H ) */ ================================================ FILE: libfsntfs/libfsntfs_sds_index_value.c ================================================ /* * $SDS index value functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_sds_index_value.h" #include "fsntfs_secure.h" /* Creates $SDS index value * Make sure the value sds_index_value is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_sds_index_value_initialize( libfsntfs_sds_index_value_t **sds_index_value, libcerror_error_t **error ) { static char *function = "libfsntfs_sds_index_value_initialize"; if( sds_index_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid $SDS index value.", function ); return( -1 ); } if( *sds_index_value != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid $SDS index value value already set.", function ); return( -1 ); } *sds_index_value = memory_allocate_structure( libfsntfs_sds_index_value_t ); if( *sds_index_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create $SDS index value.", function ); goto on_error; } if( memory_set( *sds_index_value, 0, sizeof( libfsntfs_sds_index_value_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear $SDS index value.", function ); goto on_error; } return( 1 ); on_error: if( *sds_index_value != NULL ) { memory_free( *sds_index_value ); *sds_index_value = NULL; } return( -1 ); } /* Frees $SDS index value * Returns 1 if successful or -1 on error */ int libfsntfs_sds_index_value_free( libfsntfs_sds_index_value_t **sds_index_value, libcerror_error_t **error ) { static char *function = "libfsntfs_sds_index_value_free"; if( sds_index_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid $SDS index value.", function ); return( -1 ); } if( *sds_index_value != NULL ) { memory_free( *sds_index_value ); *sds_index_value = NULL; } return( 1 ); } /* Reads the $SDS index value * Returns 1 if successful or -1 on error */ int libfsntfs_sds_index_value_read_data( libfsntfs_sds_index_value_t *sds_index_value, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_sds_index_value_read_data"; #if defined( HAVE_DEBUG_OUTPUT ) uint64_t value_64bit = 0; uint32_t value_32bit = 0; #endif if( sds_index_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid $SDS index value.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: $SDS index value:\n", function ); libcnotify_print_data( data, data_size, 0 ); } #endif if( data_size != sizeof( fsntfs_secure_index_value_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported $SDS index value size: %" PRIzd "\n", function, data_size ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { byte_stream_copy_to_uint32_little_endian( ( (fsntfs_secure_index_value_t *) data )->hash, value_32bit ); libcnotify_printf( "%s: hash\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_secure_index_value_t *) data )->identifier, value_32bit ); libcnotify_printf( "%s: identifier\t\t\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_secure_index_value_t *) data )->data_offset, value_64bit ); libcnotify_printf( "%s: data offset\t\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_secure_index_value_t *) data )->data_size, value_32bit ); libcnotify_printf( "%s: data size\t\t\t\t: %" PRIu32 "\n", function, value_32bit ); libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_sds_index_value.h ================================================ /* * $SDS index value functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_SDS_INDEX_VALUE_H ) #define _LIBFSNTFS_SDS_INDEX_VALUE_H #include #include #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_sds_index_value libfsntfs_sds_index_value_t; struct libfsntfs_sds_index_value { /* Dummy */ int dummy; }; int libfsntfs_sds_index_value_initialize( libfsntfs_sds_index_value_t **sds_index_value, libcerror_error_t **error ); int libfsntfs_sds_index_value_free( libfsntfs_sds_index_value_t **sds_index_value, libcerror_error_t **error ); int libfsntfs_sds_index_value_read_data( libfsntfs_sds_index_value_t *sds_index_value, const uint8_t *data, size_t data_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_SDS_INDEX_VALUE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_security_descriptor_attribute.c ================================================ /* * Security descriptor attribute ($SECURITY_DESCRIPTOR) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_attribute.h" #include "libfsntfs_definitions.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_security_descriptor_attribute.h" #include "libfsntfs_security_descriptor_values.h" #include "libfsntfs_types.h" /* Retrieves the security descriptor (data) size * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_security_descriptor_attribute_get_security_descriptor_size( libfsntfs_attribute_t *attribute, size_t *data_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_security_descriptor_attribute_get_security_descriptor_size"; uint32_t attribute_type = 0; int result = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( internal_attribute->value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid attribute - missing value.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_SECURITY_DESCRIPTOR ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_security_descriptor_values_get_data_size( (libfsntfs_security_descriptor_values_t *) internal_attribute->value, data_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data size from security descriptor values.", function ); return( -1 ); } return( result ); } /* Retrieves the security descriptor (data) * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_security_descriptor_attribute_get_security_descriptor( libfsntfs_attribute_t *attribute, uint8_t *data, size_t data_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_security_descriptor_attribute_get_security_descriptor"; uint32_t attribute_type = 0; int result = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( internal_attribute->value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid attribute - missing value.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_SECURITY_DESCRIPTOR ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_security_descriptor_values_get_data( (libfsntfs_security_descriptor_values_t *) internal_attribute->value, data, data_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data from security descriptor values.", function ); return( -1 ); } return( result ); } ================================================ FILE: libfsntfs/libfsntfs_security_descriptor_attribute.h ================================================ /* * Security descriptor attribute ($SECURITY_DESCRIPTOR) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_SECURITY_DESCRIPTOR_ATTRIBUTE_H ) #define _LIBFSNTFS_SECURITY_DESCRIPTOR_ATTRIBUTE_H #include #include #include "libfsntfs_extern.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_types.h" #if defined( __cplusplus ) extern "C" { #endif LIBFSNTFS_EXTERN \ int libfsntfs_security_descriptor_attribute_get_security_descriptor_size( libfsntfs_attribute_t *attribute, size_t *data_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_security_descriptor_attribute_get_security_descriptor( libfsntfs_attribute_t *attribute, uint8_t *data, size_t data_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_SECURITY_DESCRIPTOR_ATTRIBUTE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_security_descriptor_index.c ================================================ /* * Security descriptor index functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_data_stream.h" #include "libfsntfs_definitions.h" #include "libfsntfs_index.h" #include "libfsntfs_index_node.h" #include "libfsntfs_index_value.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_mft_entry.h" #include "libfsntfs_security_descriptor_index.h" #include "libfsntfs_security_descriptor_index_value.h" #include "libfsntfs_security_descriptor_values.h" #include "libfsntfs_sds_index_value.h" #include "libfsntfs_types.h" #include "fsntfs_secure.h" /* Creates a security descriptor index * Make sure the value security_descriptor_index is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_security_descriptor_index_initialize( libfsntfs_security_descriptor_index_t **security_descriptor_index, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfsntfs_mft_attribute_t *data_attribute, libcerror_error_t **error ) { static char *function = "libfsntfs_security_descriptor_index_initialize"; if( security_descriptor_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor index.", function ); return( -1 ); } if( *security_descriptor_index != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid security descriptor index value already set.", function ); return( -1 ); } if( data_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid $SDS data attribute.", function ); return( -1 ); } *security_descriptor_index = memory_allocate_structure( libfsntfs_security_descriptor_index_t ); if( *security_descriptor_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create security descriptor index.", function ); goto on_error; } if( memory_set( *security_descriptor_index, 0, sizeof( libfsntfs_security_descriptor_index_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear security descriptor index.", function ); memory_free( *security_descriptor_index ); *security_descriptor_index = NULL; return( -1 ); } /* TODO move out of index ? */ if( libfsntfs_data_stream_initialize( &( ( *security_descriptor_index )->data_stream ), io_handle, file_io_handle, data_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create $SDS data stream.", function ); goto on_error; } return( 1 ); on_error: if( *security_descriptor_index != NULL ) { memory_free( *security_descriptor_index ); *security_descriptor_index = NULL; } return( -1 ); } /* Frees a security descriptor index * Returns 1 if successful or -1 on error */ int libfsntfs_security_descriptor_index_free( libfsntfs_security_descriptor_index_t **security_descriptor_index, libcerror_error_t **error ) { static char *function = "libfsntfs_security_descriptor_index_free"; int result = 1; if( security_descriptor_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor index.", function ); return( -1 ); } if( *security_descriptor_index != NULL ) { if( ( *security_descriptor_index )->sii_index != NULL ) { if( libfsntfs_index_free( &( ( *security_descriptor_index )->sii_index ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free $SII index.", function ); result = -1; } } if( libfsntfs_data_stream_free( &( ( *security_descriptor_index )->data_stream ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free $SDS data stream.", function ); result = -1; } memory_free( *security_descriptor_index ); *security_descriptor_index = NULL; } return( result ); } /* Reads the security descriptor identifier ($SII) index * Returns 1 if successful or -1 on error */ int libfsntfs_security_descriptor_index_read_sii_index( libfsntfs_security_descriptor_index_t *security_descriptor_index, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfsntfs_mft_entry_t *mft_entry, libcerror_error_t **error ) { static char *function = "libfsntfs_security_descriptor_index_read_sii_index"; uint32_t attribute_type = 0; uint32_t collation_type = 0; int result = 0; if( security_descriptor_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor index.", function ); return( -1 ); } if( security_descriptor_index->sii_index != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid security descriptor index - $SII index value already set.", function ); return( -1 ); } if( libfsntfs_index_initialize( &( security_descriptor_index->sii_index ), io_handle, (uint8_t *) "$SII", 5, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create $SII index.", function ); goto on_error; } result = libfsntfs_index_read( security_descriptor_index->sii_index, file_io_handle, mft_entry, 0, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read $SII index.", function ); goto on_error; } else if( result != 0 ) { if( libfsntfs_index_get_attribute_type( security_descriptor_index->sii_index, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type from index.", function ); goto on_error; } if( attribute_type != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported index attribute type.", function ); goto on_error; } if( libfsntfs_index_get_collation_type( security_descriptor_index->sii_index, &collation_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve collation type from index.", function ); goto on_error; } if( collation_type != 16 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported index collation type.", function ); goto on_error; } } return( 1 ); on_error: if( security_descriptor_index->sii_index != NULL ) { libfsntfs_index_free( &( security_descriptor_index->sii_index ), NULL ); } return( -1 ); } /* Retrieves the security descriptor from an index node for a specific identifier * This function creates new security descriptor values * Returns 1 if successful, 0 if no such security descriptor or -1 on error */ int libfsntfs_security_descriptor_index_get_entry_from_index_node_by_identifier( libfsntfs_security_descriptor_index_t *security_descriptor_index, libbfio_handle_t *file_io_handle, libfsntfs_index_node_t *index_node, uint32_t security_descriptor_identifier, libfsntfs_security_descriptor_values_t **security_descriptor_values, int recursion_depth, libcerror_error_t **error ) { uint8_t secure_index_value_data[ sizeof( fsntfs_secure_index_value_t ) ]; libfsntfs_index_node_t *sub_node = NULL; libfsntfs_index_value_t *index_value = NULL; libfsntfs_sds_index_value_t *sds_index_value = NULL; libfsntfs_security_descriptor_index_value_t *security_descriptor_index_value = NULL; libfsntfs_security_descriptor_values_t *safe_security_descriptor_values = NULL; static char *function = "libfsntfs_security_descriptor_index_get_entry_from_index_node_by_identifier"; size_t security_descriptor_data_size = 0; ssize_t read_count = 0; off64_t index_entry_offset = 0; int compare_result = 0; int index_value_entry = 0; int is_allocated = 0; int number_of_index_values = 0; int result = 0; if( security_descriptor_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor index.", function ); return( -1 ); } if( security_descriptor_index->sii_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor index - missing $SII index.", function ); return( -1 ); } if( security_descriptor_index->sii_index->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor index - invalid $SII index - missing IO handle.", function ); return( -1 ); } if( security_descriptor_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor values.", function ); return( -1 ); } if( ( recursion_depth < 0 ) || ( recursion_depth > LIBFSNTFS_MAXIMUM_RECURSION_DEPTH ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid recursion depth value out of bounds.", function ); return( -1 ); } if( libfsntfs_index_node_get_number_of_values( index_node, &number_of_index_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of values from index node.", function ); goto on_error; } for( index_value_entry = 0; index_value_entry < number_of_index_values; index_value_entry++ ) { if( libfsntfs_index_node_get_value_by_index( index_node, index_value_entry, &index_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve value: %d from index node.", function, index_value_entry ); goto on_error; } if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 ) { if( index_value->sub_node_vcn > (uint64_t) INT_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: node index value: %d sub node VCN value out of bounds.", function, index_value_entry ); goto on_error; } is_allocated = libfsntfs_index_sub_node_is_allocated( security_descriptor_index->sii_index, (int) index_value->sub_node_vcn, error ); if( is_allocated == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if sub node with VCN: %d is allocated.", function, (int) index_value->sub_node_vcn ); goto on_error; } else if( is_allocated == 0 ) { continue; } } if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_LAST ) != 0 ) { break; } if( libfsntfs_security_descriptor_index_value_initialize( &security_descriptor_index_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create security descriptor index value.", function ); goto on_error; } if( libfsntfs_security_descriptor_index_value_read_data( security_descriptor_index_value, index_value->value_data, (size_t) index_value->value_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read security descriptor index value.", function ); goto on_error; } if( security_descriptor_identifier < security_descriptor_index_value->identifier ) { compare_result = LIBCDATA_COMPARE_LESS; } else if( security_descriptor_identifier > security_descriptor_index_value->identifier ) { compare_result = LIBCDATA_COMPARE_GREATER; } else { compare_result = LIBCDATA_COMPARE_EQUAL; } if( compare_result != LIBCDATA_COMPARE_EQUAL ) { if( libfsntfs_security_descriptor_index_value_free( &security_descriptor_index_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free security descriptor index value.", function ); goto on_error; } } if( compare_result == LIBCDATA_COMPARE_LESS ) { if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 ) { break; } } else if( compare_result == LIBCDATA_COMPARE_EQUAL ) { break; } } if( compare_result == LIBCDATA_COMPARE_EQUAL ) { if( security_descriptor_index_value->data_size < (size64_t) ( sizeof( fsntfs_secure_index_value_t ) + 20 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported security descriptor stream ($SDS) data size: %" PRIu64 "\n", function, security_descriptor_index_value->data_size ); return( -1 ); } read_count = libfsntfs_data_stream_read_buffer_at_offset( security_descriptor_index->data_stream, secure_index_value_data, sizeof( fsntfs_secure_index_value_t ), (off64_t) security_descriptor_index_value->data_offset, error ); if( read_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read security descriptor stream ($SDS) data at offset: 0x%08" PRIx64 ".", function, security_descriptor_index_value->data_offset ); goto on_error; } if( libfsntfs_sds_index_value_initialize( &sds_index_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create $SDS index value.", function ); goto on_error; } if( libfsntfs_sds_index_value_read_data( sds_index_value, secure_index_value_data, sizeof( fsntfs_secure_index_value_t ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read $SDS index value data.", function ); goto on_error; } /* TODO check index values against secure_index_value */ if( libfsntfs_security_descriptor_values_initialize( &safe_security_descriptor_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create security descriptor values.", function ); goto on_error; } security_descriptor_data_size = (size_t) ( security_descriptor_index_value->data_size - sizeof( fsntfs_secure_index_value_t ) ); if( ( security_descriptor_data_size == 0 ) || ( security_descriptor_data_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid security descriptor values data value out of bounds.", function, index_value_entry ); goto on_error; } safe_security_descriptor_values->data = memory_allocate( sizeof( uint8_t ) * security_descriptor_data_size ); if( safe_security_descriptor_values->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create security descriptor values data.", function ); goto on_error; } safe_security_descriptor_values->data_size = security_descriptor_data_size; if( memory_set( safe_security_descriptor_values->data, 0, sizeof( uint8_t ) * safe_security_descriptor_values->data_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear security descriptor data.", function ); goto on_error; } read_count = libfsntfs_data_stream_read_buffer( security_descriptor_index->data_stream, safe_security_descriptor_values->data, safe_security_descriptor_values->data_size, error ); if( read_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read security descriptor data at offset: 0x%08" PRIx64 ".", function, security_descriptor_index_value->data_offset ); goto on_error; } if( libfsntfs_security_descriptor_values_read_data( safe_security_descriptor_values, safe_security_descriptor_values->data, safe_security_descriptor_values->data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read security descriptor values.", function ); goto on_error; } *security_descriptor_values = safe_security_descriptor_values; result = 1; } else if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 ) { index_entry_offset = (off64_t) ( index_value->sub_node_vcn * security_descriptor_index->sii_index->io_handle->cluster_block_size ); if( libfsntfs_index_get_sub_node( security_descriptor_index->sii_index, file_io_handle, security_descriptor_index->sii_index->index_node_cache, index_entry_offset, (int) index_value->sub_node_vcn, &sub_node, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve sub node with VCN: %d at offset: 0x%08" PRIx64 ".", function, (int) index_value->sub_node_vcn, index_entry_offset ); goto on_error; } result = libfsntfs_security_descriptor_index_get_entry_from_index_node_by_identifier( security_descriptor_index, file_io_handle, security_descriptor_index->sii_index->root_node, security_descriptor_identifier, security_descriptor_values, recursion_depth + 1, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to retrieve security descriptor by identifier from index entry with VCN: %d at offset: 0x%08" PRIx64 ".", function, (int) index_value->sub_node_vcn, index_entry_offset ); goto on_error; } } return( result ); on_error: if( safe_security_descriptor_values != NULL ) { libfsntfs_security_descriptor_values_free( &safe_security_descriptor_values, NULL ); } if( security_descriptor_index_value != NULL ) { libfsntfs_security_descriptor_index_value_free( &security_descriptor_index_value, NULL ); } return( -1 ); } /* Retrieves the security descriptor for a specific identifier * This function creates new security descriptor values * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_security_descriptor_index_get_entry_by_identifier( libfsntfs_security_descriptor_index_t *security_descriptor_index, libbfio_handle_t *file_io_handle, uint32_t security_descriptor_identifier, libfsntfs_security_descriptor_values_t **security_descriptor_values, libcerror_error_t **error ) { static char *function = "libfsntfs_security_descriptor_index_get_entry_by_identifier"; int result = 0; if( security_descriptor_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor index.", function ); return( -1 ); } result = libfsntfs_security_descriptor_index_get_entry_from_index_node_by_identifier( security_descriptor_index, file_io_handle, security_descriptor_index->sii_index->root_node, security_descriptor_identifier, security_descriptor_values, 0, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve security descriptor by identifier.", function ); return( -1 ); } return( result ); } ================================================ FILE: libfsntfs/libfsntfs_security_descriptor_index.h ================================================ /* * Security descriptor index functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_SECURITY_DESCRIPTOR_INDEX_H ) #define _LIBFSNTFS_SECURITY_DESCRIPTOR_INDEX_H #include #include #include "libfsntfs_data_stream.h" #include "libfsntfs_index.h" #include "libfsntfs_index_node.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_mft_entry.h" #include "libfsntfs_security_descriptor_values.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_security_descriptor_index libfsntfs_security_descriptor_index_t; struct libfsntfs_security_descriptor_index { /* The $SII index */ libfsntfs_index_t *sii_index; /* The $SDS data stream */ libfsntfs_data_stream_t *data_stream; }; int libfsntfs_security_descriptor_index_initialize( libfsntfs_security_descriptor_index_t **security_descriptor_index, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfsntfs_mft_attribute_t *data_attribute, libcerror_error_t **error ); int libfsntfs_security_descriptor_index_free( libfsntfs_security_descriptor_index_t **security_descriptor_index, libcerror_error_t **error ); int libfsntfs_security_descriptor_index_read_sii_index( libfsntfs_security_descriptor_index_t *security_descriptor_index, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfsntfs_mft_entry_t *mft_entry, libcerror_error_t **error ); int libfsntfs_security_descriptor_index_get_entry_from_index_node_by_identifier( libfsntfs_security_descriptor_index_t *security_descriptor_index, libbfio_handle_t *file_io_handle, libfsntfs_index_node_t *index_node, uint32_t security_descriptor_identifier, libfsntfs_security_descriptor_values_t **security_descriptor_values, int recursion_depth, libcerror_error_t **error ); int libfsntfs_security_descriptor_index_get_entry_by_identifier( libfsntfs_security_descriptor_index_t *security_descriptor_index, libbfio_handle_t *file_io_handle, uint32_t security_descriptor_identifier, libfsntfs_security_descriptor_values_t **security_descriptor_values, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_SECURITY_DESCRIPTOR_INDEX_H ) */ ================================================ FILE: libfsntfs/libfsntfs_security_descriptor_index_value.c ================================================ /* * Security descriptor index value functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_libcdata.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_security_descriptor_index_value.h" #include "fsntfs_secure.h" /* Creates security descriptor index value * Make sure the value security_descriptor_index_value is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_security_descriptor_index_value_initialize( libfsntfs_security_descriptor_index_value_t **security_descriptor_index_value, libcerror_error_t **error ) { static char *function = "libfsntfs_security_descriptor_index_value_initialize"; if( security_descriptor_index_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor index value.", function ); return( -1 ); } if( *security_descriptor_index_value != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid security descriptor index value already set.", function ); return( -1 ); } *security_descriptor_index_value = memory_allocate_structure( libfsntfs_security_descriptor_index_value_t ); if( *security_descriptor_index_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create security descriptor index value.", function ); goto on_error; } if( memory_set( *security_descriptor_index_value, 0, sizeof( libfsntfs_security_descriptor_index_value_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear security descriptor index value.", function ); goto on_error; } return( 1 ); on_error: if( *security_descriptor_index_value != NULL ) { memory_free( *security_descriptor_index_value ); *security_descriptor_index_value = NULL; } return( -1 ); } /* Frees security descriptor index value * Returns 1 if successful or -1 on error */ int libfsntfs_security_descriptor_index_value_free( libfsntfs_security_descriptor_index_value_t **security_descriptor_index_value, libcerror_error_t **error ) { static char *function = "libfsntfs_security_descriptor_index_value_free"; if( security_descriptor_index_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor index value.", function ); return( -1 ); } if( *security_descriptor_index_value != NULL ) { memory_free( *security_descriptor_index_value ); *security_descriptor_index_value = NULL; } return( 1 ); } /* Compares 2 security descriptor index value by the identifier * Returns LIBCDATA_COMPARE_LESS, LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error */ int libfsntfs_security_descriptor_index_value_compare( libfsntfs_security_descriptor_index_value_t *first_security_descriptor_index_value, libfsntfs_security_descriptor_index_value_t *second_security_descriptor_index_value, libcerror_error_t **error ) { static char *function = "libfsntfs_security_descriptor_index_value_compare"; if( first_security_descriptor_index_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid first security descriptor index value.", function ); return( -1 ); } if( second_security_descriptor_index_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid second security descriptor index value.", function ); return( -1 ); } if( first_security_descriptor_index_value->identifier < second_security_descriptor_index_value->identifier ) { return( LIBCDATA_COMPARE_LESS ); } else if( first_security_descriptor_index_value->identifier > second_security_descriptor_index_value->identifier ) { return( LIBCDATA_COMPARE_GREATER ); } return( LIBCDATA_COMPARE_EQUAL ); } /* Reads the security descriptor index value * Returns 1 if successful or -1 on error */ int libfsntfs_security_descriptor_index_value_read_data( libfsntfs_security_descriptor_index_value_t *security_descriptor_index_value, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_security_descriptor_index_value_read_data"; if( security_descriptor_index_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor index value.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: security descriptor index value data:\n", function ); libcnotify_print_data( data, data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif if( data_size != sizeof( fsntfs_secure_index_value_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported security descriptor index value data size: %" PRIzd "\n", function, data_size ); return( -1 ); } byte_stream_copy_to_uint32_little_endian( ( (fsntfs_secure_index_value_t *) data )->hash, security_descriptor_index_value->hash ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_secure_index_value_t *) data )->identifier, security_descriptor_index_value->identifier ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_secure_index_value_t *) data )->data_offset, security_descriptor_index_value->data_offset ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_secure_index_value_t *) data )->data_size, security_descriptor_index_value->data_size ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: hash\t\t: 0x%08" PRIx32 "\n", function, security_descriptor_index_value->hash ); libcnotify_printf( "%s: identifier\t\t\t: %" PRIu32 "\n", function, security_descriptor_index_value->identifier ); libcnotify_printf( "%s: data offset\t: 0x%08" PRIx64 "\n", function, security_descriptor_index_value->data_offset ); libcnotify_printf( "%s: data size\t\t\t: %" PRIu32 "\n", function, security_descriptor_index_value->data_size ); libcnotify_printf( "\n" ); } #endif return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_security_descriptor_index_value.h ================================================ /* * Security descriptor index value functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_SECURITY_DESCRIPTOR_INDEX_VALUE_H ) #define _LIBFSNTFS_SECURITY_DESCRIPTOR_INDEX_VALUE_H #include #include #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_security_descriptor_index_value libfsntfs_security_descriptor_index_value_t; struct libfsntfs_security_descriptor_index_value { /* The hash */ uint32_t hash; /* The identifier */ uint32_t identifier; /* The data offset */ uint64_t data_offset; /* The data size */ uint32_t data_size; }; int libfsntfs_security_descriptor_index_value_initialize( libfsntfs_security_descriptor_index_value_t **security_descriptor_index_value, libcerror_error_t **error ); int libfsntfs_security_descriptor_index_value_free( libfsntfs_security_descriptor_index_value_t **security_descriptor_index_value, libcerror_error_t **error ); int libfsntfs_security_descriptor_index_value_compare( libfsntfs_security_descriptor_index_value_t *first_security_descriptor_index_value, libfsntfs_security_descriptor_index_value_t *second_security_descriptor_index_value, libcerror_error_t **error ); int libfsntfs_security_descriptor_index_value_read_data( libfsntfs_security_descriptor_index_value_t *security_descriptor_index_value, const uint8_t *data, size_t data_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_SECURITY_DESCRIPTOR_INDEX_VALUE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_security_descriptor_values.c ================================================ /* * Security descriptor attribute ($SECURITY_DESCRIPTOR) values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_cluster_block_stream.h" #include "libfsntfs_definitions.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_libfwnt.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_security_descriptor_values.h" /* Creates security descriptor values * Make sure the value security_descriptor_values is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_security_descriptor_values_initialize( libfsntfs_security_descriptor_values_t **security_descriptor_values, libcerror_error_t **error ) { static char *function = "libfsntfs_security_descriptor_values_initialize"; if( security_descriptor_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor values.", function ); return( -1 ); } if( *security_descriptor_values != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid security descriptor values value already set.", function ); return( -1 ); } *security_descriptor_values = memory_allocate_structure( libfsntfs_security_descriptor_values_t ); if( *security_descriptor_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create security descriptor values.", function ); goto on_error; } if( memory_set( *security_descriptor_values, 0, sizeof( libfsntfs_security_descriptor_values_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear security descriptor values.", function ); goto on_error; } return( 1 ); on_error: if( *security_descriptor_values != NULL ) { memory_free( *security_descriptor_values ); *security_descriptor_values = NULL; } return( -1 ); } /* Frees security descriptor values * Returns 1 if successful or -1 on error */ int libfsntfs_security_descriptor_values_free( libfsntfs_security_descriptor_values_t **security_descriptor_values, libcerror_error_t **error ) { static char *function = "libfsntfs_security_descriptor_values_free"; if( security_descriptor_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor values.", function ); return( -1 ); } if( *security_descriptor_values != NULL ) { if( ( *security_descriptor_values )->data != NULL ) { memory_free( ( *security_descriptor_values )->data ); } memory_free( *security_descriptor_values ); *security_descriptor_values = NULL; } return( 1 ); } /* Reads the security descriptor values * Returns 1 if successful or -1 on error */ int libfsntfs_security_descriptor_values_read_data( libfsntfs_security_descriptor_values_t *security_descriptor_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_security_descriptor_values_read_data"; #if defined( HAVE_DEBUG_OUTPUT ) libfwnt_security_descriptor_t *security_descriptor = NULL; #endif if( security_descriptor_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor values.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid data size value exceeds maximum.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: security descriptor data:\n", function ); libcnotify_print_data( data, data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( libfwnt_security_descriptor_initialize( &security_descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create security descriptor.", function ); goto on_error; } if( libfwnt_security_descriptor_copy_from_byte_stream( security_descriptor, data, data_size, LIBFWNT_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy security descriptor from byte stream.", function ); goto on_error; } if( libfwnt_security_descriptor_free( &security_descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free security descriptor.", function ); goto on_error; } libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ return( 1 ); #if defined( HAVE_DEBUG_OUTPUT ) on_error: if( security_descriptor != NULL ) { libfwnt_security_descriptor_free( &security_descriptor, NULL ); } return( -1 ); #endif } /* Reads the security descriptor values from the buffer * Returns 1 if successful or -1 on error */ int libfsntfs_security_descriptor_values_read_buffer( libfsntfs_security_descriptor_values_t *security_descriptor_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_security_descriptor_values_read_buffer"; if( security_descriptor_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor values.", function ); return( -1 ); } if( security_descriptor_values->data != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid security descriptor values - data already set.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data.", function ); return( -1 ); } if( ( data_size < 20 ) || ( data_size > MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: invalid security descriptor data size value out of bounds.", function ); goto on_error; } security_descriptor_values->data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * data_size ); if( security_descriptor_values->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create data.", function ); goto on_error; } security_descriptor_values->data_size = data_size; if( memory_copy( security_descriptor_values->data, data, data_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to copy data.", function ); goto on_error; } if( libfsntfs_security_descriptor_values_read_data( security_descriptor_values, security_descriptor_values->data, security_descriptor_values->data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read security descriptor values.", function ); goto on_error; } return( 1 ); on_error: if( security_descriptor_values->data != NULL ) { memory_free( security_descriptor_values->data ); security_descriptor_values->data = NULL; } security_descriptor_values->data_size = 0; return( -1 ); } /* Reads the security descriptor values from the data stream * Returns 1 if successful or -1 on error */ int libfsntfs_security_descriptor_values_read_stream( libfsntfs_security_descriptor_values_t *security_descriptor_values, libbfio_handle_t *file_io_handle, libfdata_stream_t *data_stream, libcerror_error_t **error ) { static char *function = "libfsntfs_security_descriptor_values_read_stream"; size64_t data_size = 0; ssize_t read_count = 0; if( security_descriptor_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor values.", function ); return( -1 ); } if( security_descriptor_values->data != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid security descriptor values - data already set.", function ); return( -1 ); } if( libfdata_stream_get_size( data_stream, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data stream size.", function ); goto on_error; } if( ( data_size < 20 ) || ( data_size > MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: invalid security descriptor data size value out of bounds.", function ); goto on_error; } security_descriptor_values->data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * (size_t) data_size ); if( security_descriptor_values->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create data.", function ); goto on_error; } security_descriptor_values->data_size = (size_t) data_size; read_count = libfdata_stream_read_buffer( data_stream, (intptr_t *) file_io_handle, security_descriptor_values->data, security_descriptor_values->data_size, 0, error ); if( read_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read security descriptor data.", function ); goto on_error; } if( libfsntfs_security_descriptor_values_read_data( security_descriptor_values, security_descriptor_values->data, security_descriptor_values->data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read security descriptor values.", function ); goto on_error; } return( 1 ); on_error: if( security_descriptor_values->data != NULL ) { memory_free( security_descriptor_values->data ); security_descriptor_values->data = NULL; } security_descriptor_values->data_size = 0; return( -1 ); } /* Reads the security descriptor values from an MFT attribute * Returns 1 if successful or -1 on error */ int libfsntfs_security_descriptor_values_read_from_mft_attribute( libfsntfs_security_descriptor_values_t *security_descriptor_values, libfsntfs_mft_attribute_t *mft_attribute, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, uint8_t flags, libcerror_error_t **error ) { libfdata_stream_t *cluster_block_stream = NULL; uint8_t *data = NULL; static char *function = "libfsntfs_security_descriptor_values_read_from_mft_attribute"; size_t data_size = 0; uint32_t attribute_type = 0; uint16_t attribute_data_flags = 0; int result = 0; if( security_descriptor_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor values.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_type( mft_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve type from attribute.", function ); goto on_error; } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_SECURITY_DESCRIPTOR ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); goto on_error; } result = libfsntfs_mft_attribute_data_is_resident( mft_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if attribute data is resident.", function ); goto on_error; } else if( result != 0 ) { if( libfsntfs_mft_attribute_get_resident_data( mft_attribute, &data, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve resident data from attribute.", function ); goto on_error; } if( libfsntfs_security_descriptor_values_read_buffer( security_descriptor_values, data, data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read security descriptor values.", function ); goto on_error; } } else if( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) == 0 ) { if( libfsntfs_mft_attribute_get_data_flags( mft_attribute, &attribute_data_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data flags.", function ); goto on_error; } if( ( attribute_data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported compressed attribute data.", function ); goto on_error; } if( libfsntfs_cluster_block_stream_initialize( &cluster_block_stream, io_handle, mft_attribute, NULL, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create cluster block stream.", function ); goto on_error; } if( libfsntfs_security_descriptor_values_read_stream( security_descriptor_values, file_io_handle, cluster_block_stream, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read security descriptor values from stream.", function ); goto on_error; } if( libfdata_stream_free( &cluster_block_stream, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free cluster block stream.", function ); goto on_error; } } return( 1 ); on_error: if( cluster_block_stream != NULL ) { libfdata_stream_free( &cluster_block_stream, NULL ); } return( -1 ); } /* Retrieves the security descriptor data size * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_security_descriptor_values_get_data_size( libfsntfs_security_descriptor_values_t *security_descriptor_values, size_t *data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_security_descriptor_values_get_data_size"; if( security_descriptor_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor values.", function ); return( -1 ); } if( data_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data size.", function ); return( -1 ); } if( security_descriptor_values->data == NULL ) { return( 0 ); } *data_size = security_descriptor_values->data_size; return( 1 ); } /* Retrieves the security descriptor data size * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_security_descriptor_values_get_data( libfsntfs_security_descriptor_values_t *security_descriptor_values, uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_security_descriptor_values_get_data"; if( security_descriptor_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor values.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid data size value exceeds maximum.", function ); return( -1 ); } if( data_size < security_descriptor_values->data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } if( security_descriptor_values->data == NULL ) { return( 0 ); } if( memory_copy( data, security_descriptor_values->data, security_descriptor_values->data_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to copy security descriptor data.", function ); return( -1 ); } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_security_descriptor_values.h ================================================ /* * Security descriptor attribute ($SECURITY_DESCRIPTOR) values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_SECURITY_DESCRIPTOR_VALUES_H ) #define _LIBFSNTFS_SECURITY_DESCRIPTOR_VALUES_H #include #include #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_attribute.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_security_descriptor_values libfsntfs_security_descriptor_values_t; struct libfsntfs_security_descriptor_values { /* The data */ uint8_t *data; /* The data size */ size_t data_size; }; int libfsntfs_security_descriptor_values_initialize( libfsntfs_security_descriptor_values_t **security_descriptor_values, libcerror_error_t **error ); int libfsntfs_security_descriptor_values_free( libfsntfs_security_descriptor_values_t **security_descriptor_values, libcerror_error_t **error ); int libfsntfs_security_descriptor_values_read_data( libfsntfs_security_descriptor_values_t *security_descriptor_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_security_descriptor_values_read_buffer( libfsntfs_security_descriptor_values_t *security_descriptor_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_security_descriptor_values_read_stream( libfsntfs_security_descriptor_values_t *security_descriptor_values, libbfio_handle_t *file_io_handle, libfdata_stream_t *data_stream, libcerror_error_t **error ); int libfsntfs_security_descriptor_values_read_from_mft_attribute( libfsntfs_security_descriptor_values_t *security_descriptor_values, libfsntfs_mft_attribute_t *mft_attribute, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, uint8_t flags, libcerror_error_t **error ); int libfsntfs_security_descriptor_values_get_data_size( libfsntfs_security_descriptor_values_t *security_descriptor_values, size_t *data_size, libcerror_error_t **error ); int libfsntfs_security_descriptor_values_get_data( libfsntfs_security_descriptor_values_t *security_descriptor_values, uint8_t *data, size_t data_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_SECURITY_DESCRIPTOR_VALUES_H ) */ ================================================ FILE: libfsntfs/libfsntfs_standard_information_attribute.c ================================================ /* * Standard information attribute ($STANDARD_INFORMATION) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_attribute.h" #include "libfsntfs_definitions.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_standard_information_attribute.h" #include "libfsntfs_standard_information_values.h" #include "libfsntfs_types.h" /* Retrieves the creation date and time * Returns 1 if successful or -1 on error */ int libfsntfs_standard_information_attribute_get_creation_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; static char *function = "libfsntfs_standard_information_attribute_get_creation_time"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( internal_attribute->value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid attribute - missing value.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } standard_information_values = (libfsntfs_standard_information_values_t *) internal_attribute->value; if( filetime == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid FILETIME.", function ); return( -1 ); } *filetime = standard_information_values->creation_time; return( 1 ); } /* Retrieves the (file) modification (last written) date and time * Returns 1 if successful or -1 on error */ int libfsntfs_standard_information_attribute_get_modification_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; static char *function = "libfsntfs_standard_information_attribute_get_modification_time"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( internal_attribute->value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid attribute - missing value.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } standard_information_values = (libfsntfs_standard_information_values_t *) internal_attribute->value; if( filetime == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid FILETIME.", function ); return( -1 ); } *filetime = standard_information_values->modification_time; return( 1 ); } /* Retrieves the access date and time * Returns 1 if successful or -1 on error */ int libfsntfs_standard_information_attribute_get_access_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; static char *function = "libfsntfs_standard_information_attribute_get_access_time"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( internal_attribute->value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid attribute - missing value.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } standard_information_values = (libfsntfs_standard_information_values_t *) internal_attribute->value; if( filetime == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid FILETIME.", function ); return( -1 ); } *filetime = standard_information_values->access_time; return( 1 ); } /* Retrieves the (file system entry) modification date and time * Returns 1 if successful or -1 on error */ int libfsntfs_standard_information_attribute_get_entry_modification_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; static char *function = "libfsntfs_standard_information_attribute_get_entry_modification_time"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( internal_attribute->value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid attribute - missing value.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } standard_information_values = (libfsntfs_standard_information_values_t *) internal_attribute->value; if( filetime == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid FILETIME.", function ); return( -1 ); } *filetime = standard_information_values->entry_modification_time; return( 1 ); } /* Retrieves the file attribute flags * Returns 1 if successful or -1 on error */ int libfsntfs_standard_information_attribute_get_file_attribute_flags( libfsntfs_attribute_t *attribute, uint32_t *file_attribute_flags, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; static char *function = "libfsntfs_standard_information_attribute_get_file_attribute_flags"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( internal_attribute->value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid attribute - missing value.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } standard_information_values = (libfsntfs_standard_information_values_t *) internal_attribute->value; if( file_attribute_flags == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file attribute flags.", function ); return( -1 ); } *file_attribute_flags = standard_information_values->file_attribute_flags; return( 1 ); } /* Retrieves the owner identifier * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_standard_information_attribute_get_owner_identifier( libfsntfs_attribute_t *attribute, uint32_t *owner_identifier, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; static char *function = "libfsntfs_standard_information_attribute_get_owner_identifier"; uint64_t attribute_data_size = 0; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( internal_attribute->value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid attribute - missing value.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } standard_information_values = (libfsntfs_standard_information_values_t *) internal_attribute->value; if( owner_identifier == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid owner identifier.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_data_size( internal_attribute, &attribute_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data from attribute.", function ); return( -1 ); } if( attribute_data_size < 72 ) { return( 0 ); } *owner_identifier = standard_information_values->owner_identifier; return( 1 ); } /* Retrieves the security descriptor identifier * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_standard_information_attribute_get_security_descriptor_identifier( libfsntfs_attribute_t *attribute, uint32_t *security_descriptor_identifier, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; static char *function = "libfsntfs_standard_information_attribute_get_security_descriptor_identifier"; uint64_t attribute_data_size = 0; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( internal_attribute->value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid attribute - missing value.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } standard_information_values = (libfsntfs_standard_information_values_t *) internal_attribute->value; if( security_descriptor_identifier == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor identifier.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_data_size( internal_attribute, &attribute_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data from attribute.", function ); return( -1 ); } if( attribute_data_size < 72 ) { return( 0 ); } *security_descriptor_identifier = standard_information_values->security_descriptor_identifier; return( 1 ); } /* Retrieves the update sequence number (USN) * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_standard_information_attribute_get_update_sequence_number( libfsntfs_attribute_t *attribute, uint64_t *update_sequence_number, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; static char *function = "libfsntfs_standard_information_attribute_get_update_sequence_number"; uint64_t attribute_data_size = 0; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( internal_attribute->value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid attribute - missing value.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } standard_information_values = (libfsntfs_standard_information_values_t *) internal_attribute->value; if( update_sequence_number == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid update sequence number (USN).", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_data_size( internal_attribute, &attribute_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve data from attribute.", function ); return( -1 ); } if( attribute_data_size < 72 ) { return( 0 ); } *update_sequence_number = standard_information_values->update_sequence_number; return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_standard_information_attribute.h ================================================ /* * Standard information attribute ($STANDARD_INFORMATION) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_STANDARD_INFORMATION_ATTRIBUTE_H ) #define _LIBFSNTFS_STANDARD_INFORMATION_ATTRIBUTE_H #include #include #include "libfsntfs_extern.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_types.h" #if defined( __cplusplus ) extern "C" { #endif LIBFSNTFS_EXTERN \ int libfsntfs_standard_information_attribute_get_creation_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_standard_information_attribute_get_modification_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_standard_information_attribute_get_access_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_standard_information_attribute_get_entry_modification_time( libfsntfs_attribute_t *attribute, uint64_t *filetime, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_standard_information_attribute_get_file_attribute_flags( libfsntfs_attribute_t *attribute, uint32_t *file_attribute_flags, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_standard_information_attribute_get_owner_identifier( libfsntfs_attribute_t *attribute, uint32_t *owner_identifier, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_standard_information_attribute_get_security_descriptor_identifier( libfsntfs_attribute_t *attribute, uint32_t *security_descriptor_identifier, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_standard_information_attribute_get_update_sequence_number( libfsntfs_attribute_t *attribute, uint64_t *update_sequence_number, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_STANDARD_INFORMATION_ATTRIBUTE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_standard_information_values.c ================================================ /* * Standard information attribute ($STANDARAD_INFORMATION) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include "libfsntfs_debug.h" #include "libfsntfs_definitions.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libfdatetime.h" #include "libfsntfs_standard_information_values.h" #include "fsntfs_standard_information.h" /* Creates standard information values * Make sure the value standard_information_values is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_standard_information_values_initialize( libfsntfs_standard_information_values_t **standard_information_values, libcerror_error_t **error ) { static char *function = "libfsntfs_standard_information_values_initialize"; if( standard_information_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid standard information values.", function ); return( -1 ); } if( *standard_information_values != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid standard information values value already set.", function ); return( -1 ); } *standard_information_values = memory_allocate_structure( libfsntfs_standard_information_values_t ); if( *standard_information_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create standard information values.", function ); goto on_error; } if( memory_set( *standard_information_values, 0, sizeof( libfsntfs_standard_information_values_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear standard information values.", function ); goto on_error; } return( 1 ); on_error: if( *standard_information_values != NULL ) { memory_free( *standard_information_values ); *standard_information_values = NULL; } return( -1 ); } /* Frees standard information values * Returns 1 if successful or -1 on error */ int libfsntfs_standard_information_values_free( libfsntfs_standard_information_values_t **standard_information_values, libcerror_error_t **error ) { static char *function = "libfsntfs_standard_information_values_free"; if( standard_information_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid standard information values.", function ); return( -1 ); } if( *standard_information_values != NULL ) { memory_free( *standard_information_values ); *standard_information_values = NULL; } return( 1 ); } /* Reads the standard information values * Returns 1 if successful or -1 on error */ int libfsntfs_standard_information_values_read_data( libfsntfs_standard_information_values_t *standard_information_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_standard_information_values_read_data"; uint32_t maximum_number_of_versions = 0; uint32_t version_number = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint64_t value_64bit = 0; uint32_t value_32bit = 0; #endif if( standard_information_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid standard information values.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: standard information data:\n", function ); libcnotify_print_data( data, data_size, 0 ); } #endif if( ( data_size != 48 ) && ( data_size != 72 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported standard information data size: %" PRIzd "\n", function, data_size ); return( -1 ); } byte_stream_copy_to_uint64_little_endian( ( (fsntfs_standard_information_t *) data )->creation_time, standard_information_values->creation_time ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_standard_information_t *) data )->modification_time, standard_information_values->modification_time ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_standard_information_t *) data )->access_time, standard_information_values->access_time ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_standard_information_t *) data )->entry_modification_time, standard_information_values->entry_modification_time ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_standard_information_t *) data )->file_attribute_flags, standard_information_values->file_attribute_flags ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_standard_information_t *) data )->maximum_number_of_versions, maximum_number_of_versions ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_standard_information_t *) data )->version_number, version_number ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( libfsntfs_debug_print_filetime_value( function, "creation time\t\t\t", ( (fsntfs_standard_information_t *) data )->creation_time, 8, LIBFDATETIME_ENDIAN_LITTLE, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print filetime value.", function ); return( -1 ); } if( libfsntfs_debug_print_filetime_value( function, "modification time\t\t", ( (fsntfs_standard_information_t *) data )->modification_time, 8, LIBFDATETIME_ENDIAN_LITTLE, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print filetime value.", function ); return( -1 ); } if( libfsntfs_debug_print_filetime_value( function, "entry modification time\t", ( (fsntfs_standard_information_t *) data )->entry_modification_time, 8, LIBFDATETIME_ENDIAN_LITTLE, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print filetime value.", function ); return( -1 ); } if( libfsntfs_debug_print_filetime_value( function, "access time\t\t\t", ( (fsntfs_standard_information_t *) data )->access_time, 8, LIBFDATETIME_ENDIAN_LITTLE, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print filetime value.", function ); return( -1 ); } libcnotify_printf( "%s: file attribute flags\t\t: 0x%08" PRIx32 "\n", function, standard_information_values->file_attribute_flags ); libfsntfs_debug_print_file_attribute_flags( standard_information_values->file_attribute_flags ); libcnotify_printf( "\n" ); libcnotify_printf( "%s: maximum number of versions\t: %" PRIu32 "\n", function, maximum_number_of_versions ); libcnotify_printf( "%s: version number\t\t\t: %" PRIu32 "\n", function, version_number ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_standard_information_t *) data )->class_identifier, value_32bit ); libcnotify_printf( "%s: class identifier\t\t: %" PRIu32 "\n", function, value_32bit ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ if( ( maximum_number_of_versions == 0 ) && ( version_number == 1 ) ) { standard_information_values->is_case_sensitive = 1; } if( data_size > 48 ) { byte_stream_copy_to_uint32_little_endian( ( (fsntfs_standard_information_t *) data )->owner_identifier, standard_information_values->owner_identifier ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_standard_information_t *) data )->security_descriptor_identifier, standard_information_values->security_descriptor_identifier ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_standard_information_t *) data )->update_sequence_number, standard_information_values->update_sequence_number ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: owner identifier\t\t: %" PRIu32 "\n", function, standard_information_values->owner_identifier ); libcnotify_printf( "%s: security descriptor identifier\t: %" PRIu32 "\n", function, standard_information_values->security_descriptor_identifier ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_standard_information_t *) data )->quota_charged, value_64bit ); libcnotify_printf( "%s: quota charged\t\t\t: %" PRIu64 "\n", function, value_64bit ); libcnotify_printf( "%s: update sequence number\t\t: %" PRIu64 "\n", function, standard_information_values->update_sequence_number ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "\n" ); } #endif return( 1 ); } /* Reads the standard information values from an MFT attribute * Returns 1 if successful or -1 on error */ int libfsntfs_standard_information_values_read_from_mft_attribute( libfsntfs_standard_information_values_t *standard_information_values, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ) { uint8_t *data = NULL; static char *function = "libfsntfs_standard_information_values_read_from_mft_attribute"; size_t data_size = 0; uint32_t attribute_type = 0; int result = 0; if( standard_information_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid standard information values.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_type( mft_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve type from attribute.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_mft_attribute_data_is_resident( mft_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if attribute data is resident.", function ); return( -1 ); } else if( result == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported non-resident attribute.", function ); return( 1 ); } if( libfsntfs_mft_attribute_get_resident_data( mft_attribute, &data, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve resident data from attribute.", function ); return( -1 ); } if( libfsntfs_standard_information_values_read_data( standard_information_values, data, data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read standard information values.", function ); return( -1 ); } return( 1 ); } /* Retrieves the creation date and time * Returns 1 if successful or -1 on error */ int libfsntfs_standard_information_values_get_creation_time( libfsntfs_standard_information_values_t *standard_information_values, uint64_t *filetime, libcerror_error_t **error ) { static char *function = "libfsntfs_standard_information_values_get_creation_time"; if( standard_information_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid standard information values.", function ); return( -1 ); } if( filetime == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid FILETIME.", function ); return( -1 ); } *filetime = standard_information_values->creation_time; return( 1 ); } /* Retrieves the (file) modification (last written) date and time * Returns 1 if successful or -1 on error */ int libfsntfs_standard_information_values_get_modification_time( libfsntfs_standard_information_values_t *standard_information_values, uint64_t *filetime, libcerror_error_t **error ) { static char *function = "libfsntfs_standard_information_values_get_modification_time"; if( standard_information_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid standard information values.", function ); return( -1 ); } if( filetime == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid FILETIME.", function ); return( -1 ); } *filetime = standard_information_values->modification_time; return( 1 ); } /* Retrieves the access date and time * Returns 1 if successful or -1 on error */ int libfsntfs_standard_information_values_get_access_time( libfsntfs_standard_information_values_t *standard_information_values, uint64_t *filetime, libcerror_error_t **error ) { static char *function = "libfsntfs_standard_information_values_get_access_time"; if( standard_information_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid standard information values.", function ); return( -1 ); } if( filetime == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid FILETIME.", function ); return( -1 ); } *filetime = standard_information_values->access_time; return( 1 ); } /* Retrieves the (file system entry) modification date and time * Returns 1 if successful or -1 on error */ int libfsntfs_standard_information_values_get_entry_modification_time( libfsntfs_standard_information_values_t *standard_information_values, uint64_t *filetime, libcerror_error_t **error ) { static char *function = "libfsntfs_standard_information_values_get_entry_modification_time"; if( standard_information_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid standard information values.", function ); return( -1 ); } if( filetime == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid FILETIME.", function ); return( -1 ); } *filetime = standard_information_values->entry_modification_time; return( 1 ); } /* Retrieves the file attribute flags * Returns 1 if successful or -1 on error */ int libfsntfs_standard_information_values_get_file_attribute_flags( libfsntfs_standard_information_values_t *standard_information_values, uint32_t *file_attribute_flags, libcerror_error_t **error ) { static char *function = "libfsntfs_standard_information_values_get_file_attribute_flags"; if( standard_information_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid standard information values.", function ); return( -1 ); } if( file_attribute_flags == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file attribute flags.", function ); return( -1 ); } *file_attribute_flags = standard_information_values->file_attribute_flags; return( 1 ); } /* Retrieves the security descriptor identifier * Returns 1 if successful or -1 on error */ int libfsntfs_standard_information_values_get_security_descriptor_identifier( libfsntfs_standard_information_values_t *standard_information_values, uint32_t *security_descriptor_identifier, libcerror_error_t **error ) { static char *function = "libfsntfs_standard_information_values_get_security_descriptor_identifier"; if( standard_information_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid standard information values.", function ); return( -1 ); } if( security_descriptor_identifier == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid security descriptor identifier.", function ); return( -1 ); } *security_descriptor_identifier = standard_information_values->security_descriptor_identifier; return( 1 ); } /* Retrieves the update sequence number * Returns 1 if successful or -1 on error */ int libfsntfs_standard_information_values_get_update_sequence_number( libfsntfs_standard_information_values_t *standard_information_values, uint64_t *update_sequence_number, libcerror_error_t **error ) { static char *function = "libfsntfs_standard_information_values_get_update_sequence_number"; if( standard_information_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid standard information values.", function ); return( -1 ); } if( update_sequence_number == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid update sequence number.", function ); return( -1 ); } *update_sequence_number = standard_information_values->update_sequence_number; return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_standard_information_values.h ================================================ /* * Standard information attribute ($STANDARD_INFORMATION) values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_STANDARD_INFORMATION_VALUES_H ) #define _LIBFSNTFS_STANDARD_INFORMATION_VALUES_H #include #include #include "libfsntfs_libcerror.h" #include "libfsntfs_mft_attribute.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_standard_information_values libfsntfs_standard_information_values_t; struct libfsntfs_standard_information_values { /* The creation time */ uint64_t creation_time; /* The modification time */ uint64_t modification_time; /* The access time */ uint64_t access_time; /* The entry modification time */ uint64_t entry_modification_time; /* The file attribute flags */ uint32_t file_attribute_flags; /* The owner identifier */ uint32_t owner_identifier; /* The security descriptor identifier */ uint32_t security_descriptor_identifier; /* The update sequence number (USN) */ uint64_t update_sequence_number; /* Value to indicate the is case sensitive flag is set */ uint8_t is_case_sensitive; }; int libfsntfs_standard_information_values_initialize( libfsntfs_standard_information_values_t **standard_information_values, libcerror_error_t **error ); int libfsntfs_standard_information_values_free( libfsntfs_standard_information_values_t **standard_information_values, libcerror_error_t **error ); int libfsntfs_standard_information_values_read_data( libfsntfs_standard_information_values_t *standard_information_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_standard_information_values_read_from_mft_attribute( libfsntfs_standard_information_values_t *standard_information_values, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ); int libfsntfs_standard_information_values_get_creation_time( libfsntfs_standard_information_values_t *standard_information_values, uint64_t *filetime, libcerror_error_t **error ); int libfsntfs_standard_information_values_get_modification_time( libfsntfs_standard_information_values_t *standard_information_values, uint64_t *filetime, libcerror_error_t **error ); int libfsntfs_standard_information_values_get_access_time( libfsntfs_standard_information_values_t *standard_information_values, uint64_t *filetime, libcerror_error_t **error ); int libfsntfs_standard_information_values_get_entry_modification_time( libfsntfs_standard_information_values_t *standard_information_values, uint64_t *filetime, libcerror_error_t **error ); int libfsntfs_standard_information_values_get_file_attribute_flags( libfsntfs_standard_information_values_t *standard_information_values, uint32_t *file_attribute_flags, libcerror_error_t **error ); int libfsntfs_standard_information_values_get_security_descriptor_identifier( libfsntfs_standard_information_values_t *standard_information_values, uint32_t *security_descriptor_identifier, libcerror_error_t **error ); int libfsntfs_standard_information_values_get_update_sequence_number( libfsntfs_standard_information_values_t *standard_information_values, uint64_t *update_sequence_number, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_STANDARD_INFORMATION_VALUES_H ) */ ================================================ FILE: libfsntfs/libfsntfs_support.c ================================================ /* * Support functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include "libfsntfs_definitions.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libclocale.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_support.h" #if !defined( HAVE_LOCAL_LIBFSNTFS ) /* Returns the library version */ const char *libfsntfs_get_version( void ) { return( (const char *) LIBFSNTFS_VERSION_STRING ); } /* Returns the access flags for reading */ int libfsntfs_get_access_flags_read( void ) { return( (int) LIBFSNTFS_ACCESS_FLAG_READ ); } /* Retrieves the narrow system string codepage * A value of 0 represents no codepage, UTF-8 encoding is used instead * Returns 1 if successful or -1 on error */ int libfsntfs_get_codepage( int *codepage, libcerror_error_t **error ) { static char *function = "libfsntfs_get_codepage"; if( libclocale_codepage_get( codepage, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve codepage.", function ); return( -1 ); } return( 1 ); } /* Sets the narrow system string codepage * A value of 0 represents no codepage, UTF-8 encoding is used instead * Returns 1 if successful or -1 on error */ int libfsntfs_set_codepage( int codepage, libcerror_error_t **error ) { static char *function = "libfsntfs_set_codepage"; if( libclocale_codepage_set( codepage, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set codepage.", function ); return( -1 ); } return( 1 ); } #endif /* !defined( HAVE_LOCAL_LIBFSNTFS ) */ /* Determines if a file contains a NTFS volume signature * Returns 1 if true, 0 if not or -1 on error */ int libfsntfs_check_volume_signature( const char *filename, libcerror_error_t **error ) { libbfio_handle_t *file_io_handle = NULL; static char *function = "libfsntfs_check_volume_signature"; size_t filename_length = 0; int result = 0; if( filename == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid filename.", function ); return( -1 ); } filename_length = narrow_string_length( filename ); if( filename_length == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid filename.", function ); goto on_error; } if( libbfio_file_initialize( &file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file IO handle.", function ); goto on_error; } if( libbfio_file_set_name( file_io_handle, filename, filename_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set filename in file IO handle.", function ); goto on_error; } result = libfsntfs_check_volume_signature_file_io_handle( file_io_handle, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to check file signature using a file handle.", function ); goto on_error; } if( libbfio_handle_free( &file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to free file IO handle.", function ); goto on_error; } return( result ); on_error: if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } return( -1 ); } #if defined( HAVE_WIDE_CHARACTER_TYPE ) /* Determines if a file contains a NTFS volume signature * Returns 1 if true, 0 if not or -1 on error */ int libfsntfs_check_volume_signature_wide( const wchar_t *filename, libcerror_error_t **error ) { libbfio_handle_t *file_io_handle = NULL; static char *function = "libfsntfs_check_volume_signature_wide"; size_t filename_length = 0; int result = 0; if( filename == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid filename.", function ); return( -1 ); } filename_length = wide_string_length( filename ); if( filename_length == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid filename.", function ); goto on_error; } if( libbfio_file_initialize( &file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file IO handle.", function ); goto on_error; } if( libbfio_file_set_name_wide( file_io_handle, filename, filename_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set filename in file IO handle.", function ); goto on_error; } result = libfsntfs_check_volume_signature_file_io_handle( file_io_handle, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to check file signature using a file handle.", function ); goto on_error; } if( libbfio_handle_free( &file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to free file IO handle.", function ); goto on_error; } return( result ); on_error: if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } return( -1 ); } #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */ /* Determines if a file contains a NTFS volume signature using a Basic File IO (bfio) handle * Returns 1 if true, 0 if not or -1 on error */ int libfsntfs_check_volume_signature_file_io_handle( libbfio_handle_t *file_io_handle, libcerror_error_t **error ) { uint8_t signature[ 12 ]; static char *function = "libfsntfs_check_volume_signature_file_io_handle"; ssize_t read_count = 0; int file_io_handle_is_open = 0; if( file_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file IO handle.", function ); return( -1 ); } file_io_handle_is_open = libbfio_handle_is_open( file_io_handle, error ); if( file_io_handle_is_open == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open file.", function ); goto on_error; } else if( file_io_handle_is_open == 0 ) { if( libbfio_handle_open( file_io_handle, LIBBFIO_OPEN_READ, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open file.", function ); goto on_error; } } read_count = libbfio_handle_read_buffer_at_offset( file_io_handle, signature, 12, 0, error ); if( read_count != 12 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read signature at offset: 0 (0x00000000).", function ); goto on_error; } if( file_io_handle_is_open == 0 ) { if( libbfio_handle_close( file_io_handle, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close file.", function ); goto on_error; } } if( memory_compare( fsntfs_volume_file_system_signature, &( signature[ 3 ] ), 8 ) == 0 ) { return( 1 ); } /* TODO also check sector signature ? */ return( 0 ); on_error: if( file_io_handle_is_open == 0 ) { libbfio_handle_close( file_io_handle, NULL ); } return( -1 ); } /* Determines if a file contains a NTFS MFT metadata file signature * Returns 1 if true, 0 if not or -1 on error */ int libfsntfs_check_mft_metadata_file_signature( const char *filename, libcerror_error_t **error ) { libbfio_handle_t *file_io_handle = NULL; static char *function = "libfsntfs_check_mft_metadata_file_signature"; size_t filename_length = 0; int result = 0; if( filename == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid filename.", function ); return( -1 ); } filename_length = narrow_string_length( filename ); if( filename_length == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid filename.", function ); goto on_error; } if( libbfio_file_initialize( &file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file IO handle.", function ); goto on_error; } if( libbfio_file_set_name( file_io_handle, filename, filename_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set filename in file IO handle.", function ); goto on_error; } result = libfsntfs_check_mft_metadata_file_signature_file_io_handle( file_io_handle, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to check file signature using a file handle.", function ); goto on_error; } if( libbfio_handle_free( &file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to free file IO handle.", function ); goto on_error; } return( result ); on_error: if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } return( -1 ); } #if defined( HAVE_WIDE_CHARACTER_TYPE ) /* Determines if a file contains a NTFS MFT metadata file signature * Returns 1 if true, 0 if not or -1 on error */ int libfsntfs_check_mft_metadata_file_signature_wide( const wchar_t *filename, libcerror_error_t **error ) { libbfio_handle_t *file_io_handle = NULL; static char *function = "libfsntfs_check_mft_metadata_file_signature_wide"; size_t filename_length = 0; int result = 0; if( filename == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid filename.", function ); return( -1 ); } filename_length = wide_string_length( filename ); if( filename_length == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid filename.", function ); goto on_error; } if( libbfio_file_initialize( &file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file IO handle.", function ); goto on_error; } if( libbfio_file_set_name_wide( file_io_handle, filename, filename_length, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set filename in file IO handle.", function ); goto on_error; } result = libfsntfs_check_mft_metadata_file_signature_file_io_handle( file_io_handle, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to check file signature using a file handle.", function ); goto on_error; } if( libbfio_handle_free( &file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to free file IO handle.", function ); goto on_error; } return( result ); on_error: if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } return( -1 ); } #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */ /* Determines if a file contains a NTFS MFT metadata file signature using a Basic File IO (bfio) handle * Returns 1 if true, 0 if not or -1 on error */ int libfsntfs_check_mft_metadata_file_signature_file_io_handle( libbfio_handle_t *file_io_handle, libcerror_error_t **error ) { uint8_t signature[ 4 ]; static char *function = "libfsntfs_check_mft_metadata_file_signature_file_io_handle"; ssize_t read_count = 0; int file_io_handle_is_open = 0; if( file_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file IO handle.", function ); return( -1 ); } file_io_handle_is_open = libbfio_handle_is_open( file_io_handle, error ); if( file_io_handle_is_open == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open file.", function ); goto on_error; } else if( file_io_handle_is_open == 0 ) { if( libbfio_handle_open( file_io_handle, LIBBFIO_OPEN_READ, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open file.", function ); goto on_error; } } read_count = libbfio_handle_read_buffer_at_offset( file_io_handle, signature, 4, 0, error ); if( read_count != 4 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read signature at offset: 0 (0x00000000).", function ); goto on_error; } if( file_io_handle_is_open == 0 ) { if( libbfio_handle_close( file_io_handle, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close file.", function ); goto on_error; } } if( memory_compare( "FILE", signature, 4 ) == 0 ) { return( 1 ); } return( 0 ); on_error: if( file_io_handle_is_open == 0 ) { libbfio_handle_close( file_io_handle, NULL ); } return( -1 ); } ================================================ FILE: libfsntfs/libfsntfs_support.h ================================================ /* * Support functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_SUPPORT_H ) #define _LIBFSNTFS_SUPPORT_H #include #include #include "libfsntfs_extern.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif #if !defined( HAVE_LOCAL_LIBFSNTFS ) LIBFSNTFS_EXTERN \ const char *libfsntfs_get_version( void ); LIBFSNTFS_EXTERN \ int libfsntfs_get_access_flags_read( void ); LIBFSNTFS_EXTERN \ int libfsntfs_get_codepage( int *codepage, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_set_codepage( int codepage, libcerror_error_t **error ); #endif /* !defined( HAVE_LOCAL_LIBFSNTFS ) */ LIBFSNTFS_EXTERN \ int libfsntfs_check_volume_signature( const char *filename, libcerror_error_t **error ); #if defined( HAVE_WIDE_CHARACTER_TYPE ) LIBFSNTFS_EXTERN \ int libfsntfs_check_volume_signature_wide( const wchar_t *filename, libcerror_error_t **error ); #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */ LIBFSNTFS_EXTERN \ int libfsntfs_check_volume_signature_file_io_handle( libbfio_handle_t *file_io_handle, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_check_mft_metadata_file_signature( const char *filename, libcerror_error_t **error ); #if defined( HAVE_WIDE_CHARACTER_TYPE ) LIBFSNTFS_EXTERN \ int libfsntfs_check_mft_metadata_file_signature_wide( const wchar_t *filename, libcerror_error_t **error ); #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */ LIBFSNTFS_EXTERN \ int libfsntfs_check_mft_metadata_file_signature_file_io_handle( libbfio_handle_t *file_io_handle, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_SUPPORT_H ) */ ================================================ FILE: libfsntfs/libfsntfs_txf_data_values.c ================================================ /* * The Transactional NTFS (TxF) data ($TXF_DATA) logged utility stream * attribute ($LOGGED_UTILITY_STREAM) values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_definitions.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_txf_data_values.h" #include "fsntfs_txf_data.h" /* Creates TxF data values * Make sure the value txf_data_values is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_txf_data_values_initialize( libfsntfs_txf_data_values_t **txf_data_values, libcerror_error_t **error ) { static char *function = "libfsntfs_txf_data_values_initialize"; if( txf_data_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid TxF data values.", function ); return( -1 ); } if( *txf_data_values != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid TxF data values value already set.", function ); return( -1 ); } *txf_data_values = memory_allocate_structure( libfsntfs_txf_data_values_t ); if( *txf_data_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create TxF data values.", function ); goto on_error; } if( memory_set( *txf_data_values, 0, sizeof( libfsntfs_txf_data_values_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear TxF data values.", function ); goto on_error; } return( 1 ); on_error: if( *txf_data_values != NULL ) { memory_free( *txf_data_values ); *txf_data_values = NULL; } return( -1 ); } /* Frees TxF data values * Returns 1 if successful or -1 on error */ int libfsntfs_txf_data_values_free( libfsntfs_txf_data_values_t **txf_data_values, libcerror_error_t **error ) { static char *function = "libfsntfs_txf_data_values_free"; if( txf_data_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid TxF data values.", function ); return( -1 ); } if( *txf_data_values != NULL ) { memory_free( *txf_data_values ); *txf_data_values = NULL; } return( 1 ); } /* Reads the TxF data values * Returns 1 if successful or -1 on error */ int libfsntfs_txf_data_values_read_data( libfsntfs_txf_data_values_t *txf_data_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_txf_data_values_read_data"; #if defined( HAVE_DEBUG_OUTPUT ) uint64_t value_64bit = 0; uint16_t value_16bit = 0; #endif if( txf_data_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid TxF data values.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: TxF data values:\n", function ); libcnotify_print_data( data, data_size, 0 ); } #endif if( data_size != sizeof( fsntfs_txf_data_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported TxF data values size: %" PRIzd "\n", function, data_size ); return( -1 ); } byte_stream_copy_to_uint64_little_endian( ( (fsntfs_txf_data_t *) data )->rm_root_file_reference, txf_data_values->rm_root_file_reference ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_txf_data_t *) data )->file_identifier, txf_data_values->file_identifier ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_txf_data_t *) data )->data_lsn, txf_data_values->data_lsn ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_txf_data_t *) data )->metadata_lsn, txf_data_values->metadata_lsn ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_txf_data_t *) data )->directory_index_lsn, txf_data_values->directory_index_lsn ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: unknown1:\n", function ); libcnotify_print_data( ( (fsntfs_txf_data_t *) data )->unknown1, 6, 0 ); libcnotify_printf( "%s: resource manager root file reference\t: %" PRIu64 "- %" PRIu64 "\n", function, txf_data_values->rm_root_file_reference & 0xffffffffffffUL, txf_data_values->rm_root_file_reference >> 48 ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_txf_data_t *) data )->usn_index, value_64bit ); libcnotify_printf( "%s: update sequence number index\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); libcnotify_printf( "%s: file identifier\t\t\t\t: 0x%08" PRIx64 "\n", function, txf_data_values->file_identifier ); libcnotify_printf( "%s: data log sequence number\t\t\t: 0x%08" PRIx64 "\n", function, txf_data_values->data_lsn ); libcnotify_printf( "%s: metadata log sequence number\t\t: 0x%08" PRIx64 "\n", function, txf_data_values->metadata_lsn ); libcnotify_printf( "%s: directory index log sequence number\t: 0x%08" PRIx64 "\n", function, txf_data_values->directory_index_lsn ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_txf_data_t *) data )->flags, value_16bit ); libcnotify_printf( "%s: flags\t\t\t\t\t: 0x%04" PRIx16 "\n", function, value_16bit ); libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ return( 1 ); } /* Reads the TxF data values from an MFT attribute * Returns 1 if successful or -1 on error */ int libfsntfs_txf_data_values_read_from_mft_attribute( libfsntfs_txf_data_values_t *txf_data_values, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ) { uint8_t *data = NULL; static char *function = "libfsntfs_txf_data_values_read_from_mft_attribute"; size_t data_size = 0; uint32_t attribute_type = 0; int result = 0; if( txf_data_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid TxF data values.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_type( mft_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve type from attribute.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_LOGGED_UTILITY_STREAM ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_mft_attribute_data_is_resident( mft_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if attribute data is resident.", function ); return( -1 ); } else if( result == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported non-resident attribute.", function ); return( 1 ); } if( libfsntfs_mft_attribute_get_resident_data( mft_attribute, &data, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve resident data from attribute.", function ); return( -1 ); } if( libfsntfs_txf_data_values_read_data( txf_data_values, data, data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read TxF data values.", function ); return( -1 ); } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_txf_data_values.h ================================================ /* * The Transactional NTFS (TxF) data ($TXF_DATA) logged utility stream * attribute ($LOGGED_UTILITY_STREAM) values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_TXF_DATA_VALUES_H ) #define _LIBFSNTFS_TXF_DATA_VALUES_H #include #include #include "libfsntfs_libcerror.h" #include "libfsntfs_mft_attribute.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_txf_data_values libfsntfs_txf_data_values_t; struct libfsntfs_txf_data_values { /* The resource manager root file reference */ uint64_t rm_root_file_reference; /* The file identifier */ uint64_t file_identifier; /* The file data lsn */ uint64_t data_lsn; /* The file system metadata lsn */ uint64_t metadata_lsn; /* The directory index lsn */ uint64_t directory_index_lsn; }; int libfsntfs_txf_data_values_initialize( libfsntfs_txf_data_values_t **txf_data_values, libcerror_error_t **error ); int libfsntfs_txf_data_values_free( libfsntfs_txf_data_values_t **txf_data_values, libcerror_error_t **error ); int libfsntfs_txf_data_values_read_data( libfsntfs_txf_data_values_t *txf_data_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_txf_data_values_read_from_mft_attribute( libfsntfs_txf_data_values_t *txf_data_values, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_TXF_DATA_VALUES_H ) */ ================================================ FILE: libfsntfs/libfsntfs_types.h ================================================ /* * The internal type definitions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_INTERNAL_TYPES_H ) #define _LIBFSNTFS_INTERNAL_TYPES_H #include #include /* Define HAVE_LOCAL_LIBFSNTFS for local use of libfsntfs * The definitions in are copied here * for local use of libfsntfs */ #if defined( HAVE_LOCAL_LIBFSNTFS ) /* The following type definitions hide internal data structures */ #if defined( HAVE_DEBUG_OUTPUT ) && !defined( WINAPI ) typedef struct libfsntfs_attribute {} libfsntfs_attribute_t; typedef struct libfsntfs_attribute_list_entry {} libfsntfs_attribute_list_entry_t; typedef struct libfsntfs_data_stream {} libfsntfs_data_stream_t; typedef struct libfsntfs_file_entry {} libfsntfs_file_entry_t; typedef struct libfsntfs_mft_metadata_file {} libfsntfs_mft_metadata_file_t; typedef struct libfsntfs_usn_change_journal {} libfsntfs_usn_change_journal_t; typedef struct libfsntfs_volume {} libfsntfs_volume_t; #else typedef intptr_t libfsntfs_attribute_t; typedef intptr_t libfsntfs_attribute_list_entry_t; typedef intptr_t libfsntfs_data_stream_t; typedef intptr_t libfsntfs_file_entry_t; typedef intptr_t libfsntfs_mft_metadata_file_t; typedef intptr_t libfsntfs_usn_change_journal_t; typedef intptr_t libfsntfs_volume_t; #endif /* defined( HAVE_DEBUG_OUTPUT ) && !defined( WINAPI ) */ #endif /* defined( HAVE_LOCAL_LIBFSNTFS ) */ /* The largest primary (or scalar) available * supported by a single load and store instruction */ typedef unsigned long int libfsntfs_aligned_t; #endif /* !defined( _LIBFSNTFS_INTERNAL_TYPES_H ) */ ================================================ FILE: libfsntfs/libfsntfs_unused.h ================================================ /* * Definitions to silence compiler warnings about unused function attributes/parameters. * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_UNUSED_H ) #define _LIBFSNTFS_UNUSED_H #include #if !defined( LIBFSNTFS_ATTRIBUTE_UNUSED ) #if defined( __GNUC__ ) && __GNUC__ >= 3 #define LIBFSNTFS_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) #else #define LIBFSNTFS_ATTRIBUTE_UNUSED #endif #endif #if defined( _MSC_VER ) #define LIBFSNTFS_UNREFERENCED_PARAMETER( parameter ) \ UNREFERENCED_PARAMETER( parameter ); #else #define LIBFSNTFS_UNREFERENCED_PARAMETER( parameter ) \ /* parameter */ #endif #endif /* !defined( _LIBFSNTFS_UNUSED_H ) */ ================================================ FILE: libfsntfs/libfsntfs_usn_change_journal.c ================================================ /* * USN change journal functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_cluster_block_stream.h" #include "libfsntfs_definitions.h" #include "libfsntfs_file_entry.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_types.h" #include "libfsntfs_usn_change_journal.h" /* Creates an USN change journal * Make sure the value usn_change_journal is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_usn_change_journal_initialize( libfsntfs_usn_change_journal_t **usn_change_journal, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfsntfs_directory_entry_t *directory_entry, libfsntfs_mft_attribute_t *data_attribute, libcerror_error_t **error ) { libfsntfs_internal_usn_change_journal_t *internal_usn_change_journal = NULL; static char *function = "libfsntfs_usn_change_journal_initialize"; off64_t segment_offset = 0; int segment_file_index = 0; if( usn_change_journal == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid USN change journal.", function ); return( -1 ); } if( *usn_change_journal != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid USN change journal value already set.", function ); return( -1 ); } if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( data_attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid $J data attribute.", function ); return( -1 ); } internal_usn_change_journal = memory_allocate_structure( libfsntfs_internal_usn_change_journal_t ); if( internal_usn_change_journal == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create USN change journal.", function ); goto on_error; } if( memory_set( internal_usn_change_journal, 0, sizeof( libfsntfs_internal_usn_change_journal_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear USN change journal.", function ); memory_free( internal_usn_change_journal ); return( -1 ); } if( libfsntfs_cluster_block_stream_initialize( &( internal_usn_change_journal->data_stream ), io_handle, data_attribute, NULL, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create $J data stream.", function ); goto on_error; } if( libfdata_stream_get_size( internal_usn_change_journal->data_stream, &( internal_usn_change_journal->data_size ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve $J data stream size.", function ); goto on_error; } if( libfdata_stream_get_number_of_segments( internal_usn_change_journal->data_stream, &( internal_usn_change_journal->number_of_extents ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve $J data stream number of extents.", function ); goto on_error; } if( libfdata_stream_get_segment_by_index( internal_usn_change_journal->data_stream, internal_usn_change_journal->extent_index, &segment_file_index, &segment_offset, &( internal_usn_change_journal->extent_size ), &( internal_usn_change_journal->extent_flags ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve $J data stream extent: %d.", function, internal_usn_change_journal->extent_index ); goto on_error; } /* TODO what defines the journal block size? the index entry size? */ internal_usn_change_journal->journal_block_size = 0x1000; internal_usn_change_journal->journal_block_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * internal_usn_change_journal->journal_block_size ); if( internal_usn_change_journal->journal_block_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create journal block data.", function ); goto on_error; } internal_usn_change_journal->file_io_handle = file_io_handle; internal_usn_change_journal->directory_entry = directory_entry; *usn_change_journal = (libfsntfs_usn_change_journal_t *) internal_usn_change_journal; return( 1 ); on_error: if( internal_usn_change_journal != NULL ) { if( internal_usn_change_journal->data_stream != NULL ) { libfdata_stream_free( &( internal_usn_change_journal->data_stream ), NULL ); } memory_free( internal_usn_change_journal ); } return( -1 ); } /* Frees an USN change journal * Returns 1 if successful or -1 on error */ int libfsntfs_usn_change_journal_free( libfsntfs_usn_change_journal_t **usn_change_journal, libcerror_error_t **error ) { libfsntfs_internal_usn_change_journal_t *internal_usn_change_journal = NULL; static char *function = "libfsntfs_usn_change_journal_free"; int result = 1; if( usn_change_journal == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid USN change journal.", function ); return( -1 ); } if( *usn_change_journal != NULL ) { internal_usn_change_journal = (libfsntfs_internal_usn_change_journal_t *) *usn_change_journal; *usn_change_journal = NULL; /* The file_io_handle reference is freed elsewhere */ if( libfsntfs_directory_entry_free( &( internal_usn_change_journal->directory_entry ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free directory entry.", function ); result = -1; } if( libfdata_stream_free( &( internal_usn_change_journal->data_stream ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free $J data stream.", function ); result = -1; } memory_free( internal_usn_change_journal->journal_block_data ); memory_free( internal_usn_change_journal ); } return( result ); } /* Retrieves the current offset of the default data stream (nameless $DATA attribute) * Returns the offset if successful or -1 on error */ int libfsntfs_usn_change_journal_get_offset( libfsntfs_usn_change_journal_t *usn_change_journal, off64_t *offset, libcerror_error_t **error ) { libfsntfs_internal_usn_change_journal_t *internal_usn_change_journal = NULL; static char *function = "libfsntfs_usn_change_journal_get_offset"; if( usn_change_journal == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid USN change journal.", function ); return( -1 ); } internal_usn_change_journal = (libfsntfs_internal_usn_change_journal_t *) usn_change_journal; if( offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid offset.", function ); return( -1 ); } *offset = internal_usn_change_journal->data_offset; return( 1 ); } /* Reads an USN record from the USN change journal * Returns the number of bytes read if successful or -1 on error */ ssize_t libfsntfs_usn_change_journal_read_usn_record( libfsntfs_usn_change_journal_t *usn_change_journal, uint8_t *usn_record_data, size_t usn_record_data_size, libcerror_error_t **error ) { libfsntfs_internal_usn_change_journal_t *internal_usn_change_journal = NULL; static char *function = "libfsntfs_usn_change_journal_read_usn_record"; size_t read_size = 0; ssize_t read_count = 0; off64_t journal_block_offset = 0; off64_t segment_offset = 0; uint32_t usn_record_size = 0; int read_journal_block = 0; int segment_file_index = 0; if( usn_change_journal == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid USN change journal.", function ); return( -1 ); } internal_usn_change_journal = (libfsntfs_internal_usn_change_journal_t *) usn_change_journal; if( ( internal_usn_change_journal->journal_block_size < 60 ) || ( internal_usn_change_journal->journal_block_size > MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid USN change journal - journal block size value out of bounds.", function ); return( -1 ); } if( usn_record_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid USN record data.", function ); return( -1 ); } if( usn_record_data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid USN record data size value out of bounds.", function ); return( -1 ); } if( internal_usn_change_journal->extent_index >= internal_usn_change_journal->number_of_extents ) { return( 0 ); } while( usn_record_size == 0 ) { if( internal_usn_change_journal->data_offset == 0 ) { read_journal_block = 1; } else if( internal_usn_change_journal->journal_block_offset >= ( internal_usn_change_journal->journal_block_size - 60 ) ) { /* Get the next journal block */ internal_usn_change_journal->extent_offset += internal_usn_change_journal->journal_block_size; read_journal_block = 1; } while( ( ( internal_usn_change_journal->extent_flags & LIBFSNTFS_EXTENT_FLAG_IS_SPARSE ) != 0 ) || ( (size64_t) internal_usn_change_journal->extent_offset >= internal_usn_change_journal->extent_size ) ) { /* Get the next non-sparse extent */ internal_usn_change_journal->extent_start_offset += internal_usn_change_journal->extent_size; internal_usn_change_journal->extent_index += 1; if( internal_usn_change_journal->extent_index >= internal_usn_change_journal->number_of_extents ) { return( 0 ); } if( libfdata_stream_get_segment_by_index( internal_usn_change_journal->data_stream, internal_usn_change_journal->extent_index, &segment_file_index, &segment_offset, &( internal_usn_change_journal->extent_size ), &( internal_usn_change_journal->extent_flags ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve $J data stream extent: %d.", function, internal_usn_change_journal->extent_index ); return( -1 ); } internal_usn_change_journal->extent_offset = 0; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: $J data stream extent: %d segment offset\t: 0x%08" PRIx64 "\n", function, internal_usn_change_journal->extent_index, segment_offset ); libcnotify_printf( "%s: $J data stream extent: %d size\t: %" PRIu64 "\n", function, internal_usn_change_journal->extent_index, internal_usn_change_journal->extent_size ); libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ if( ( internal_usn_change_journal->extent_flags & LIBFSNTFS_EXTENT_FLAG_IS_SPARSE ) != 0 ) { internal_usn_change_journal->data_offset += internal_usn_change_journal->extent_size; } else { read_journal_block = 1; } } if( read_journal_block != 0 ) { if( (size64_t) internal_usn_change_journal->extent_offset >= internal_usn_change_journal->extent_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid USN change journal - extent data offset value out of bounds.", function ); return( -1 ); } if( memory_set( internal_usn_change_journal->journal_block_data, 0, internal_usn_change_journal->journal_block_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear journal block.", function ); return( -1 ); } read_size = internal_usn_change_journal->journal_block_size; if( read_size > ( internal_usn_change_journal->extent_size - internal_usn_change_journal->extent_offset ) ) { read_size = (size_t) ( internal_usn_change_journal->extent_size - internal_usn_change_journal->extent_offset ); } journal_block_offset = internal_usn_change_journal->extent_start_offset + internal_usn_change_journal->extent_offset; read_count = libfdata_stream_read_buffer_at_offset( internal_usn_change_journal->data_stream, (intptr_t *) internal_usn_change_journal->file_io_handle, internal_usn_change_journal->journal_block_data, read_size, journal_block_offset, 0, error ); if( read_count != (ssize_t) read_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read journal block from $J data stream at offset: %" PRIi64 " (0x%08" PRIx64 ").", function, journal_block_offset, journal_block_offset ); return( -1 ); } internal_usn_change_journal->journal_block_offset = 0; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: journal block offset\t: %" PRIzd "\n", function, internal_usn_change_journal->journal_block_offset ); libcnotify_printf( "%s: journal block size\t: %" PRIu64 "\n", function, internal_usn_change_journal->journal_block_size ); libcnotify_printf( "\n" ); } #endif if( internal_usn_change_journal->journal_block_offset >= ( internal_usn_change_journal->journal_block_size - 60 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid USN change journal - journal block offset value out of bounds.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: USN change journal record header data:\n", function ); libcnotify_print_data( &( internal_usn_change_journal->journal_block_data[ internal_usn_change_journal->journal_block_offset ] ), 60, 0 ); } #endif byte_stream_copy_to_uint32_little_endian( &( internal_usn_change_journal->journal_block_data[ internal_usn_change_journal->journal_block_offset ] ), usn_record_size ); if( usn_record_size == 0 ) { internal_usn_change_journal->data_offset = internal_usn_change_journal->journal_block_size - internal_usn_change_journal->journal_block_offset; internal_usn_change_journal->journal_block_offset = internal_usn_change_journal->journal_block_size; } } if( ( usn_record_size < 60 ) || ( usn_record_size > ( internal_usn_change_journal->journal_block_size - internal_usn_change_journal->journal_block_offset ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid USN record size value out of bounds.", function ); return( -1 ); } if( usn_record_data_size < usn_record_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: USN record data size value too small.", function ); return( -1 ); } if( memory_copy( usn_record_data, &( internal_usn_change_journal->journal_block_data[ internal_usn_change_journal->journal_block_offset ] ), (size_t) usn_record_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy USN record data.", function ); return( -1 ); } internal_usn_change_journal->data_offset += usn_record_size; internal_usn_change_journal->journal_block_offset += usn_record_size; return( (ssize_t) usn_record_size ); } ================================================ FILE: libfsntfs/libfsntfs_usn_change_journal.h ================================================ /* * USN change journal functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_INTERNAL_USN_CHANGE_JOURNAL_H ) #define _LIBFSNTFS_INTERNAL_USN_CHANGE_JOURNAL_H #include #include #include "libfsntfs_directory_entry.h" #include "libfsntfs_extern.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_types.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_internal_usn_change_journal libfsntfs_internal_usn_change_journal_t; struct libfsntfs_internal_usn_change_journal { /* The file IO handle */ libbfio_handle_t *file_io_handle; /* The directory entry */ libfsntfs_directory_entry_t *directory_entry; /* The $J data stream */ libfdata_stream_t *data_stream; /* The data offset */ off64_t data_offset; /* The data size */ size64_t data_size; /* The number of extents */ int number_of_extents; /* The extent index */ int extent_index; /* The extent start offset */ off64_t extent_start_offset; /* The extent offset */ off64_t extent_offset; /* The extent size */ size64_t extent_size; /* The extent flags */ uint32_t extent_flags; /* The journal block data */ uint8_t *journal_block_data; /* The journal block (data) offset */ size_t journal_block_offset; /* The journal block size */ size_t journal_block_size; }; int libfsntfs_usn_change_journal_initialize( libfsntfs_usn_change_journal_t **usn_change_journal, libfsntfs_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libfsntfs_directory_entry_t *directory_entry, libfsntfs_mft_attribute_t *data_attribute, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_usn_change_journal_free( libfsntfs_usn_change_journal_t **usn_change_journal, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_usn_change_journal_get_offset( libfsntfs_usn_change_journal_t *usn_change_journal, off64_t *offset, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ ssize_t libfsntfs_usn_change_journal_read_usn_record( libfsntfs_usn_change_journal_t *usn_change_journal, uint8_t *usn_record_data, size_t usn_record_data_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_INTERNAL_USN_CHANGE_JOURNAL_H ) */ ================================================ FILE: libfsntfs/libfsntfs_volume.c ================================================ /* * Volume functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include "libfsntfs_attribute.h" #include "libfsntfs_debug.h" #include "libfsntfs_definitions.h" #include "libfsntfs_directory_entries_tree.h" #include "libfsntfs_directory_entry.h" #include "libfsntfs_file_entry.h" #include "libfsntfs_file_name_values.h" #include "libfsntfs_file_system.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_libfcache.h" #include "libfsntfs_libfdata.h" #include "libfsntfs_libuna.h" #include "libfsntfs_mft_entry.h" #include "libfsntfs_usn_change_journal.h" #include "libfsntfs_volume.h" #include "libfsntfs_volume_header.h" #include "libfsntfs_volume_information_attribute.h" #include "libfsntfs_volume_name_attribute.h" /* Creates a volume * Make sure the value volume is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_volume_initialize( libfsntfs_volume_t **volume, libcerror_error_t **error ) { libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_initialize"; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } if( *volume != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid volume value already set.", function ); return( -1 ); } internal_volume = memory_allocate_structure( libfsntfs_internal_volume_t ); if( internal_volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create volume.", function ); goto on_error; } if( memory_set( internal_volume, 0, sizeof( libfsntfs_internal_volume_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear volume.", function ); memory_free( internal_volume ); return( -1 ); } if( libfsntfs_io_handle_initialize( &( internal_volume->io_handle ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create IO handle.", function ); goto on_error; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_initialize( &( internal_volume->read_write_lock ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize read/write lock.", function ); goto on_error; } #endif *volume = (libfsntfs_volume_t *) internal_volume; return( 1 ); on_error: if( internal_volume != NULL ) { if( internal_volume->io_handle != NULL ) { libfsntfs_io_handle_free( &( internal_volume->io_handle ), NULL ); } memory_free( internal_volume ); } return( -1 ); } /* Frees a volume * Returns 1 if successful or -1 on error */ int libfsntfs_volume_free( libfsntfs_volume_t **volume, libcerror_error_t **error ) { libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_free"; int result = 1; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } if( *volume != NULL ) { internal_volume = (libfsntfs_internal_volume_t *) *volume; if( internal_volume->file_io_handle != NULL ) { if( libfsntfs_volume_close( *volume, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close volume.", function ); result = -1; } } *volume = NULL; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_free( &( internal_volume->read_write_lock ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free read/write lock.", function ); result = -1; } #endif if( libfsntfs_io_handle_free( &( internal_volume->io_handle ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free IO handle.", function ); result = -1; } memory_free( internal_volume ); } return( result ); } /* Signals the volume to abort its current activity * Returns 1 if successful or -1 on error */ int libfsntfs_volume_signal_abort( libfsntfs_volume_t *volume, libcerror_error_t **error ) { libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_signal_abort"; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; if( internal_volume->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid volume - missing IO handle.", function ); return( -1 ); } internal_volume->io_handle->abort = 1; return( 1 ); } /* Opens a volume * Returns 1 if successful or -1 on error */ int libfsntfs_volume_open( libfsntfs_volume_t *volume, const char *filename, int access_flags, libcerror_error_t **error ) { libbfio_handle_t *file_io_handle = NULL; libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_open"; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; if( filename == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid filename.", function ); return( -1 ); } if( ( ( access_flags & LIBFSNTFS_ACCESS_FLAG_READ ) == 0 ) && ( ( access_flags & LIBFSNTFS_ACCESS_FLAG_WRITE ) == 0 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported access flags.", function ); return( -1 ); } if( ( access_flags & LIBFSNTFS_ACCESS_FLAG_WRITE ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: write access currently not supported.", function ); return( -1 ); } if( libbfio_file_initialize( &file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file IO handle.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libbfio_handle_set_track_offsets_read( file_io_handle, 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set track offsets read in file IO handle.", function ); goto on_error; } #endif if( libbfio_file_set_name( file_io_handle, filename, narrow_string_length( filename ) + 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set filename in file IO handle.", function ); goto on_error; } if( libfsntfs_volume_open_file_io_handle( volume, file_io_handle, access_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open volume: %s.", function, filename ); goto on_error; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); goto on_error; } #endif internal_volume->file_io_handle_created_in_library = 1; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); internal_volume->file_io_handle_created_in_library = 0; goto on_error; } #endif return( 1 ); on_error: if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } return( -1 ); } #if defined( HAVE_WIDE_CHARACTER_TYPE ) /* Opens a volume * Returns 1 if successful or -1 on error */ int libfsntfs_volume_open_wide( libfsntfs_volume_t *volume, const wchar_t *filename, int access_flags, libcerror_error_t **error ) { libbfio_handle_t *file_io_handle = NULL; libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_open_wide"; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; if( filename == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid filename.", function ); return( -1 ); } if( ( ( access_flags & LIBFSNTFS_ACCESS_FLAG_READ ) == 0 ) && ( ( access_flags & LIBFSNTFS_ACCESS_FLAG_WRITE ) == 0 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported access flags.", function ); return( -1 ); } if( ( access_flags & LIBFSNTFS_ACCESS_FLAG_WRITE ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: write access currently not supported.", function ); return( -1 ); } if( libbfio_file_initialize( &file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file IO handle.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libbfio_handle_set_track_offsets_read( file_io_handle, 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set track offsets read in file IO handle.", function ); goto on_error; } #endif if( libbfio_file_set_name_wide( file_io_handle, filename, wide_string_length( filename ) + 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set filename in file IO handle.", function ); goto on_error; } if( libfsntfs_volume_open_file_io_handle( volume, file_io_handle, access_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open volume: %ls.", function, filename ); goto on_error; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); goto on_error; } #endif internal_volume->file_io_handle_created_in_library = 1; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); internal_volume->file_io_handle_created_in_library = 0; goto on_error; } #endif return( 1 ); on_error: if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } return( -1 ); } #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */ /* Opens a volume using a Basic File IO (bfio) handle * Returns 1 if successful or -1 on error */ int libfsntfs_volume_open_file_io_handle( libfsntfs_volume_t *volume, libbfio_handle_t *file_io_handle, int access_flags, libcerror_error_t **error ) { libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_open_file_io_handle"; int bfio_access_flags = 0; int file_io_handle_is_open = 0; uint8_t file_io_handle_opened_in_library = 0; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; if( internal_volume->file_io_handle != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid volume - file IO handle already set.", function ); return( -1 ); } if( file_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file IO handle.", function ); return( -1 ); } if( ( ( access_flags & LIBFSNTFS_ACCESS_FLAG_READ ) == 0 ) && ( ( access_flags & LIBFSNTFS_ACCESS_FLAG_WRITE ) == 0 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported access flags.", function ); return( -1 ); } if( ( access_flags & LIBFSNTFS_ACCESS_FLAG_WRITE ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: write access currently not supported.", function ); return( -1 ); } if( ( access_flags & LIBFSNTFS_ACCESS_FLAG_READ ) != 0 ) { bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ; } file_io_handle_is_open = libbfio_handle_is_open( file_io_handle, error ); if( file_io_handle_is_open == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open volume.", function ); goto on_error; } else if( file_io_handle_is_open == 0 ) { if( libbfio_handle_open( file_io_handle, bfio_access_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open file IO handle.", function ); goto on_error; } file_io_handle_opened_in_library = 1; } if( libfsntfs_internal_volume_open_read( internal_volume, file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read from file IO handle.", function ); goto on_error; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); goto on_error; } #endif internal_volume->file_io_handle = file_io_handle; internal_volume->file_io_handle_opened_in_library = file_io_handle_opened_in_library; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); internal_volume->file_io_handle = NULL; internal_volume->file_io_handle_opened_in_library = 0; goto on_error; } #endif return( 1 ); on_error: if( file_io_handle_opened_in_library != 0 ) { libbfio_handle_close( file_io_handle, error ); } return( -1 ); } /* Closes a volume * Returns 0 if successful or -1 on error */ int libfsntfs_volume_close( libfsntfs_volume_t *volume, libcerror_error_t **error ) { libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_close"; int result = 0; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; if( internal_volume->file_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid volume - missing file IO handle.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( internal_volume->file_io_handle_created_in_library != 0 ) { if( libfsntfs_debug_print_read_offsets( internal_volume->file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print the read offsets.", function ); result = -1; } } } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ if( internal_volume->file_io_handle_opened_in_library != 0 ) { if( libbfio_handle_close( internal_volume->file_io_handle, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close file IO handle.", function ); result = -1; } internal_volume->file_io_handle_opened_in_library = 0; } if( internal_volume->file_io_handle_created_in_library != 0 ) { if( libbfio_handle_free( &( internal_volume->file_io_handle ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file IO handle.", function ); result = -1; } internal_volume->file_io_handle_created_in_library = 0; } internal_volume->file_io_handle = NULL; if( libfsntfs_io_handle_clear( internal_volume->io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to clear IO handle.", function ); result = -1; } if( internal_volume->volume_header != NULL ) { if( libfsntfs_volume_header_free( &( internal_volume->volume_header ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free volume header.", function ); result = -1; } } if( internal_volume->volume_mft_entry != NULL ) { if( libfsntfs_mft_entry_free( &( internal_volume->volume_mft_entry ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free volume MFT entry.", function ); result = -1; } } if( internal_volume->volume_information_attribute != NULL ) { if( libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &( internal_volume->volume_information_attribute ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free volume information attribute.", function ); result = -1; } } if( internal_volume->volume_name_attribute != NULL ) { if( libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &( internal_volume->volume_name_attribute ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free volume name attribute.", function ); result = -1; } } if( internal_volume->file_system != NULL ) { if( libfsntfs_file_system_free( &( internal_volume->file_system ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file system.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Opens a volume for reading * Returns 1 if successful or -1 on error */ int libfsntfs_internal_volume_open_read( libfsntfs_internal_volume_t *internal_volume, libbfio_handle_t *file_io_handle, libcerror_error_t **error ) { static char *function = "libfsntfs_internal_volume_open_read"; off64_t mft_offset = 0; if( internal_volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid internal volume.", function ); return( -1 ); } if( internal_volume->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid internal volume - missing IO handle.", function ); return( -1 ); } if( internal_volume->volume_header != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid internal volume - volume header value already set.", function ); return( -1 ); } if( internal_volume->file_system != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid internal volume - file system value already set.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "Reading volume header:\n" ); } #endif if( libfsntfs_volume_header_initialize( &( internal_volume->volume_header ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create volume header.", function ); goto on_error; } if( libfsntfs_volume_header_read_file_io_handle( internal_volume->volume_header, file_io_handle, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read volume header at offset: 0 (0x00000000).", function ); goto on_error; } if( libfsntfs_volume_header_get_bytes_per_sector( internal_volume->volume_header, &( internal_volume->io_handle->bytes_per_sector ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve bytes per sector.", function ); goto on_error; } if( libfsntfs_volume_header_get_cluster_block_size( internal_volume->volume_header, &( internal_volume->io_handle->cluster_block_size ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve cluster block size.", function ); goto on_error; } if( libfsntfs_volume_header_get_mft_entry_size( internal_volume->volume_header, &( internal_volume->io_handle->mft_entry_size ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry size.", function ); goto on_error; } if( libfsntfs_volume_header_get_index_entry_size( internal_volume->volume_header, &( internal_volume->io_handle->index_entry_size ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve index entry size.", function ); goto on_error; } if( libfsntfs_volume_header_get_mft_offset( internal_volume->volume_header, &mft_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT offset.", function ); goto on_error; } if( libfsntfs_file_system_initialize( &( internal_volume->file_system ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file system.", function ); goto on_error; } if( mft_offset < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid MFT offset value out of bounds.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "Reading MFT entry: 0 ($MFT):\n" ); } #endif if( libfsntfs_file_system_read_mft( internal_volume->file_system, internal_volume->io_handle, file_io_handle, mft_offset, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read MFT (MFT entry: 0).", function ); goto on_error; } /* TODO what about the mirror MFT ? */ #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "Reading MFT entry: 6 ($Bitmap):\n" ); } if( libfsntfs_file_system_read_bitmap( internal_volume->file_system, internal_volume->io_handle, file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read bitmap (MFT entry: 6).", function ); goto on_error; } if( libcnotify_verbose != 0 ) { libcnotify_printf( "Reading MFT entry: 9 ($Secure):\n" ); } #endif if( libfsntfs_file_system_read_security_descriptors( internal_volume->file_system, internal_volume->io_handle, file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read security descriptors (MFT entry: 9).", function ); goto on_error; } return( 1 ); on_error: if( internal_volume->file_system != NULL ) { libfsntfs_file_system_free( &( internal_volume->file_system ), NULL ); } if( internal_volume->volume_header != NULL ) { libfsntfs_volume_header_free( &( internal_volume->volume_header ), NULL ); } return( -1 ); } /* Determines if the volume has BitLocker Drive Encryption (BDE) * Returns 1 if the volume has BitLocker Drive Encryption, 0 if not or -1 on error */ int libfsntfs_volume_has_bitlocker_drive_encryption( libfsntfs_volume_t *volume, libcerror_error_t **error ) { libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_has_bitlocker_drive_encryption"; int result = 0; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif /* TODO implement */ #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Determines if the volume has Volume Shadow Snapshots (VSS) * Returns 1 if the volume has Volume Shadow Snapshots, 0 if not or -1 on error */ int libfsntfs_volume_has_volume_shadow_snapshots( libfsntfs_volume_t *volume, libcerror_error_t **error ) { libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_has_volume_shadow_snapshots"; int result = 0; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif /* TODO implement */ #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the $VOLUME_INFORMATION attribute from MFT entry 3 * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_internal_volume_get_volume_information_attribute( libfsntfs_internal_volume_t *internal_volume, libfsntfs_attribute_t **attribute, libcerror_error_t **error ) { libfsntfs_mft_attribute_t *mft_attribute = NULL; static char *function = "libfsntfs_internal_volume_get_volume_information_attribute"; int result = 0; if( internal_volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( internal_volume->volume_mft_entry == NULL ) { if( libfsntfs_file_system_get_mft_entry_by_index_no_cache( internal_volume->file_system, internal_volume->file_io_handle, LIBFSNTFS_MFT_ENTRY_INDEX_VOLUME, &( internal_volume->volume_mft_entry ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: %d.", function, LIBFSNTFS_MFT_ENTRY_INDEX_VOLUME ); return( -1 ); } } if( internal_volume->volume_information_attribute == NULL ) { result = libfsntfs_mft_entry_get_volume_information_attribute( internal_volume->volume_mft_entry, &mft_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve $VOLUME_INFORMATION attribute.", function ); return( -1 ); } else if( result == 0 ) { return( 0 ); } if( libfsntfs_attribute_initialize( &( internal_volume->volume_information_attribute ), mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create $VOLUME_INFORMATION attribute.", function ); return( -1 ); } if( libfsntfs_internal_attribute_read_value( (libfsntfs_internal_attribute_t *) internal_volume->volume_information_attribute, internal_volume->io_handle, internal_volume->file_io_handle, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read value of $VOLUME_INFORMATION attribute.", function ); return( -1 ); } } *attribute = internal_volume->volume_information_attribute; return( 1 ); } /* Retrieves the $VOLUME_NAME attribute from MFT entry 3 * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_internal_volume_get_volume_name_attribute( libfsntfs_internal_volume_t *internal_volume, libfsntfs_attribute_t **attribute, libcerror_error_t **error ) { libfsntfs_mft_attribute_t *mft_attribute = NULL; static char *function = "libfsntfs_internal_volume_get_volume_name_attribute"; int result = 0; if( internal_volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } if( internal_volume->volume_mft_entry == NULL ) { if( libfsntfs_file_system_get_mft_entry_by_index_no_cache( internal_volume->file_system, internal_volume->file_io_handle, LIBFSNTFS_MFT_ENTRY_INDEX_VOLUME, &( internal_volume->volume_mft_entry ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: %d.", function, LIBFSNTFS_MFT_ENTRY_INDEX_VOLUME ); return( -1 ); } } if( internal_volume->volume_name_attribute == NULL ) { result = libfsntfs_mft_entry_get_volume_name_attribute( internal_volume->volume_mft_entry, &mft_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve $VOLUME_NAME attribute.", function ); return( -1 ); } else if( result == 0 ) { return( 0 ); } if( libfsntfs_attribute_initialize( &( internal_volume->volume_name_attribute ), mft_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create $VOLUME_NAME attribute.", function ); return( -1 ); } if( libfsntfs_internal_attribute_read_value( (libfsntfs_internal_attribute_t *) internal_volume->volume_name_attribute, internal_volume->io_handle, internal_volume->file_io_handle, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read value of $VOLUME_NAME attribute.", function ); return( -1 ); } } *attribute = internal_volume->volume_name_attribute; return( 1 ); } /* Retrieves the bytes per sector * Returns 1 if successful or -1 on error */ int libfsntfs_volume_get_bytes_per_sector( libfsntfs_volume_t *volume, uint16_t *bytes_per_sector, libcerror_error_t **error ) { libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_get_bytes_per_sector"; int result = 1; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_volume_header_get_bytes_per_sector( internal_volume->volume_header, bytes_per_sector, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve bytes per sector.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the cluster block size * Returns 1 if successful or -1 on error */ int libfsntfs_volume_get_cluster_block_size( libfsntfs_volume_t *volume, size32_t *cluster_block_size, libcerror_error_t **error ) { libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_get_cluster_block_size"; int result = 1; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_volume_header_get_cluster_block_size( internal_volume->volume_header, cluster_block_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve cluster block size.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the MFT entry size * Returns 1 if successful or -1 on error */ int libfsntfs_volume_get_mft_entry_size( libfsntfs_volume_t *volume, size32_t *mft_entry_size, libcerror_error_t **error ) { libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_get_mft_entry_size"; int result = 1; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_volume_header_get_mft_entry_size( internal_volume->volume_header, mft_entry_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry size.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the index entry size * Returns 1 if successful or -1 on error */ int libfsntfs_volume_get_index_entry_size( libfsntfs_volume_t *volume, size32_t *index_entry_size, libcerror_error_t **error ) { libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_get_index_entry_size"; int result = 1; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_volume_header_get_index_entry_size( internal_volume->volume_header, index_entry_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve index entry size.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the size of the UTF-8 encoded name * The returned size includes the end of string character * This value is retrieved from the $VOLUME_NAME attribute of the $Volume metadata file * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_volume_get_utf8_name_size( libfsntfs_volume_t *volume, size_t *utf8_string_size, libcerror_error_t **error ) { libfsntfs_attribute_t *volume_name_attribute = NULL; libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_get_utf8_name_size"; int result = 0; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_volume_get_volume_name_attribute( internal_volume, &volume_name_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve volume name attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_volume_name_attribute_get_utf8_name_size( volume_name_attribute, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-8 name from volume name attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the UTF-8 encoded name * The size should include the end of string character * This value is retrieved from the $VOLUME_NAME attribute of the $Volume metadata file * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_volume_get_utf8_name( libfsntfs_volume_t *volume, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { libfsntfs_attribute_t *volume_name_attribute = NULL; libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_get_utf8_name"; int result = 0; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_volume_get_volume_name_attribute( internal_volume, &volume_name_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve volume name attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_volume_name_attribute_get_utf8_name( volume_name_attribute, utf8_string, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 name from volume name attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the size of the UTF-16 encoded name * The returned size includes the end of string character * This value is retrieved from the $VOLUME_NAME attribute of the $Volume metadata file * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_volume_get_utf16_name_size( libfsntfs_volume_t *volume, size_t *utf16_string_size, libcerror_error_t **error ) { libfsntfs_attribute_t *volume_name_attribute = NULL; libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_get_utf16_name_size"; int result = 0; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_volume_get_volume_name_attribute( internal_volume, &volume_name_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve volume name attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_volume_name_attribute_get_utf16_name_size( volume_name_attribute, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-16 name from volume name attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the UTF-16 encoded name * The size should include the end of string character * This value is retrieved from the $VOLUME_NAME attribute of the $Volume metadata file * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_volume_get_utf16_name( libfsntfs_volume_t *volume, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { libfsntfs_attribute_t *volume_name_attribute = NULL; libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_get_utf16_name"; int result = 0; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_volume_get_volume_name_attribute( internal_volume, &volume_name_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve volume name attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_volume_name_attribute_get_utf16_name( volume_name_attribute, utf16_string, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 name from volume name attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the format version * This value is retrieved from the $VOLUME_INFORMATION attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_volume_get_version( libfsntfs_volume_t *volume, uint8_t *major_version, uint8_t *minor_version, libcerror_error_t **error ) { libfsntfs_attribute_t *volume_information_attribute = NULL; libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_get_version"; int result = 0; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_volume_get_volume_information_attribute( internal_volume, &volume_information_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve volume information attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_volume_information_attribute_get_version( volume_information_attribute, major_version, minor_version, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve version from volume information attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the flags * This value is retrieved from the $VOLUME_INFORMATION attribute * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_volume_get_flags( libfsntfs_volume_t *volume, uint16_t *flags, libcerror_error_t **error ) { libfsntfs_attribute_t *volume_information_attribute = NULL; libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_get_flags"; int result = 0; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_volume_get_volume_information_attribute( internal_volume, &volume_information_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve volume information attribute.", function ); result = -1; } else if( result != 0 ) { if( libfsntfs_volume_information_attribute_get_flags( volume_information_attribute, flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve flags from volume information attribute.", function ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the serial number * Returns 1 if successful or -1 on error */ int libfsntfs_volume_get_serial_number( libfsntfs_volume_t *volume, uint64_t *serial_number, libcerror_error_t **error ) { libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_get_serial_number"; int result = 1; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_volume_header_get_volume_serial_number( internal_volume->volume_header, serial_number, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve volume serial number.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the root directory file entry * Returns 1 if successful or -1 on error */ int libfsntfs_volume_get_root_directory( libfsntfs_volume_t *volume, libfsntfs_file_entry_t **file_entry, libcerror_error_t **error ) { libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_get_root_directory"; int result = 1; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( *file_entry != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file entry value already set.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif if( libfsntfs_file_entry_initialize( file_entry, internal_volume->io_handle, internal_volume->file_io_handle, internal_volume->file_system, LIBFSNTFS_MFT_ENTRY_INDEX_ROOT_DIRECTORY, NULL, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file entry from MFT entry: %d.", function, LIBFSNTFS_MFT_ENTRY_INDEX_ROOT_DIRECTORY ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the number of file entries (MFT entries) * Returns 1 if successful or -1 on error */ int libfsntfs_volume_get_number_of_file_entries( libfsntfs_volume_t *volume, uint64_t *number_of_file_entries, libcerror_error_t **error ) { libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_get_number_of_file_entries"; int result = 1; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_read( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( libfsntfs_file_system_get_number_of_mft_entries( internal_volume->file_system, number_of_file_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of MFT entries.", function ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_read( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the file entry of a specific MFT entry index * Returns 1 if successful or -1 on error */ int libfsntfs_volume_get_file_entry_by_index( libfsntfs_volume_t *volume, uint64_t mft_entry_index, libfsntfs_file_entry_t **file_entry, libcerror_error_t **error ) { libfsntfs_internal_volume_t *internal_volume = NULL; static char *function = "libfsntfs_volume_get_file_entry_by_index"; int result = 1; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( *file_entry != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file entry value already set.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif if( libfsntfs_file_entry_initialize( file_entry, internal_volume->io_handle, internal_volume->file_io_handle, internal_volume->file_system, mft_entry_index, NULL, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file entry with MFT entry: %" PRIu64 ".", function, mft_entry_index ); result = -1; } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); } /* Retrieves the MFT entry for an UTF-8 encoded path * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode * A new directory_entry is allocated if a match is found * Returns 1 if successful, 0 if no such file entry or -1 on error */ int libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf8_path( libfsntfs_internal_volume_t *internal_volume, const uint8_t *utf8_string, size_t utf8_string_length, libfsntfs_mft_entry_t **mft_entry, libfsntfs_directory_entry_t **directory_entry, libcerror_error_t **error ) { libfsntfs_directory_entries_tree_t *directory_entries_tree = NULL; libfsntfs_directory_entry_t *safe_directory_entry = NULL; const uint8_t *utf8_string_segment = NULL; static char *function = "libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf8_path"; libuna_unicode_character_t unicode_character = 0; size_t utf8_string_index = 0; size_t utf8_string_segment_length = 0; uint64_t mft_entry_index = 0; int result = 0; if( internal_volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } if( utf8_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-8 string.", function ); return( -1 ); } if( utf8_string_length > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-8 string length value exceeds maximum.", function ); return( -1 ); } if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( utf8_string_length > 0 ) { /* Ignore a leading separator */ if( utf8_string[ utf8_string_index ] == (uint8_t) LIBFSNTFS_SEPARATOR ) { utf8_string_index++; } } if( libfsntfs_file_system_get_mft_entry_by_index( internal_volume->file_system, internal_volume->file_io_handle, LIBFSNTFS_MFT_ENTRY_INDEX_ROOT_DIRECTORY, mft_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: 5.", function ); goto on_error; } if( ( utf8_string_length == 0 ) || ( utf8_string_length == 1 ) ) { result = 1; } else while( utf8_string_index < utf8_string_length ) { if( directory_entries_tree != NULL ) { if( libfsntfs_directory_entries_tree_free( &directory_entries_tree, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free directory entries tree.", function ); goto on_error; } } if( libfsntfs_directory_entries_tree_initialize( &directory_entries_tree, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create directory entries tree.", function ); goto on_error; } if( libfsntfs_directory_entries_tree_read_from_i30_index( directory_entries_tree, internal_volume->io_handle, internal_volume->file_io_handle, *mft_entry, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read directory entries tree from MFT entry: %" PRIu64 ".", function, mft_entry_index ); goto on_error; } utf8_string_segment = &( utf8_string[ utf8_string_index ] ); utf8_string_segment_length = utf8_string_index; while( utf8_string_index < utf8_string_length ) { if( libuna_unicode_character_copy_from_utf8_rfc2279( &unicode_character, utf8_string, utf8_string_length, &utf8_string_index, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy UTF-8 string to Unicode character.", function ); goto on_error; } if( ( unicode_character == (libuna_unicode_character_t) LIBFSNTFS_SEPARATOR ) || ( unicode_character == 0 ) ) { utf8_string_segment_length += 1; break; } } utf8_string_segment_length = utf8_string_index - utf8_string_segment_length; if( utf8_string_segment_length == 0 ) { result = 0; } else { if( safe_directory_entry != NULL ) { if( libfsntfs_directory_entry_free( &safe_directory_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free directory entry.", function ); goto on_error; } } result = libfsntfs_directory_entries_tree_get_entry_by_utf8_name( directory_entries_tree, internal_volume->file_io_handle, utf8_string_segment, utf8_string_segment_length, &safe_directory_entry, error ); } if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve directory entry by UTF-8 name.", function ); goto on_error; } else if( result == 0 ) { break; } if( libfsntfs_directory_entry_get_mft_entry_index( safe_directory_entry, &mft_entry_index, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry index.", function ); goto on_error; } if( libfsntfs_file_system_get_mft_entry_by_index( internal_volume->file_system, internal_volume->file_io_handle, mft_entry_index, mft_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: %" PRIu64 ".", function, mft_entry_index ); goto on_error; } } if( result != 0 ) { *directory_entry = safe_directory_entry; } else if( safe_directory_entry != NULL ) { if( libfsntfs_directory_entry_free( &safe_directory_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free directory entry.", function ); goto on_error; } } if( directory_entries_tree != NULL ) { if( libfsntfs_directory_entries_tree_free( &directory_entries_tree, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free directory entries tree.", function ); goto on_error; } } return( result ); on_error: if( safe_directory_entry != NULL ) { libfsntfs_directory_entry_free( &safe_directory_entry, NULL ); } if( directory_entries_tree != NULL ) { libfsntfs_directory_entries_tree_free( &directory_entries_tree, NULL ); } *directory_entry = NULL; return( -1 ); } /* Retrieves the file entry for an UTF-8 encoded path * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode * Returns 1 if successful, 0 if no such file entry or -1 on error */ int libfsntfs_volume_get_file_entry_by_utf8_path( libfsntfs_volume_t *volume, const uint8_t *utf8_string, size_t utf8_string_length, libfsntfs_file_entry_t **file_entry, libcerror_error_t **error ) { libfsntfs_directory_entry_t *directory_entry = NULL; libfsntfs_internal_volume_t *internal_volume = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; static char *function = "libfsntfs_volume_get_file_entry_by_utf8_path"; int result = 0; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( *file_entry != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file entry value already set.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf8_path( internal_volume, utf8_string, utf8_string_length, &mft_entry, &directory_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT and directory entry by path.", function ); result = -1; } else if( result != 0 ) { /* file_entry takes over management of directory_entry */ if( libfsntfs_file_entry_initialize( file_entry, internal_volume->io_handle, internal_volume->file_io_handle, internal_volume->file_system, (uint64_t) mft_entry->index, directory_entry, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file entry with MFT entry: %" PRIu32 ".", function, mft_entry->index ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); result = -1; } #endif if( result == -1 ) { if( directory_entry != NULL ) { libfsntfs_directory_entry_free( &directory_entry, NULL ); } } return( result ); } /* Retrieves the MFT entry for an UTF-16 encoded path * This function uses UCS-2 (with surrogates) to support characters outside Unicode * A new directory_entry is allocated if a match is found * Returns 1 if successful, 0 if no such file entry or -1 on error */ int libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf16_path( libfsntfs_internal_volume_t *internal_volume, const uint16_t *utf16_string, size_t utf16_string_length, libfsntfs_mft_entry_t **mft_entry, libfsntfs_directory_entry_t **directory_entry, libcerror_error_t **error ) { libfsntfs_directory_entries_tree_t *directory_entries_tree = NULL; libfsntfs_directory_entry_t *safe_directory_entry = NULL; const uint16_t *utf16_string_segment = NULL; static char *function = "libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf16_path"; libuna_unicode_character_t unicode_character = 0; size_t utf16_string_index = 0; size_t utf16_string_segment_length = 0; uint64_t mft_entry_index = 0; int result = 0; if( internal_volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } if( utf16_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-16 string.", function ); return( -1 ); } if( utf16_string_length > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-16 string length value exceeds maximum.", function ); return( -1 ); } if( mft_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry.", function ); return( -1 ); } if( directory_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid directory entry.", function ); return( -1 ); } if( utf16_string_length > 0 ) { /* Ignore a leading separator */ if( utf16_string[ utf16_string_index ] == (uint16_t) LIBFSNTFS_SEPARATOR ) { utf16_string_index++; } } if( libfsntfs_file_system_get_mft_entry_by_index( internal_volume->file_system, internal_volume->file_io_handle, LIBFSNTFS_MFT_ENTRY_INDEX_ROOT_DIRECTORY, mft_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: 5.", function ); goto on_error; } if( ( utf16_string_length == 0 ) || ( utf16_string_length == 1 ) ) { result = 1; } else while( utf16_string_index < utf16_string_length ) { if( directory_entries_tree != NULL ) { if( libfsntfs_directory_entries_tree_free( &directory_entries_tree, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free directory entries tree.", function ); goto on_error; } } if( libfsntfs_directory_entries_tree_initialize( &directory_entries_tree, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create directory entries tree.", function ); goto on_error; } if( libfsntfs_directory_entries_tree_read_from_i30_index( directory_entries_tree, internal_volume->io_handle, internal_volume->file_io_handle, *mft_entry, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read directory entries tree from MFT entry: %" PRIu64 ".", function, mft_entry_index ); goto on_error; } utf16_string_segment = &( utf16_string[ utf16_string_index ] ); utf16_string_segment_length = utf16_string_index; while( utf16_string_index < utf16_string_length ) { if( libuna_unicode_character_copy_from_ucs2( &unicode_character, utf16_string, utf16_string_length, &utf16_string_index, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy UTF-16 string to Unicode character.", function ); goto on_error; } if( ( unicode_character == (libuna_unicode_character_t) LIBFSNTFS_SEPARATOR ) || ( unicode_character == 0 ) ) { utf16_string_segment_length += 1; break; } } utf16_string_segment_length = utf16_string_index - utf16_string_segment_length; if( utf16_string_segment_length == 0 ) { result = 0; } else { if( safe_directory_entry != NULL ) { if( libfsntfs_directory_entry_free( &safe_directory_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free directory entry.", function ); goto on_error; } } result = libfsntfs_directory_entries_tree_get_entry_by_utf16_name( directory_entries_tree, internal_volume->file_io_handle, utf16_string_segment, utf16_string_segment_length, &safe_directory_entry, error ); } if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve directory entry by UTF-16 name.", function ); goto on_error; } else if( result == 0 ) { break; } if( libfsntfs_directory_entry_get_mft_entry_index( safe_directory_entry, &mft_entry_index, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry index.", function ); goto on_error; } if( libfsntfs_file_system_get_mft_entry_by_index( internal_volume->file_system, internal_volume->file_io_handle, mft_entry_index, mft_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT entry: %" PRIu64 ".", function, mft_entry_index ); goto on_error; } } if( result != 0 ) { *directory_entry = safe_directory_entry; } else if( safe_directory_entry != NULL ) { if( libfsntfs_directory_entry_free( &safe_directory_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free directory entry.", function ); goto on_error; } } if( directory_entries_tree != NULL ) { if( libfsntfs_directory_entries_tree_free( &directory_entries_tree, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free directory entries tree.", function ); goto on_error; } } return( result ); on_error: if( safe_directory_entry != NULL ) { libfsntfs_directory_entry_free( &safe_directory_entry, NULL ); } if( directory_entries_tree != NULL ) { libfsntfs_directory_entries_tree_free( &directory_entries_tree, NULL ); } *directory_entry = NULL; return( -1 ); } /* Retrieves the file entry for an UTF-16 encoded path * This function uses UCS-2 (with surrogates) to support characters outside Unicode * Returns 1 if successful, 0 if no such file entry or -1 on error */ int libfsntfs_volume_get_file_entry_by_utf16_path( libfsntfs_volume_t *volume, const uint16_t *utf16_string, size_t utf16_string_length, libfsntfs_file_entry_t **file_entry, libcerror_error_t **error ) { libfsntfs_directory_entry_t *directory_entry = NULL; libfsntfs_internal_volume_t *internal_volume = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; static char *function = "libfsntfs_volume_get_file_entry_by_utf16_path"; int result = 0; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; if( file_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file entry.", function ); return( -1 ); } if( *file_entry != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file entry value already set.", function ); return( -1 ); } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf16_path( internal_volume, utf16_string, utf16_string_length, &mft_entry, &directory_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve MFT and directory entry by path.", function ); result = -1; } else if( result != 0 ) { /* file_entry takes over management of directory_entry */ if( libfsntfs_file_entry_initialize( file_entry, internal_volume->io_handle, internal_volume->file_io_handle, internal_volume->file_system, (uint64_t) mft_entry->index, directory_entry, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file entry with MFT entry: %" PRIu32 ".", function, mft_entry->index ); result = -1; } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); result = -1; } #endif if( result == -1 ) { if( directory_entry != NULL ) { libfsntfs_directory_entry_free( &directory_entry, NULL ); } } return( result ); } /* Retrieves the USN change journal * Returns 1 if successful, 0 if not available or -1 on error */ int libfsntfs_volume_get_usn_change_journal( libfsntfs_volume_t *volume, libfsntfs_usn_change_journal_t **usn_change_journal, libcerror_error_t **error ) { libfsntfs_directory_entry_t *directory_entry = NULL; libfsntfs_internal_volume_t *internal_volume = NULL; libfsntfs_mft_attribute_t *data_attribute = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; static char *function = "libfsntfs_volume_get_usn_change_journal"; int result = 0; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libfsntfs_internal_volume_t *) volume; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif result = libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf8_path( internal_volume, (uint8_t *) "\\$Extend\\$UsnJrnl", 17, &mft_entry, &directory_entry, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve \\$Extend\\$UsnJrnl MFT and directory entry by path.", function ); result = -1; } else if( result != 0 ) { result = libfsntfs_mft_entry_get_alternate_data_attribute_by_utf8_name( mft_entry, (uint8_t *) "$J", 2, &data_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve $J data attribute.", function ); result = -1; } else if( result != 0 ) { /* libfsntfs_usn_change_journal_initialize takes over management of directory_entry */ if( libfsntfs_usn_change_journal_initialize( usn_change_journal, internal_volume->io_handle, internal_volume->file_io_handle, directory_entry, data_attribute, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create USN change journal.", function ); result = -1; } } else { if( libfsntfs_directory_entry_free( &directory_entry, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free directory entry.", function ); result = -1; } } } #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_volume->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif if( result == - 1 ) { if( directory_entry != NULL ) { libfsntfs_directory_entry_free( &directory_entry, NULL ); } } return( result ); } ================================================ FILE: libfsntfs/libfsntfs_volume.h ================================================ /* * Volume functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_VOLUME_H ) #define _LIBFSNTFS_VOLUME_H #include #include #include "libfsntfs_directory_entry.h" #include "libfsntfs_extern.h" #include "libfsntfs_file_system.h" #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_mft.h" #include "libfsntfs_mft_entry.h" #include "libfsntfs_types.h" #include "libfsntfs_volume_header.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_internal_volume libfsntfs_internal_volume_t; struct libfsntfs_internal_volume { /* The IO handle */ libfsntfs_io_handle_t *io_handle; /* The file IO handle */ libbfio_handle_t *file_io_handle; /* Value to indicate if the file IO handle was created inside the library */ uint8_t file_io_handle_created_in_library; /* Value to indicate if the file IO handle was opened inside the library */ uint8_t file_io_handle_opened_in_library; /* The volume serial number */ uint64_t volume_serial_number; /* The volume header */ libfsntfs_volume_header_t *volume_header; /* The MFT */ libfsntfs_mft_t *mft; /* The volume MFT entry */ libfsntfs_mft_entry_t *volume_mft_entry; /* The volume information ($VOLUME_INFORMATION) attribute */ libfsntfs_attribute_t *volume_information_attribute; /* The volume name ($VOLUME_NAME) attribute */ libfsntfs_attribute_t *volume_name_attribute; /* The file system */ libfsntfs_file_system_t *file_system; #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) /* The read/write lock */ libcthreads_read_write_lock_t *read_write_lock; #endif }; LIBFSNTFS_EXTERN \ int libfsntfs_volume_initialize( libfsntfs_volume_t **volume, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_free( libfsntfs_volume_t **volume, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_signal_abort( libfsntfs_volume_t *volume, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_open( libfsntfs_volume_t *volume, const char *filename, int access_flags, libcerror_error_t **error ); #if defined( HAVE_WIDE_CHARACTER_TYPE ) LIBFSNTFS_EXTERN \ int libfsntfs_volume_open_wide( libfsntfs_volume_t *volume, const wchar_t *filename, int access_flags, libcerror_error_t **error ); #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_open_file_io_handle( libfsntfs_volume_t *volume, libbfio_handle_t *file_io_handle, int access_flags, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_close( libfsntfs_volume_t *volume, libcerror_error_t **error ); int libfsntfs_internal_volume_open_read( libfsntfs_internal_volume_t *internal_volume, libbfio_handle_t *file_io_handle, libcerror_error_t **error ); int libfsntfs_internal_volume_read_bitmap( libfsntfs_internal_volume_t *internal_volume, libbfio_handle_t *file_io_handle, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_has_bitlocker_drive_encryption( libfsntfs_volume_t *volume, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_has_volume_shadow_snapshots( libfsntfs_volume_t *volume, libcerror_error_t **error ); int libfsntfs_internal_volume_get_volume_information_attribute( libfsntfs_internal_volume_t *internal_volume, libfsntfs_attribute_t **attribute, libcerror_error_t **error ); int libfsntfs_internal_volume_get_volume_name_attribute( libfsntfs_internal_volume_t *internal_volume, libfsntfs_attribute_t **attribute, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_bytes_per_sector( libfsntfs_volume_t *volume, uint16_t *bytes_per_sector, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_cluster_block_size( libfsntfs_volume_t *volume, size32_t *cluster_block_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_mft_entry_size( libfsntfs_volume_t *volume, size32_t *mft_entry_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_index_entry_size( libfsntfs_volume_t *volume, size32_t *index_entry_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_utf8_name_size( libfsntfs_volume_t *volume, size_t *utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_utf8_name( libfsntfs_volume_t *volume, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_utf16_name_size( libfsntfs_volume_t *volume, size_t *utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_utf16_name( libfsntfs_volume_t *volume, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_version( libfsntfs_volume_t *volume, uint8_t *major_version, uint8_t *minor_version, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_flags( libfsntfs_volume_t *volume, uint16_t *flags, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_serial_number( libfsntfs_volume_t *volume, uint64_t *serial_number, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_root_directory( libfsntfs_volume_t *volume, libfsntfs_file_entry_t **file_entry, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_number_of_file_entries( libfsntfs_volume_t *volume, uint64_t *number_of_file_entries, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_file_entry_by_index( libfsntfs_volume_t *volume, uint64_t mft_entry_index, libfsntfs_file_entry_t **file_entry, libcerror_error_t **error ); int libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf8_path( libfsntfs_internal_volume_t *internal_volume, const uint8_t *utf8_string, size_t utf8_string_length, libfsntfs_mft_entry_t **mft_entry, libfsntfs_directory_entry_t **directory_entry, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_file_entry_by_utf8_path( libfsntfs_volume_t *volume, const uint8_t *utf8_string, size_t utf8_string_length, libfsntfs_file_entry_t **file_entry, libcerror_error_t **error ); int libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf16_path( libfsntfs_internal_volume_t *internal_volume, const uint16_t *utf16_string, size_t utf16_string_length, libfsntfs_mft_entry_t **mft_entry, libfsntfs_directory_entry_t **directory_entry, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_file_entry_by_utf16_path( libfsntfs_volume_t *volume, const uint16_t *utf16_string, size_t utf16_string_length, libfsntfs_file_entry_t **file_entry, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_get_usn_change_journal( libfsntfs_volume_t *volume, libfsntfs_usn_change_journal_t **usn_change_journal, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_VOLUME_H ) */ ================================================ FILE: libfsntfs/libfsntfs_volume_header.c ================================================ /* * The NTFS volume header functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_io_handle.h" #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_volume_header.h" #include "fsntfs_index.h" #include "fsntfs_mft_entry.h" #include "fsntfs_volume_header.h" /* Creates a volume header * Make sure the value volume_header is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_volume_header_initialize( libfsntfs_volume_header_t **volume_header, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_header_initialize"; if( volume_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume header.", function ); return( -1 ); } if( *volume_header != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid volume header value already set.", function ); return( -1 ); } *volume_header = memory_allocate_structure( libfsntfs_volume_header_t ); if( *volume_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create volume header.", function ); goto on_error; } if( memory_set( *volume_header, 0, sizeof( libfsntfs_volume_header_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear volume header.", function ); goto on_error; } return( 1 ); on_error: if( *volume_header != NULL ) { memory_free( *volume_header ); *volume_header = NULL; } return( -1 ); } /* Frees a volume header * Returns 1 if successful or -1 on error */ int libfsntfs_volume_header_free( libfsntfs_volume_header_t **volume_header, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_header_free"; if( volume_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume header.", function ); return( -1 ); } if( *volume_header != NULL ) { memory_free( *volume_header ); *volume_header = NULL; } return( 1 ); } /* Reads the volume header * Returns 1 if successful or -1 on error */ int libfsntfs_volume_header_read_data( libfsntfs_volume_header_t *volume_header, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_header_read_data"; uint64_t mft_cluster_block_number = 0; uint64_t mirror_mft_cluster_block_number = 0; uint64_t volume_size = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint32_t value_32bit = 0; uint16_t value_16bit = 0; #endif if( volume_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume header.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( ( data_size < sizeof( fsntfs_volume_header_t ) ) || ( data_size > (size_t) SSIZE_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: volume header data:\n", function ); libcnotify_print_data( data, sizeof( fsntfs_volume_header_t ), LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif if( memory_compare( ( (fsntfs_volume_header_t *) data )->file_system_signature, fsntfs_volume_file_system_signature, 8 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: invalid volume system signature.", function ); return( -1 ); } byte_stream_copy_to_uint16_little_endian( ( (fsntfs_volume_header_t *) data )->bytes_per_sector, volume_header->bytes_per_sector ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_volume_header_t *) data )->total_number_of_sectors, volume_size ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_volume_header_t *) data )->mft_cluster_block_number, mft_cluster_block_number ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_volume_header_t *) data )->mirror_mft_cluster_block_number, mirror_mft_cluster_block_number ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_volume_header_t *) data )->mft_entry_size, volume_header->mft_entry_size ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_volume_header_t *) data )->index_entry_size, volume_header->index_entry_size ); byte_stream_copy_to_uint64_little_endian( ( (fsntfs_volume_header_t *) data )->volume_serial_number, volume_header->volume_serial_number ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: boot entry point\t\t\t: 0x%02x 0x%02x 0x%02x\n", function, ( (fsntfs_volume_header_t *) data )->boot_entry_point[ 0 ], ( (fsntfs_volume_header_t *) data )->boot_entry_point[ 1 ], ( (fsntfs_volume_header_t *) data )->boot_entry_point[ 2 ] ); libcnotify_printf( "%s: file system signature\t\t: %c%c%c%c%c%c%c%c\n", function, ( (fsntfs_volume_header_t *) data )->file_system_signature[ 0 ], ( (fsntfs_volume_header_t *) data )->file_system_signature[ 1 ], ( (fsntfs_volume_header_t *) data )->file_system_signature[ 2 ], ( (fsntfs_volume_header_t *) data )->file_system_signature[ 3 ], ( (fsntfs_volume_header_t *) data )->file_system_signature[ 4 ], ( (fsntfs_volume_header_t *) data )->file_system_signature[ 5 ], ( (fsntfs_volume_header_t *) data )->file_system_signature[ 6 ], ( (fsntfs_volume_header_t *) data )->file_system_signature[ 7 ] ); libcnotify_printf( "%s: bytes per sector\t\t\t: %" PRIu16 "\n", function, volume_header->bytes_per_sector ); libcnotify_printf( "%s: sectors per cluster block\t\t: %" PRIu8 "\n", function, ( (fsntfs_volume_header_t *) data )->sectors_per_cluster_block ); libcnotify_printf( "%s: unknown1\n", function ); libcnotify_print_data( ( (fsntfs_volume_header_t *) data )->unknown1, 7, 0 ); libcnotify_printf( "%s: media descriptor\t\t\t: 0x%02" PRIx8 "\n", function, ( (fsntfs_volume_header_t *) data )->media_descriptor ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_volume_header_t *) data )->unknown2, value_16bit ); libcnotify_printf( "%s: unknown2\t\t\t\t: %" PRIu16 "\n", function, value_16bit ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_volume_header_t *) data )->sectors_per_track, value_16bit ); libcnotify_printf( "%s: sectors per track\t\t\t: %" PRIu16 "\n", function, value_16bit ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_volume_header_t *) data )->number_of_heads, value_16bit ); libcnotify_printf( "%s: number of heads\t\t\t: %" PRIu16 "\n", function, value_16bit ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_volume_header_t *) data )->number_of_hidden_sectors, value_32bit ); libcnotify_printf( "%s: number of hidden sectors\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_volume_header_t *) data )->unknown3, value_32bit ); libcnotify_printf( "%s: unknown3\t\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n", function, value_32bit, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_volume_header_t *) data )->unknown4, value_32bit ); libcnotify_printf( "%s: unknown4\t\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n", function, value_32bit, value_32bit ); libcnotify_printf( "%s: total number of sectors\t\t: %" PRIu64 "\n", function, volume_size ); libcnotify_printf( "%s: MFT cluster block number\t\t: %" PRIu64 "\n", function, mft_cluster_block_number ); libcnotify_printf( "%s: mirror MFT cluster block number\t: %" PRIu64 "\n", function, mirror_mft_cluster_block_number ); libcnotify_printf( "%s: MFT entry size\t\t\t: %" PRIu32 "\n", function, volume_header->mft_entry_size ); libcnotify_printf( "%s: index entry size\t\t\t: %" PRIu32 "\n", function, volume_header->index_entry_size ); libcnotify_printf( "%s: volume serial number\t\t\t: 0x%08" PRIx64 "\n", function, volume_header->volume_serial_number ); byte_stream_copy_to_uint32_little_endian( ( (fsntfs_volume_header_t *) data )->checksum, value_32bit ); libcnotify_printf( "%s: checksum\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); libcnotify_printf( "%s: bootcode\n", function ); libcnotify_print_data( ( (fsntfs_volume_header_t *) data )->bootcode, 426, 0 ); byte_stream_copy_to_uint16_little_endian( ( (fsntfs_volume_header_t *) data )->sector_signature, value_16bit ); libcnotify_printf( "%s: sector signature\t\t\t: 0x%04" PRIx16 "\n", function, value_16bit ); libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ if( ( volume_header->bytes_per_sector != 256 ) && ( volume_header->bytes_per_sector != 512 ) && ( volume_header->bytes_per_sector != 1024 ) && ( volume_header->bytes_per_sector != 2048 ) && ( volume_header->bytes_per_sector != 4096 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported bytes per sector: %" PRIu16 ".", function, volume_header->bytes_per_sector ); return( -1 ); } volume_header->cluster_block_size = ( (fsntfs_volume_header_t *) data )->sectors_per_cluster_block; if( volume_header->cluster_block_size > 128 ) { /* The size is calculated as: 2 ^ ( 256 - value ) */ volume_header->cluster_block_size = 256 - volume_header->cluster_block_size; if( volume_header->cluster_block_size > 12 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid cluster block size value out of bounds.", function ); return( -1 ); } volume_header->cluster_block_size = 1 << volume_header->cluster_block_size; } volume_header->cluster_block_size *= volume_header->bytes_per_sector; if( ( volume_header->cluster_block_size != 256 ) && ( volume_header->cluster_block_size != 512 ) && ( volume_header->cluster_block_size != 1024 ) && ( volume_header->cluster_block_size != 2048 ) && ( volume_header->cluster_block_size != 4096 ) && ( volume_header->cluster_block_size != 8192 ) && ( volume_header->cluster_block_size != 16384 ) && ( volume_header->cluster_block_size != 32768 ) && ( volume_header->cluster_block_size != 65536 ) && ( volume_header->cluster_block_size != 131072 ) && ( volume_header->cluster_block_size != 262144 ) && ( volume_header->cluster_block_size != 524288 ) && ( volume_header->cluster_block_size != 1048576 ) && ( volume_header->cluster_block_size != 2097152 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported cluster block size: %" PRIu32 ".", function, volume_header->cluster_block_size ); return( -1 ); } if( ( volume_header->mft_entry_size == 0 ) || ( volume_header->mft_entry_size > 255 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported MFT entry size: %" PRIu32 ".", function, volume_header->mft_entry_size ); return( -1 ); } if( volume_header->mft_entry_size < 128 ) { if( volume_header->mft_entry_size >= (size32_t) ( ( UINT32_MAX / volume_header->cluster_block_size ) + 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid MFT entry size value out of bounds.", function ); return( -1 ); } volume_header->mft_entry_size *= volume_header->cluster_block_size; } else { /* The size is calculated as: 2 ^ ( 256 - value ) */ volume_header->mft_entry_size = 256 - volume_header->mft_entry_size; if( volume_header->mft_entry_size >= 32 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid MFT entry size value out of bounds.", function ); return( -1 ); } volume_header->mft_entry_size = (uint32_t) 1UL << volume_header->mft_entry_size; } if( ( (size_t) volume_header->mft_entry_size < sizeof( fsntfs_mft_entry_header_t ) ) || ( volume_header->mft_entry_size >= (uint32_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid MFT entry size: %" PRIu32 " value out of bounds.", function, volume_header->mft_entry_size ); return( -1 ); } if( ( volume_header->index_entry_size == 0 ) || ( volume_header->index_entry_size > 255 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported index entry size: %" PRIu32 ".", function, volume_header->index_entry_size ); return( -1 ); } if( volume_header->index_entry_size < 128 ) { if( volume_header->index_entry_size >= (size32_t) ( ( UINT32_MAX / volume_header->cluster_block_size ) + 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid index entry size value out of bounds.", function ); return( -1 ); } volume_header->index_entry_size *= volume_header->cluster_block_size; } else { /* The size is calculated as: 2 ^ ( 256 - value ) */ volume_header->index_entry_size = 256 - volume_header->index_entry_size; if( volume_header->index_entry_size >= 32 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid index entry size value out of bounds.", function ); return( -1 ); } volume_header->index_entry_size = (uint32_t) 1UL << volume_header->index_entry_size; } if( (size_t) volume_header->index_entry_size < sizeof( fsntfs_index_entry_header_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid index entry size: %" PRIu32 " value out of bounds.", function, volume_header->index_entry_size ); return( -1 ); } if( volume_size > (size64_t) ( ( UINT64_MAX / volume_header->bytes_per_sector ) + 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid volume size value out of bounds.", function ); return( -1 ); } volume_size *= volume_header->bytes_per_sector; volume_size += volume_header->bytes_per_sector; volume_header->mft_offset = mft_cluster_block_number * volume_header->cluster_block_size; volume_header->mirror_mft_offset = mirror_mft_cluster_block_number * volume_header->cluster_block_size; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: calculated cluster block size\t: %" PRIu32 "\n", function, volume_header->cluster_block_size ); libcnotify_printf( "%s: calculated MFT entry size\t\t: %" PRIu32 "\n", function, volume_header->mft_entry_size ); libcnotify_printf( "%s: calculated index entry size\t\t: %" PRIu32 "\n", function, volume_header->index_entry_size ); libcnotify_printf( "%s: calculated volume size\t\t: %" PRIu64 "\n", function, volume_size ); libcnotify_printf( "%s: calculated MFT offset\t\t: 0x%08" PRIx64 "\n", function, volume_header->mft_offset ); libcnotify_printf( "%s: calculated mirror MFT offset\t\t: 0x%08" PRIx64 "\n", function, volume_header->mirror_mft_offset ); libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ return( 1 ); } /* Reads the volume header * Returns 1 if successful or -1 on error */ int libfsntfs_volume_header_read_file_io_handle( libfsntfs_volume_header_t *volume_header, libbfio_handle_t *file_io_handle, off64_t file_offset, libcerror_error_t **error ) { uint8_t volume_header_data[ sizeof( fsntfs_volume_header_t ) ]; static char *function = "libfsntfs_volume_header_read_file_io_handle"; ssize_t read_count = 0; if( volume_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume header.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading volume header at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, file_offset, file_offset ); } #endif read_count = libbfio_handle_read_buffer_at_offset( file_io_handle, volume_header_data, sizeof( fsntfs_volume_header_t ), file_offset, error ); if( read_count != (ssize_t) sizeof( fsntfs_volume_header_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read volume header data at offset: %" PRIi64 " (0x%08" PRIx64 ").", function, file_offset, file_offset ); return( -1 ); } if( libfsntfs_volume_header_read_data( volume_header, volume_header_data, sizeof( fsntfs_volume_header_t ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read volume header data.", function ); return( -1 ); } return( 1 ); } /* Retrieves the bytes per sector * Returns 1 if successful or -1 on error */ int libfsntfs_volume_header_get_bytes_per_sector( libfsntfs_volume_header_t *volume_header, uint16_t *bytes_per_sector, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_header_get_bytes_per_sector"; if( volume_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume header.", function ); return( -1 ); } if( bytes_per_sector == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid bytes per sector.", function ); return( -1 ); } *bytes_per_sector = volume_header->bytes_per_sector; return( 1 ); } /* Retrieves the cluster block size * Returns 1 if successful or -1 on error */ int libfsntfs_volume_header_get_cluster_block_size( libfsntfs_volume_header_t *volume_header, size32_t *cluster_block_size, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_header_get_cluster_block_size"; if( volume_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume header.", function ); return( -1 ); } if( cluster_block_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid cluster block size.", function ); return( -1 ); } *cluster_block_size = volume_header->cluster_block_size; return( 1 ); } /* Retrieves the MFT entry size * Returns 1 if successful or -1 on error */ int libfsntfs_volume_header_get_mft_entry_size( libfsntfs_volume_header_t *volume_header, size32_t *mft_entry_size, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_header_get_mft_entry_size"; if( volume_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume header.", function ); return( -1 ); } if( mft_entry_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT entry size.", function ); return( -1 ); } *mft_entry_size = volume_header->mft_entry_size; return( 1 ); } /* Retrieves the index entry size * Returns 1 if successful or -1 on error */ int libfsntfs_volume_header_get_index_entry_size( libfsntfs_volume_header_t *volume_header, size32_t *index_entry_size, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_header_get_index_entry_size"; if( volume_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume header.", function ); return( -1 ); } if( index_entry_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index entry size.", function ); return( -1 ); } *index_entry_size = volume_header->index_entry_size; return( 1 ); } /* Retrieves the volume serial number * Returns 1 if successful or -1 on error */ int libfsntfs_volume_header_get_volume_serial_number( libfsntfs_volume_header_t *volume_header, uint64_t *volume_serial_number, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_header_get_volume_serial_number"; if( volume_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume header.", function ); return( -1 ); } if( volume_serial_number == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume serial number.", function ); return( -1 ); } *volume_serial_number = volume_header->volume_serial_number; return( 1 ); } /* Retrieves the MFT offset * Returns 1 if successful or -1 on error */ int libfsntfs_volume_header_get_mft_offset( libfsntfs_volume_header_t *volume_header, off64_t *mft_offset, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_header_get_mft_offset"; if( volume_header == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume header.", function ); return( -1 ); } if( mft_offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT offset.", function ); return( -1 ); } *mft_offset = volume_header->mft_offset; return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_volume_header.h ================================================ /* * The NTFS volume header functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_VOLUME_HEADER_H ) #define _LIBFSNTFS_VOLUME_HEADER_H #include #include #include "libfsntfs_libbfio.h" #include "libfsntfs_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_volume_header libfsntfs_volume_header_t; struct libfsntfs_volume_header { /* The cluster block size */ size32_t cluster_block_size; /* The number of bytes per sector */ uint16_t bytes_per_sector; /* The volume serial number */ uint64_t volume_serial_number; /* The MFT entry size */ uint32_t mft_entry_size; /* The index entry size */ uint32_t index_entry_size; /* The offset of the MFT */ off64_t mft_offset; /* The offset of the mirror MFT */ off64_t mirror_mft_offset; }; int libfsntfs_volume_header_initialize( libfsntfs_volume_header_t **volume_header, libcerror_error_t **error ); int libfsntfs_volume_header_free( libfsntfs_volume_header_t **volume_header, libcerror_error_t **error ); int libfsntfs_volume_header_read_data( libfsntfs_volume_header_t *volume_header, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_volume_header_read_file_io_handle( libfsntfs_volume_header_t *volume_header, libbfio_handle_t *file_io_handle, off64_t file_offset, libcerror_error_t **error ); int libfsntfs_volume_header_get_bytes_per_sector( libfsntfs_volume_header_t *volume_header, uint16_t *bytes_per_sector, libcerror_error_t **error ); int libfsntfs_volume_header_get_cluster_block_size( libfsntfs_volume_header_t *volume_header, size32_t *cluster_block_size, libcerror_error_t **error ); int libfsntfs_volume_header_get_mft_entry_size( libfsntfs_volume_header_t *volume_header, size32_t *mft_entry_size, libcerror_error_t **error ); int libfsntfs_volume_header_get_index_entry_size( libfsntfs_volume_header_t *volume_header, size32_t *index_entry_size, libcerror_error_t **error ); int libfsntfs_volume_header_get_volume_serial_number( libfsntfs_volume_header_t *volume_header, uint64_t *volume_serial_number, libcerror_error_t **error ); int libfsntfs_volume_header_get_mft_offset( libfsntfs_volume_header_t *volume_header, off64_t *mft_offset, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_VOLUME_HEADER_H ) */ ================================================ FILE: libfsntfs/libfsntfs_volume_information_attribute.c ================================================ /* * Volume information attribute ($VOLUME_INFORMATION) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_attribute.h" #include "libfsntfs_definitions.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_types.h" #include "libfsntfs_volume_information_attribute.h" #include "libfsntfs_volume_information_values.h" /* Retrieves the version * Returns 1 if successful or -1 on error */ int libfsntfs_volume_information_attribute_get_version( libfsntfs_attribute_t *attribute, uint8_t *major_version, uint8_t *minor_version, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; libfsntfs_volume_information_values_t *volume_information_values = NULL; static char *function = "libfsntfs_volume_information_attribute_get_version"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( internal_attribute->value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid attribute - missing value.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_INFORMATION ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } volume_information_values = (libfsntfs_volume_information_values_t *) internal_attribute->value; if( major_version == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid major version.", function ); return( -1 ); } if( minor_version == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid minor version.", function ); return( -1 ); } *major_version = volume_information_values->major_version; *minor_version = volume_information_values->minor_version; return( 1 ); } /* Retrieves the flags * Returns 1 if successful or -1 on error */ int libfsntfs_volume_information_attribute_get_flags( libfsntfs_attribute_t *attribute, uint16_t *flags, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; libfsntfs_volume_information_values_t *volume_information_values = NULL; static char *function = "libfsntfs_volume_information_attribute_get_flags"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( internal_attribute->value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid attribute - missing value.", function ); return( -1 ); } if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_INFORMATION ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } volume_information_values = (libfsntfs_volume_information_values_t *) internal_attribute->value; if( flags == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid flags.", function ); return( -1 ); } *flags = volume_information_values->flags; return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_volume_information_attribute.h ================================================ /* * Volume information attribute ($VOLUME_INFORMATION) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_VOLUME_INFORMATION_ATTRIBUTE_H ) #define _LIBFSNTFS_VOLUME_INFORMATION_ATTRIBUTE_H #include #include #include "libfsntfs_extern.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_types.h" #if defined( __cplusplus ) extern "C" { #endif LIBFSNTFS_EXTERN \ int libfsntfs_volume_information_attribute_get_version( libfsntfs_attribute_t *attribute, uint8_t *major_version, uint8_t *minor_version, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_information_attribute_get_flags( libfsntfs_attribute_t *attribute, uint16_t *flags, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_VOLUME_INFORMATION_ATTRIBUTE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_volume_information_values.c ================================================ /* * Volume information attribute ($VOLUME_INFORMATION) values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libfsntfs_debug.h" #include "libfsntfs_definitions.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_volume_information_values.h" #include "fsntfs_volume_information.h" /* Creates volume information values * Make sure the value volume_information_values is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_volume_information_values_initialize( libfsntfs_volume_information_values_t **volume_information_values, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_information_values_initialize"; if( volume_information_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume information values.", function ); return( -1 ); } if( *volume_information_values != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid volume information values value already set.", function ); return( -1 ); } *volume_information_values = memory_allocate_structure( libfsntfs_volume_information_values_t ); if( *volume_information_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create volume information values.", function ); goto on_error; } if( memory_set( *volume_information_values, 0, sizeof( libfsntfs_volume_information_values_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear volume information values.", function ); goto on_error; } return( 1 ); on_error: if( *volume_information_values != NULL ) { memory_free( *volume_information_values ); *volume_information_values = NULL; } return( -1 ); } /* Frees volume information values * Returns 1 if successful or -1 on error */ int libfsntfs_volume_information_values_free( libfsntfs_volume_information_values_t **volume_information_values, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_information_values_free"; if( volume_information_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume information values.", function ); return( -1 ); } if( *volume_information_values != NULL ) { memory_free( *volume_information_values ); *volume_information_values = NULL; } return( 1 ); } /* Reads the volume information values * Returns 1 if successful or -1 on error */ int libfsntfs_volume_information_values_read_data( libfsntfs_volume_information_values_t *volume_information_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_information_values_read_data"; if( volume_information_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume information values.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); return( -1 ); } if( data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: volume information data:\n", function ); libcnotify_print_data( data, data_size, 0 ); } #endif if( data_size != 12 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported volume information data size: %" PRIzd "\n", function, data_size ); return( -1 ); } volume_information_values->major_version = ( (fsntfs_volume_information_t *) data )->major_version; volume_information_values->minor_version = ( (fsntfs_volume_information_t *) data )->minor_version; byte_stream_copy_to_uint16_little_endian( ( (fsntfs_volume_information_t *) data )->flags, volume_information_values->flags ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: unknown1:\n", function ); libcnotify_print_data( ( (fsntfs_volume_information_t *) data )->unknown1, 8, 0 ); libcnotify_printf( "%s: major version\t\t: %" PRIu8 "\n", function, volume_information_values->major_version ); libcnotify_printf( "%s: minor version\t\t: %" PRIu8 "\n", function, volume_information_values->minor_version ); libcnotify_printf( "%s: flags\t\t\t: 0x%04" PRIx16 "\n", function, volume_information_values->flags ); libfsntfs_debug_print_volume_information_flags( volume_information_values->flags ); libcnotify_printf( "\n" ); libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ return( 1 ); } /* Reads the volume information values from an MFT attribute * Returns 1 if successful or -1 on error */ int libfsntfs_volume_information_values_read_from_mft_attribute( libfsntfs_volume_information_values_t *volume_information_values, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ) { uint8_t *data = NULL; static char *function = "libfsntfs_volume_information_values_read_from_mft_attribute"; size_t data_size = 0; uint32_t attribute_type = 0; int result = 0; if( volume_information_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume information values.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_type( mft_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve type from attribute.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_INFORMATION ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_mft_attribute_data_is_resident( mft_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if attribute data is resident.", function ); return( -1 ); } else if( result == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported non-resident attribute.", function ); return( 1 ); } if( libfsntfs_mft_attribute_get_resident_data( mft_attribute, &data, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve resident data from attribute.", function ); return( -1 ); } if( libfsntfs_volume_information_values_read_data( volume_information_values, data, data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read volume information values.", function ); return( -1 ); } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_volume_information_values.h ================================================ /* * Volume information attribute ($VOLUME_INFORMATION) values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_VOLUME_INFORMATION_VALUES_H ) #define _LIBFSNTFS_VOLUME_INFORMATION_VALUES_H #include #include #include "libfsntfs_libcerror.h" #include "libfsntfs_mft_attribute.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_volume_information_values libfsntfs_volume_information_values_t; struct libfsntfs_volume_information_values { /* The major version (number) */ uint8_t major_version; /* The minor version (number) */ uint8_t minor_version; /* The flags */ uint16_t flags; }; int libfsntfs_volume_information_values_initialize( libfsntfs_volume_information_values_t **volume_information_values, libcerror_error_t **error ); int libfsntfs_volume_information_values_free( libfsntfs_volume_information_values_t **volume_information_values, libcerror_error_t **error ); int libfsntfs_volume_information_values_read_data( libfsntfs_volume_information_values_t *volume_information_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_volume_information_values_read_from_mft_attribute( libfsntfs_volume_information_values_t *volume_information_values, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_VOLUME_INFORMATION_VALUES_H ) */ ================================================ FILE: libfsntfs/libfsntfs_volume_name_attribute.c ================================================ /* * Volume name attribute ($VOLUME_NAME) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "libfsntfs_attribute.h" #include "libfsntfs_definitions.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcthreads.h" #include "libfsntfs_types.h" #include "libfsntfs_volume_name_attribute.h" #include "libfsntfs_volume_name_values.h" /* Retrieves the size of the UTF-8 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_volume_name_attribute_get_utf8_name_size( libfsntfs_attribute_t *attribute, size_t *utf8_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_volume_name_attribute_get_utf8_name_size"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } if( libfsntfs_volume_name_values_get_utf8_name_size( (libfsntfs_volume_name_values_t *) internal_attribute->value, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-8 name.", function ); return( -1 ); } return( 1 ); } /* Retrieves the UTF-8 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_volume_name_attribute_get_utf8_name( libfsntfs_attribute_t *attribute, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_volume_name_attribute_get_utf8_name"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } if( libfsntfs_volume_name_values_get_utf8_name( (libfsntfs_volume_name_values_t *) internal_attribute->value, utf8_string, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 name.", function ); return( -1 ); } return( 1 ); } /* Retrieves the size of the UTF-16 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_volume_name_attribute_get_utf16_name_size( libfsntfs_attribute_t *attribute, size_t *utf16_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_volume_name_attribute_get_utf16_name_size"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } if( libfsntfs_volume_name_values_get_utf16_name_size( (libfsntfs_volume_name_values_t *) internal_attribute->value, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of UTF-16 name.", function ); return( -1 ); } return( 1 ); } /* Retrieves the UTF-16 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_volume_name_attribute_get_utf16_name( libfsntfs_attribute_t *attribute, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { libfsntfs_internal_attribute_t *internal_attribute = NULL; static char *function = "libfsntfs_volume_name_attribute_get_utf16_name"; uint32_t attribute_type = 0; if( attribute == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid attribute.", function ); return( -1 ); } internal_attribute = (libfsntfs_internal_attribute_t *) attribute; if( libfsntfs_internal_attribute_get_type( internal_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve attribute type.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } if( libfsntfs_volume_name_values_get_utf16_name( (libfsntfs_volume_name_values_t *) internal_attribute->value, utf16_string, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 name.", function ); return( -1 ); } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_volume_name_attribute.h ================================================ /* * Volume name attribute ($VOLUME_NAME) functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_VOLUME_NAME_ATTRIBUTE_H ) #define _LIBFSNTFS_VOLUME_NAME_ATTRIBUTE_H #include #include #include "libfsntfs_extern.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_types.h" #if defined( __cplusplus ) extern "C" { #endif LIBFSNTFS_EXTERN \ int libfsntfs_volume_name_attribute_get_utf8_name_size( libfsntfs_attribute_t *attribute, size_t *utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_name_attribute_get_utf8_name( libfsntfs_attribute_t *attribute, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_name_attribute_get_utf16_name_size( libfsntfs_attribute_t *attribute, size_t *utf16_string_size, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_name_attribute_get_utf16_name( libfsntfs_attribute_t *attribute, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_VOLUME_NAME_ATTRIBUTE_H ) */ ================================================ FILE: libfsntfs/libfsntfs_volume_name_values.c ================================================ /* * Volume name attribute ($VOLUME_NAME) values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include "libfsntfs_debug.h" #include "libfsntfs_definitions.h" #include "libfsntfs_libcerror.h" #include "libfsntfs_libcnotify.h" #include "libfsntfs_libuna.h" #include "libfsntfs_mft_attribute.h" #include "libfsntfs_volume_name_values.h" /* Creates volume name values * Make sure the value volume_name_values is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libfsntfs_volume_name_values_initialize( libfsntfs_volume_name_values_t **volume_name_values, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_name_values_initialize"; if( volume_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume name values.", function ); return( -1 ); } if( *volume_name_values != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid volume name values value already set.", function ); return( -1 ); } *volume_name_values = memory_allocate_structure( libfsntfs_volume_name_values_t ); if( *volume_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create volume name values.", function ); goto on_error; } if( memory_set( *volume_name_values, 0, sizeof( libfsntfs_volume_name_values_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear volume name values.", function ); goto on_error; } return( 1 ); on_error: if( *volume_name_values != NULL ) { memory_free( *volume_name_values ); *volume_name_values = NULL; } return( -1 ); } /* Frees volume name values * Returns 1 if successful or -1 on error */ int libfsntfs_volume_name_values_free( libfsntfs_volume_name_values_t **volume_name_values, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_name_values_free"; if( volume_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume name values.", function ); return( -1 ); } if( *volume_name_values != NULL ) { if( ( *volume_name_values )->name != NULL ) { memory_free( ( *volume_name_values )->name ); } memory_free( *volume_name_values ); *volume_name_values = NULL; } return( 1 ); } /* Reads the volume name values * Returns 1 if successful or -1 on error */ int libfsntfs_volume_name_values_read_data( libfsntfs_volume_name_values_t *volume_name_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_name_values_read_data"; if( volume_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume name values.", function ); return( -1 ); } if( volume_name_values->name != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid volume name values - name already set.", function ); return( -1 ); } /* The volume name attribute can contain an empty volume name */ if( data_size > 0 ) { if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data.", function ); goto on_error; } } if( data_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data size value out of bounds.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: volume name data:\n", function ); libcnotify_print_data( data, data_size, 0 ); } #endif /* The size of the data can be 0 if the name is not set. */ if( data_size > 0 ) { volume_name_values->name = (uint8_t *) memory_allocate( sizeof( uint8_t ) * data_size ); if( volume_name_values->name == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create name.", function ); goto on_error; } volume_name_values->name_size = data_size; if( memory_copy( volume_name_values->name, data, volume_name_values->name_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy volume name.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( libfsntfs_debug_print_utf16_string_value( function, "name\t\t\t\t", volume_name_values->name, volume_name_values->name_size, LIBUNA_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print UTF-16 string value.", function ); goto on_error; } libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ } return( 1 ); on_error: if( volume_name_values->name != NULL ) { memory_free( volume_name_values->name ); volume_name_values->name = NULL; } volume_name_values->name_size = 0; return( -1 ); } /* Reads the volume name values from an MFT attribute * Returns 1 if successful or -1 on error */ int libfsntfs_volume_name_values_read_from_mft_attribute( libfsntfs_volume_name_values_t *volume_name_values, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ) { uint8_t *data = NULL; static char *function = "libfsntfs_volume_name_values_read_from_mft_attribute"; size_t data_size = 0; uint32_t attribute_type = 0; int result = 0; if( volume_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume name values.", function ); return( -1 ); } if( libfsntfs_mft_attribute_get_type( mft_attribute, &attribute_type, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve type from attribute.", function ); return( -1 ); } if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported attribute type.", function ); return( -1 ); } result = libfsntfs_mft_attribute_data_is_resident( mft_attribute, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if attribute data is resident.", function ); return( -1 ); } else if( result == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported non-resident attribute.", function ); return( 1 ); } if( libfsntfs_mft_attribute_get_resident_data( mft_attribute, &data, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve resident data from attribute.", function ); return( -1 ); } if( libfsntfs_volume_name_values_read_data( volume_name_values, data, data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read volume name values.", function ); return( -1 ); } return( 1 ); } /* Retrieves the size of the UTF-8 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_volume_name_values_get_utf8_name_size( libfsntfs_volume_name_values_t *volume_name_values, size_t *utf8_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_name_values_get_utf8_name_size"; if( volume_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume name values.", function ); return( -1 ); } if( volume_name_values->name_size == 0 ) { if( utf8_string_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-8 string size.", function ); return( -1 ); } *utf8_string_size = 0; } else { if( libuna_utf8_string_size_from_utf16_stream( volume_name_values->name, (size_t) volume_name_values->name_size, LIBUNA_ENDIAN_LITTLE, utf8_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 string size.", function ); return( -1 ); } } return( 1 ); } /* Retrieves the UTF-8 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_volume_name_values_get_utf8_name( libfsntfs_volume_name_values_t *volume_name_values, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_name_values_get_utf8_name"; if( volume_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume name values.", function ); return( -1 ); } if( volume_name_values->name_size == 0 ) { if( utf8_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-8 string.", function ); return( -1 ); } if( utf8_string_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-8 string size value exceeds maximum.", function ); return( -1 ); } if( utf8_string_size < 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: UTF-8 string size value too small.", function ); return( -1 ); } utf8_string[ 0 ] = 0; } else { if( libuna_utf8_string_copy_from_utf16_stream( utf8_string, utf8_string_size, volume_name_values->name, (size_t) volume_name_values->name_size, LIBUNA_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-8 string.", function ); return( -1 ); } } return( 1 ); } /* Retrieves the size of the UTF-16 encoded name * The returned size includes the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_volume_name_values_get_utf16_name_size( libfsntfs_volume_name_values_t *volume_name_values, size_t *utf16_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_name_values_get_utf16_name_size"; if( volume_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume name values.", function ); return( -1 ); } if( volume_name_values->name_size == 0 ) { if( utf16_string_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-16 string size.", function ); return( -1 ); } *utf16_string_size = 0; } else { if( libuna_utf16_string_size_from_utf16_stream( volume_name_values->name, (size_t) volume_name_values->name_size, LIBUNA_ENDIAN_LITTLE, utf16_string_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 string size.", function ); return( -1 ); } } return( 1 ); } /* Retrieves the UTF-16 encoded name * The size should include the end of string character * Returns 1 if successful or -1 on error */ int libfsntfs_volume_name_values_get_utf16_name( libfsntfs_volume_name_values_t *volume_name_values, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ) { static char *function = "libfsntfs_volume_name_values_get_utf16_name"; if( volume_name_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume name values.", function ); return( -1 ); } if( volume_name_values->name_size == 0 ) { if( utf16_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-16 string.", function ); return( -1 ); } if( utf16_string_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid UTF-16 string size value exceeds maximum.", function ); return( -1 ); } if( utf16_string_size < 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: UTF-16 string size value too small.", function ); return( -1 ); } utf16_string[ 0 ] = 0; } else { if( libuna_utf16_string_copy_from_utf16_stream( utf16_string, utf16_string_size, volume_name_values->name, (size_t) volume_name_values->name_size, LIBUNA_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve UTF-16 string.", function ); return( -1 ); } } return( 1 ); } ================================================ FILE: libfsntfs/libfsntfs_volume_name_values.h ================================================ /* * Volume name attribute ($VOLUME_NAME) values functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _LIBFSNTFS_VOLUME_NAME_VALUES_H ) #define _LIBFSNTFS_VOLUME_NAME_VALUES_H #include #include #include "libfsntfs_libcerror.h" #include "libfsntfs_mft_attribute.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct libfsntfs_volume_name_values libfsntfs_volume_name_values_t; struct libfsntfs_volume_name_values { /* The name */ uint8_t *name; /* The name size */ size_t name_size; }; int libfsntfs_volume_name_values_initialize( libfsntfs_volume_name_values_t **volume_name_values, libcerror_error_t **error ); int libfsntfs_volume_name_values_free( libfsntfs_volume_name_values_t **volume_name_values, libcerror_error_t **error ); int libfsntfs_volume_name_values_read_data( libfsntfs_volume_name_values_t *volume_name_values, const uint8_t *data, size_t data_size, libcerror_error_t **error ); int libfsntfs_volume_name_values_read_from_mft_attribute( libfsntfs_volume_name_values_t *volume_name_values, libfsntfs_mft_attribute_t *mft_attribute, libcerror_error_t **error ); int libfsntfs_volume_name_values_get_utf8_name_size( libfsntfs_volume_name_values_t *volume_name_values, size_t *utf8_string_size, libcerror_error_t **error ); int libfsntfs_volume_name_values_get_utf8_name( libfsntfs_volume_name_values_t *volume_name_values, uint8_t *utf8_string, size_t utf8_string_size, libcerror_error_t **error ); int libfsntfs_volume_name_values_get_utf16_name_size( libfsntfs_volume_name_values_t *volume_name_values, size_t *utf16_string_size, libcerror_error_t **error ); int libfsntfs_volume_name_values_get_utf16_name( libfsntfs_volume_name_values_t *volume_name_values, uint16_t *utf16_string, size_t utf16_string_size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _LIBFSNTFS_VOLUME_NAME_VALUES_H ) */ ================================================ FILE: libfsntfs.ini ================================================ [project] name: "libfsntfs" status: "experimental" year_of_creation: "2010" data_format: "New Technology File System (NTFS)" documentation_url: "https://github.com/libyal/libfsntfs/tree/main/documentation" features: ["debug_output", "nuget", "ossfuzz", "python_bindings", "tools"] [library] features: ["pthread", "wide_character_type"] public_types: ["attribute", "attribute_list_entry", "data_stream", "file_entry", "mft_metadata_file", "usn_change_journal", "volume"] [tools] build_dependencies: ["crypto", "fuse"] description: "Several tools for reading New Technology File System (NTFS) volumes" names: ["fsntfsinfo", "fsntfsmount"] [info_tool] source_description: "a New Technology File System (NTFS) volume" source_type: "volume" [mount_tool] features: ["offset", "symbolic_link"] file_entry_access_time_type: "filetime" file_entry_creation_time_type: "filetime" file_entry_inode_change_time_type: "filetime" file_entry_modification_time_type: "filetime" file_entry_type: "file_entry" file_system_type: "volume" mounted_description: "a file system contained in the NTFS volume" source: "image.raw" source_description: "a NTFS volume" source_description_long: "a New Technology File System (NTFS) volume" source_type: "volume" [tests] profiles: ["libfsntfs", "pyfsntfs", "fsntfsinfo", "fsntfsinfo_bodyfile_fs", "fsntfsinfo_bodyfile_mft", "fsntfsinfo_fs", "fsntfsinfo_mft", "fsntfsinfo_usn"] option_sets: ["offset"] info_tool_option_sets: ["offset"] info_tool_options_per_profile: ["", "-H", "-Eall", "-U"] info_tool_profiles: ["fsntfsinfo", "fsntfsinfo_fs", "fsntfsinfo_mft", "fsntfsinfo_usn"] ================================================ FILE: libfsntfs.nuspec ================================================ libfsntfs 20260208 Joachim Metz joachimmetz LGPL-3.0-or-later https://github.com/libyal/libfsntfs false libfsntfs Library to access the New Technology File System (NTFS) format Release of libfsntfs 20260208 Copyright (C) 2010-2026 native ================================================ FILE: libfsntfs.pc.in ================================================ prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libfsntfs Description: Library to access the New Technology File System (NTFS) format Version: @VERSION@ Libs: -L${libdir} -lfsntfs Libs.private: @ax_libbfio_pc_libs_private@ @ax_libcdata_pc_libs_private@ @ax_libcerror_pc_libs_private@ @ax_libcfile_pc_libs_private@ @ax_libclocale_pc_libs_private@ @ax_libcnotify_pc_libs_private@ @ax_libcpath_pc_libs_private@ @ax_libcsplit_pc_libs_private@ @ax_libcthreads_pc_libs_private@ @ax_libfcache_pc_libs_private@ @ax_libfdata_pc_libs_private@ @ax_libfdatetime_pc_libs_private@ @ax_libfguid_pc_libs_private@ @ax_libfwnt_pc_libs_private@ @ax_libuna_pc_libs_private@ @ax_pthread_pc_libs_private@ Cflags: -I${includedir} ================================================ FILE: libfsntfs.spec.in ================================================ Name: libfsntfs Version: @VERSION@ Release: 1 Summary: Library to access the New Technology File System (NTFS) format Group: System Environment/Libraries License: LGPL-3.0-or-later Source: %{name}-%{version}.tar.gz URL: https://github.com/libyal/libfsntfs @libfsntfs_spec_requires@ @ax_libbfio_spec_requires@ @ax_libcdata_spec_requires@ @ax_libcerror_spec_requires@ @ax_libcfile_spec_requires@ @ax_libclocale_spec_requires@ @ax_libcnotify_spec_requires@ @ax_libcpath_spec_requires@ @ax_libcsplit_spec_requires@ @ax_libcthreads_spec_requires@ @ax_libfcache_spec_requires@ @ax_libfdata_spec_requires@ @ax_libfdatetime_spec_requires@ @ax_libfguid_spec_requires@ @ax_libfwnt_spec_requires@ @ax_libuna_spec_requires@ BuildRequires: gcc @ax_libbfio_spec_build_requires@ @ax_libcdata_spec_build_requires@ @ax_libcerror_spec_build_requires@ @ax_libcfile_spec_build_requires@ @ax_libclocale_spec_build_requires@ @ax_libcnotify_spec_build_requires@ @ax_libcpath_spec_build_requires@ @ax_libcsplit_spec_build_requires@ @ax_libcthreads_spec_build_requires@ @ax_libfcache_spec_build_requires@ @ax_libfdata_spec_build_requires@ @ax_libfdatetime_spec_build_requires@ @ax_libfguid_spec_build_requires@ @ax_libfwnt_spec_build_requires@ @ax_libuna_spec_build_requires@ %description -n libfsntfs Library to access the New Technology File System (NTFS) format %package -n libfsntfs-static Summary: Library to access the New Technology File System (NTFS) format Group: Development/Libraries Requires: libfsntfs = %{version}-%{release} %description -n libfsntfs-static Static library version of libfsntfs. %package -n libfsntfs-devel Summary: Header files and libraries for developing applications for libfsntfs Group: Development/Libraries Requires: libfsntfs = %{version}-%{release} %description -n libfsntfs-devel Header files and libraries for developing applications for libfsntfs. %package -n libfsntfs-python3 Summary: Python 3 bindings for libfsntfs Group: System Environment/Libraries Requires: libfsntfs = %{version}-%{release} python3 BuildRequires: python3-devel python3-setuptools %description -n libfsntfs-python3 Python 3 bindings for libfsntfs %package -n libfsntfs-tools Summary: Several tools for reading New Technology File System (NTFS) volumes Group: Applications/System Requires: libfsntfs = %{version}-%{release} @ax_libcrypto_spec_requires@ @ax_libfuse_spec_requires@ @ax_libfusn_spec_requires@ @ax_libhmac_spec_requires@ @libfsntfs_spec_tools_build_requires@ @ax_libcrypto_spec_build_requires@ @ax_libfuse_spec_build_requires@ @ax_libfusn_spec_build_requires@ @ax_libhmac_spec_build_requires@ %description -n libfsntfs-tools Several tools for reading New Technology File System (NTFS) volumes %prep %setup -q %build %configure --prefix=/usr --libdir=%{_libdir} --mandir=%{_mandir} --enable-python make %{?_smp_mflags} %install rm -rf %{buildroot} %make_install %clean rm -rf %{buildroot} %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %files -n libfsntfs %license COPYING COPYING.LESSER %doc AUTHORS README %{_libdir}/*.so.* %files -n libfsntfs-static %license COPYING COPYING.LESSER %doc AUTHORS README %{_libdir}/*.a %files -n libfsntfs-devel %license COPYING COPYING.LESSER %doc AUTHORS README %{_libdir}/*.so %{_libdir}/pkgconfig/libfsntfs.pc %{_includedir}/* %{_mandir}/man3/* %files -n libfsntfs-python3 %license COPYING COPYING.LESSER %doc AUTHORS README %{_libdir}/python3*/site-packages/*.a %{_libdir}/python3*/site-packages/*.so %files -n libfsntfs-tools %license COPYING COPYING.LESSER %doc AUTHORS README %{_bindir}/* %{_mandir}/man1/* %changelog * @SPEC_DATE@ Joachim Metz @VERSION@-1 - Auto-generated ================================================ FILE: m4/common.m4 ================================================ dnl Checks for common headers and functions dnl dnl Version: 20241013 dnl Function to test if a certain feature was disabled AC_DEFUN([AX_COMMON_ARG_DISABLE], [AC_ARG_ENABLE( [$1], [AS_HELP_STRING( [--disable-$1], [$3])], [ac_cv_enable_$2=$enableval], [ac_cv_enable_$2="yes"])dnl AC_CACHE_CHECK( [whether to disable $3], [ac_cv_enable_$2], [ac_cv_enable_$2="yes"])dnl ]) dnl Function to test if a certain feature was enabled AC_DEFUN([AX_COMMON_ARG_ENABLE], [AC_ARG_ENABLE( [$1], [AS_HELP_STRING( [--enable-$1], [$3 @<:@default=$4@:>@])], [ac_cv_enable_$2=$enableval], [ac_cv_enable_$2=$4])dnl AC_CACHE_CHECK( [whether to enable $3], [ac_cv_enable_$2], [ac_cv_enable_$2=$4])dnl ]) dnl Function to test if the location of a certain feature was provided AC_DEFUN([AX_COMMON_ARG_WITH], [AC_ARG_WITH( [$1], [AS_HELP_STRING( [--with-$1[[=$5]]], [$3 @<:@default=$4@:>@])], [ac_cv_with_$2=$withval], [ac_cv_with_$2=$4])dnl AC_CACHE_CHECK( [whether to use $3], [ac_cv_with_$2], [ac_cv_with_$2=$4])dnl ]) dnl Function to detect whether shared library support should be disabled AC_DEFUN([AX_COMMON_CHECK_DISABLE_SHARED_LIBS], [AX_COMMON_ARG_DISABLE( [shared-libs], [shared_libs], [disable shared library support]) ]) dnl Function to detect whether debug output should be enabled AC_DEFUN([AX_COMMON_CHECK_ENABLE_DEBUG_OUTPUT], [AX_COMMON_ARG_ENABLE( [debug-output], [debug_output], [enable debug output], [no]) AS_IF( [test "x$ac_cv_enable_debug_output" != xno ], [AC_DEFINE( [HAVE_DEBUG_OUTPUT], [1], [Define to 1 if debug output should be used.]) ac_cv_enable_debug_output=yes]) ]) dnl Function to detect whether static executables support should be enabled AC_DEFUN([AX_COMMON_CHECK_ENABLE_STATIC_EXECUTABLES], [AX_COMMON_ARG_ENABLE( [static-executables], [static_executables], [build static executables (binaries)], [no]) AS_IF( [test "x$ac_cv_enable_static_executables" != xno], [STATIC_LDFLAGS="-all-static"; AC_SUBST( [STATIC_LDFLAGS]) ac_cv_enable_static_executables=yes enable_shared=no]) ]) dnl Function to detect whether verbose output should be enabled AC_DEFUN([AX_COMMON_CHECK_ENABLE_VERBOSE_OUTPUT], [AX_COMMON_ARG_ENABLE( [verbose-output], [verbose_output], [enable verbose output], [no]) AS_IF( [test "x$ac_cv_enable_verbose_output" != xno ], [AC_DEFINE( [HAVE_VERBOSE_OUTPUT], [1], [Define to 1 if verbose output should be used.]) ac_cv_enable_verbose_output=yes]) ]) dnl Function to detect whether wide character type support should be enabled AC_DEFUN([AX_COMMON_CHECK_ENABLE_WIDE_CHARACTER_TYPE], [AX_COMMON_ARG_ENABLE( [wide-character-type], [wide_character_type], [enable wide character type support], [no]) ]) dnl Function to detect whether WINAPI support should be enabled AC_DEFUN([AX_COMMON_CHECK_ENABLE_WINAPI], [AX_COMMON_ARG_ENABLE( [winapi], [winapi], [enable WINAPI support for cross-compilation], [auto-detect]) AS_IF( [test "x$ac_cv_enable_winapi" = xauto-detect], [ac_common_check_winapi_target_string="$target" AS_IF( [test "x$ac_common_check_winapi_target_string" = x], [ac_common_check_winapi_target_string="$host"]) AS_CASE( [$ac_common_check_winapi_target_string], [*mingw*],[AC_MSG_NOTICE( [detected MinGW enabling WINAPI support for cross-compilation]) ac_cv_enable_winapi=yes], [*msys*],[AC_MSG_NOTICE( [detected MSYS enabling WINAPI support for cross-compilation]) ac_cv_enable_winapi=yes], [*],[ac_cv_enable_winapi=no]) ]) ]) dnl Function to detect whether printf conversion specifier "%jd" is available AC_DEFUN([AX_COMMON_CHECK_FUNC_PRINTF_JD], [AC_MSG_CHECKING( [whether printf supports the conversion specifier "%jd"]) SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wall -Werror" AC_LANG_PUSH(C) dnl First try to see if compilation and linkage without a parameter succeeds AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#include ]], [[printf( "%jd" ); ]] )], [ac_cv_cv_have_printf_jd=no], [ac_cv_cv_have_printf_jd=yes]) dnl Second try to see if compilation and linkage with a parameter succeeds AS_IF( [test "x$ac_cv_cv_have_printf_jd" = xyes], [AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#include #include ]], [[printf( "%jd", (off_t) 10 ); ]] )], [ac_cv_cv_have_printf_jd=yes], [ac_cv_cv_have_printf_jd=no]) ]) dnl Third try to see if the program runs correctly AS_IF( [test "x$ac_cv_cv_have_printf_jd" = xyes], [AC_RUN_IFELSE( [AC_LANG_PROGRAM( [[#include #include ]], [[char string[ 3 ]; if( snprintf( string, 3, "%jd", (off_t) 10 ) < 0 ) return( 1 ); if( ( string[ 0 ] != '1' ) || ( string[ 1 ] != '0' ) ) return( 1 ); ]] )], [ac_cv_cv_have_printf_jd=yes], [ac_cv_cv_have_printf_jd=no], [ac_cv_cv_have_printf_jd=undetermined]) ]) AC_LANG_POP(C) CFLAGS="$SAVE_CFLAGS" AS_IF( [test "x$ac_cv_cv_have_printf_jd" = xyes], [AC_MSG_RESULT( [yes]) AC_DEFINE( [HAVE_PRINTF_JD], [1], [Define to 1 whether printf supports the conversion specifier "%jd".]) ], [AC_MSG_RESULT( [$ac_cv_cv_have_printf_jd]) ]) ]) dnl Function to detect whether printf conversion specifier "%zd" is available AC_DEFUN([AX_COMMON_CHECK_FUNC_PRINTF_ZD], [AC_MSG_CHECKING( [whether printf supports the conversion specifier "%zd"]) SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wall -Werror" AC_LANG_PUSH(C) dnl First try to see if compilation and linkage without a parameter succeeds AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#include ]], [[printf( "%zd" ); ]] )], [ac_cv_cv_have_printf_zd=no], [ac_cv_cv_have_printf_zd=yes]) dnl Second try to see if compilation and linkage with a parameter succeeds AS_IF( [test "x$ac_cv_cv_have_printf_zd" = xyes], [AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#include #include ]], [[printf( "%zd", (size_t) 10 ); ]] )], [ac_cv_cv_have_printf_zd=yes], [ac_cv_cv_have_printf_zd=no]) ]) dnl Third try to see if the program runs correctly AS_IF( [test "x$ac_cv_cv_have_printf_zd" = xyes], [AC_RUN_IFELSE( [AC_LANG_PROGRAM( [[#include #include ]], [[char string[ 3 ]; if( snprintf( string, 3, "%zd", (size_t) 10 ) < 0 ) return( 1 ); if( ( string[ 0 ] != '1' ) || ( string[ 1 ] != '0' ) ) return( 1 ); ]] )], [ac_cv_cv_have_printf_zd=yes], [ac_cv_cv_have_printf_zd=no], [ac_cv_cv_have_printf_zd=undetermined]) ]) AC_LANG_POP(C) CFLAGS="$SAVE_CFLAGS" AS_IF( [test "x$ac_cv_cv_have_printf_zd" = xyes], [AC_MSG_RESULT( [yes]) AC_DEFINE( [HAVE_PRINTF_ZD], [1], [Define to 1 whether printf supports the conversion specifier "%zd".]) ], [AC_MSG_RESULT( [$ac_cv_cv_have_printf_zd]) ]) ]) dnl Function to detect if common dependencies are available AC_DEFUN([AX_COMMON_CHECK_LOCAL], [dnl Headers included in common/common.h AS_IF( [test "x$ac_cv_enable_winapi" = xyes], [AC_CHECK_HEADERS([windows.h]) AS_IF( [test "x$ac_cv_header_windows_h" = xno], [AC_MSG_FAILURE( [Missing header: windows.h header is required to compile with winapi support], [1]) ]) ]) AS_IF( [test "x$ac_cv_enable_winapi" = xno], [AC_CHECK_HEADERS([libintl.h]) ]) dnl Headers included in common/types.h AC_CHECK_HEADERS([limits.h]) dnl Headers included in common/memory.h and common/narrow_string.h AC_CHECK_HEADERS([stdlib.h string.h]) dnl Headers included in common/wide_string.h AC_CHECK_HEADERS([wchar.h wctype.h]) dnl File stream functions used in common/file_stream.h AC_CHECK_FUNCS([fclose feof fgets fopen fread fseeko fseeko64 fwrite vfprintf]) AS_IF( [test "x$ac_cv_func_fclose" != xyes], [AC_MSG_FAILURE( [Missing function: fclose], [1]) ]) AS_IF( [test "x$ac_cv_func_feof" != xyes], [AC_MSG_FAILURE( [Missing function: feof], [1]) ]) AS_IF( [test "x$ac_cv_func_fgets" != xyes], [AC_MSG_FAILURE( [Missing function: fgets], [1]) ]) AS_IF( [test "x$ac_cv_func_fopen" != xyes], [AC_MSG_FAILURE( [Missing function: fopen], [1]) ]) AS_IF( [test "x$ac_cv_func_fread" != xyes], [AC_MSG_FAILURE( [Missing function: fread], [1]) ]) AS_IF( [test "x$ac_cv_func_fseeko" != xyes && test "x$ac_cv_func_fseeko64" != xyes], [AC_MSG_FAILURE( [Missing function: fseeko and fseeko64], [1]) ]) AS_IF( [test "x$ac_cv_func_fwrite" != xyes], [AC_MSG_FAILURE( [Missing function: fwrite], [1]) ]) AS_IF( [test "x$ac_cv_func_vfprintf" != xyes], [AC_MSG_FAILURE( [Missing function: vfprintf], [1]) ]) AS_IF( [test "x$ac_cv_enable_wide_character_type" != xno], [AC_CHECK_FUNCS([fgetws]) AS_IF( [test "x$ac_cv_func_fgetws" != xyes], [AC_MSG_FAILURE( [Missing function: fgetws], [1]) ]) ]) dnl Memory functions used in common/memory.h AC_CHECK_FUNCS([free malloc memcmp memcpy memset realloc]) AS_IF( [test "x$ac_cv_func_free" != xyes], [AC_MSG_FAILURE( [Missing function: free], [1]) ]) AS_IF( [test "x$ac_cv_func_malloc" != xyes], [AC_MSG_FAILURE( [Missing function: malloc], [1]) ]) AS_IF( [test "x$ac_cv_func_memcmp" != xyes], [AC_MSG_FAILURE( [Missing function: memcmp], [1]) ]) AS_IF( [test "x$ac_cv_func_memcpy" != xyes], [AC_MSG_FAILURE( [Missing function: memcpy], [1]) ]) AS_IF( [test "x$ac_cv_func_memset" != xyes], [AC_MSG_FAILURE( [Missing function: memset], [1]) ]) AS_IF( [test "x$ac_cv_func_realloc" != xyes], [AC_MSG_FAILURE( [Missing function: realloc], [1]) ]) dnl Narrow character string functions used in common/narrow_string.h AC_CHECK_FUNCS([memchr memrchr snprintf sscanf strcasecmp strchr strlen strncasecmp strncmp strncpy strnicmp strrchr strstr vsnprintf]) AS_IF( [test "x$ac_cv_func_memchr" != xyes && test "x$ac_cv_func_strchr" != xyes], [AC_MSG_FAILURE( [Missing functions: memchr and strchr], [1]) ]) AS_IF( [test "x$ac_cv_func_memcmp" != xyes && test "x$ac_cv_func_strncmp" != xyes], [AC_MSG_FAILURE( [Missing functions: memcmp and strncmp], [1]) ]) AS_IF( [test "x$ac_cv_func_memcpy" != xyes && test "x$ac_cv_func_strncpy" != xyes], [AC_MSG_FAILURE( [Missing functions: memcpy and strncpy], [1]) ]) AS_IF( [test "x$ac_cv_func_memrchr" = xyes], [AC_CHECK_DECLS([memrchr]) AS_IF( [test "x$ac_cv_decl_memrchr" != xyes], [ac_cv_func_memrchr=no]) ]) AS_IF( [test "x$ac_cv_func_memrchr" != xyes && test "x$ac_cv_func_strrchr" != xyes], [AC_MSG_FAILURE( [Missing functions: strrchr and memrchr], [1]) ]) AS_IF( [test "x$ac_cv_func_snprintf" != xyes], [AC_MSG_FAILURE( [Missing function: snprintf], [1]) ]) AS_IF( [test "x$ac_cv_func_sscanf" != xyes], [AC_MSG_FAILURE( [Missing function: sscanf], [1]) ]) AS_IF( [test "x$ac_cv_func_strlen" != xyes], [AC_MSG_FAILURE( [Missing function: strlen], [1]) ]) AS_IF( [test "x$ac_cv_func_strcasecmp" != xyes && test "x$ac_cv_func_strncasecmp" != xyes && test "x$ac_cv_func_strnicmp" != xyes], [AC_MSG_FAILURE( [Missing functions: strncasecmp, strcasecmp and strnicmp], [1]) ]) AS_IF( [test "x$ac_cv_func_strstr" != xyes], [AC_MSG_FAILURE( [Missing function: strstr], [1]) ]) AS_IF( [test "x$ac_cv_func_vsnprintf" != xyes], [AC_MSG_FAILURE( [Missing function: vsnprintf], [1]) ]) dnl Wide character string functions used in common/wide_string.h AS_IF( [test "x$ac_cv_enable_wide_character_type" != xno], [AC_CHECK_FUNCS([swprintf towlower wcscasecmp wcschr wcslen wcsncasecmp wcsncmp wcsncpy wcsnicmp wcsrchr wcsstr wmemchr wmemcmp wmemcpy wmemrchr]) AS_IF( [test "x$ac_cv_func_swprintf" != xyes], [AC_MSG_FAILURE( [Missing function: swprintf], [1]) ]) AS_IF( [test "x$ac_cv_func_wmemchr" != xyes && test "x$ac_cv_func_wcschr" != xyes], [AC_MSG_FAILURE( [Missing functions: wmemchr and wcschr], [1]) ]) AS_IF( [test "x$ac_cv_func_wmemcmp" != xyes && test "x$ac_cv_func_wcsncmp" != xyes], [AC_MSG_FAILURE( [Missing functions: wmemcmp and wcsncmp], [1]) ]) AS_IF( [test "x$ac_cv_func_wmemcpy" != xyes && test "x$ac_cv_func_wcsncpy" != xyes], [AC_MSG_FAILURE( [Missing functions: wmemcpy and wcsncpy], [1]) ]) AS_IF( [test "x$ac_cv_func_wmemrchr" != xyes && test "x$ac_cv_func_wcsrchr" != xyes], [AC_MSG_FAILURE( [Missing functions: wmemrchr and wcsrchr], [1]) ]) AS_IF( [test "x$ac_cv_func_wcslen" != xyes], [AC_MSG_FAILURE( [Missing function: wcslen], [1]) ]) AS_IF( [test "x$ac_cv_func_wcsncasecmp" != xyes && test "x$ac_cv_func_wcscasecmp" != xyes && test "x$ac_cv_func_wcsnicmp" != xyes && test "x$ac_cv_func_towlower" != xyes], [AC_MSG_FAILURE( [Missing functions: wcsncasecmp, wcscasecmp, wcsnicmp and towlower], [1]) ]) AS_IF( [test "x$ac_cv_func_wcsstr" != xyes], [AC_MSG_FAILURE( [Missing function: wcsstr], [1]) ]) ]) dnl Check for printf conversion specifier support AX_COMMON_CHECK_FUNC_PRINTF_JD AX_COMMON_CHECK_FUNC_PRINTF_ZD ]) dnl Function to test if a library with a specific definition is available AC_DEFUN([AX_CHECK_LIB_DEFINITION], [AC_CACHE_CHECK( [if `$2' is defined], [ac_cv_$1_definition_$2], [AC_LANG_PUSH(C) AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#include <$1.h>]], [[int test = $2; return( 0 ); ]] )], [ac_cv_$1_definition_$2=yes], [ac_cv_$1_definition_$2=no]) AC_LANG_POP(C)]) AS_IF( [test "x$ac_cv_$1_definition_$2" != xyes], [ac_cv_$1=no]) ]) dnl Function to test if a library with specific definitions is available AC_DEFUN([AX_CHECK_LIB_DEFINITIONS], [m4_foreach( [definition], [$2], [AX_CHECK_LIB_DEFINITION( [$1], [definition]) ]) ]) dnl Function to test if a library with specific functions is available AC_DEFUN([AX_CHECK_LIB_FUNCTIONS], [m4_foreach( [function], [$3], [AC_CHECK_LIB( [$2], [function], [ac_cv_$1_dummy=yes], [ac_cv_$1=no]) ]) ]) dnl Function to check if an user specified library directory exists AC_DEFUN([AX_CHECK_LIB_DIRECTORY_EXISTS], [AS_IF( [test -d "$ac_cv_with_$1"], [CFLAGS="$CFLAGS -I${ac_cv_with_$1}/include" LDFLAGS="$LDFLAGS -L${ac_cv_with_$1}/lib"], [AC_MSG_FAILURE( [no such directory: $ac_cv_with_$1], [1]) ]) ]) dnl Function to warn if no supported library was found in an user specified directory AC_DEFUN([AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE], [AS_IF( [test "x$ac_cv_$1" != xyes && test "x$ac_cv_with_$1" != x && test "x$ac_cv_with_$1" != xauto-detect && test "x$ac_cv_with_$1" != xyes], [AC_MSG_FAILURE( [unable to find supported $1 in directory: $ac_cv_with_$1], [1]) ]) ]) ================================================ FILE: m4/libbfio.m4 ================================================ dnl Checks for libbfio required headers and functions dnl dnl Version: 20240518 dnl Function to detect if libbfio is available dnl ac_libbfio_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l arguments AC_DEFUN([AX_LIBBFIO_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_libbfio" = xno], [ac_cv_libbfio=no], [ac_cv_libbfio=check dnl Check if the directory provided as parameter exists dnl For both --with-libbfio which returns "yes" and --with-libbfio= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_libbfio" != x && test "x$ac_cv_with_libbfio" != xauto-detect && test "x$ac_cv_with_libbfio" != xyes], [AX_CHECK_LIB_DIRECTORY_EXISTS([libbfio])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [libbfio], [libbfio >= 20201125], [ac_cv_libbfio=yes], [ac_cv_libbfio=check]) ]) AS_IF( [test "x$ac_cv_libbfio" = xyes && test "x$ac_cv_enable_wide_character_type" != xno], [AC_CACHE_CHECK( [whether libbfio/features.h defines LIBBFIO_HAVE_WIDE_CHARACTER_TYPE as 1], [ac_cv_header_libbfio_features_h_have_wide_character_type], [AC_LANG_PUSH(C) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [[#include ]], [[#if !defined( LIBBFIO_HAVE_WIDE_CHARACTER_TYPE ) || ( LIBBFIO_HAVE_WIDE_CHARACTER_TYPE != 1 ) #error LIBBFIO_HAVE_WIDE_CHARACTER_TYPE not defined #endif]] )], [ac_cv_header_libbfio_features_h_have_wide_character_type=yes], [ac_cv_header_libbfio_features_h_have_wide_character_type=no]) AC_LANG_POP(C)], [ac_cv_header_libbfio_features_h_have_wide_character_type=no]) AS_IF( [test "x$ac_cv_header_libbfio_features_h_have_wide_character_type" = xno], [ac_cv_libbfio=no]) ]) AS_IF( [test "x$ac_cv_libbfio" = xyes], [ac_cv_libbfio_CPPFLAGS="$pkg_cv_libbfio_CFLAGS" ac_cv_libbfio_LIBADD="$pkg_cv_libbfio_LIBS"]) ]) AS_IF( [test "x$ac_cv_libbfio" = xcheck], [dnl Check for headers AC_CHECK_HEADERS([libbfio.h]) AS_IF( [test "x$ac_cv_header_libbfio_h" = xno], [ac_cv_libbfio=no], [ac_cv_libbfio=yes AX_CHECK_LIB_FUNCTIONS( [libbfio], [bfio], [[libbfio_get_version], [libbfio_handle_free], [libbfio_handle_open], [libbfio_handle_close], [libbfio_handle_exists], [libbfio_handle_read_buffer], [libbfio_handle_read_buffer_at_offset], [libbfio_handle_write_buffer], [libbfio_handle_write_buffer_at_offset], [libbfio_handle_seek_offset], [libbfio_handle_is_open], [libbfio_handle_get_offset], [libbfio_handle_get_size], [libbfio_handle_set_track_offsets_read], [libbfio_handle_get_number_of_offsets_read], [libbfio_handle_get_offset_read], [libbfio_file_initialize], [libbfio_file_get_name_size], [libbfio_file_get_name], [libbfio_file_set_name], [libbfio_pool_initialize], [libbfio_pool_free], [libbfio_pool_clone], [libbfio_pool_get_number_of_handles], [libbfio_pool_get_handle], [libbfio_pool_set_handle], [libbfio_pool_append_handle], [libbfio_pool_remove_handle], [libbfio_pool_get_maximum_number_of_open_handles], [libbfio_pool_set_maximum_number_of_open_handles], [libbfio_pool_open], [libbfio_pool_reopen], [libbfio_pool_close], [libbfio_pool_close_all], [libbfio_pool_read_buffer], [libbfio_pool_read_buffer_at_offset], [libbfio_pool_write_buffer], [libbfio_pool_write_buffer_at_offset], [libbfio_pool_seek_offset], [libbfio_pool_get_offset], [libbfio_pool_get_size], [libbfio_file_pool_open]]) AS_IF( [test "x$ac_cv_enable_wide_character_type" != xno], [AX_CHECK_LIB_FUNCTIONS( [libbfio], [bfio], [[libbfio_file_get_name_size_wide], [libbfio_file_get_name_wide], [libbfio_file_set_name_wide], [libbfio_file_pool_open_wide]]) ]) ac_cv_libbfio_LIBADD="-lbfio"]) ]) AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE([libbfio]) ]) AS_IF( [test "x$ac_cv_libbfio" = xyes], [AC_DEFINE( [HAVE_LIBBFIO], [1], [Define to 1 if you have the `bfio' library (-lbfio).]) ]) AS_IF( [test "x$ac_cv_libbfio" = xyes], [AC_SUBST( [HAVE_LIBBFIO], [1]) ], [AC_SUBST( [HAVE_LIBBFIO], [0]) ]) ]) dnl Function to detect if libbfio dependencies are available AC_DEFUN([AX_LIBBFIO_CHECK_LOCAL], [dnl No additional checks. ac_cv_libbfio_CPPFLAGS="-I../libbfio -I\$(top_srcdir)/libbfio"; ac_cv_libbfio_LIBADD="../libbfio/libbfio.la"; ac_cv_libbfio=local ]) dnl Function to detect how to enable libbfio AC_DEFUN([AX_LIBBFIO_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [libbfio], [libbfio], [search for libbfio in includedir and libdir or in the specified DIR, or no if to use local version], [auto-detect], [DIR]) dnl Check for a shared library version AX_LIBBFIO_CHECK_LIB dnl Check if the dependencies for the local library version AS_IF( [test "x$ac_cv_libbfio" != xyes], [AX_LIBBFIO_CHECK_LOCAL AC_DEFINE( [HAVE_LOCAL_LIBBFIO], [1], [Define to 1 if the local version of libbfio is used.]) AC_SUBST( [HAVE_LOCAL_LIBBFIO], [1]) ]) AM_CONDITIONAL( [HAVE_LOCAL_LIBBFIO], [test "x$ac_cv_libbfio" = xlocal]) AS_IF( [test "x$ac_cv_libbfio_CPPFLAGS" != "x"], [AC_SUBST( [LIBBFIO_CPPFLAGS], [$ac_cv_libbfio_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libbfio_LIBADD" != "x"], [AC_SUBST( [LIBBFIO_LIBADD], [$ac_cv_libbfio_LIBADD]) ]) AS_IF( [test "x$ac_cv_libbfio" = xyes], [AC_SUBST( [ax_libbfio_pc_libs_private], [-lbfio]) ]) AS_IF( [test "x$ac_cv_libbfio" = xyes], [AC_SUBST( [ax_libbfio_spec_requires], [libbfio]) AC_SUBST( [ax_libbfio_spec_build_requires], [libbfio-devel]) ]) ]) ================================================ FILE: m4/libcdata.m4 ================================================ dnl Checks for libcdata required headers and functions dnl dnl Version: 20240514 dnl Function to detect if libcdata is available dnl ac_libcdata_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l arguments AC_DEFUN([AX_LIBCDATA_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_libcdata" = xno], [ac_cv_libcdata=no], [ac_cv_libcdata=check dnl Check if the directory provided as parameter exists dnl For both --with-libcdata which returns "yes" and --with-libcdata= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_libcdata" != x && test "x$ac_cv_with_libcdata" != xauto-detect && test "x$ac_cv_with_libcdata" != xyes], [AX_CHECK_LIB_DIRECTORY_EXISTS([libcdata])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [libcdata], [libcdata >= 20230108], [ac_cv_libcdata=yes], [ac_cv_libcdata=check]) ]) AS_IF( [test "x$ac_cv_libcdata" = xyes], [ac_cv_libcdata_CPPFLAGS="$pkg_cv_libcdata_CFLAGS" ac_cv_libcdata_LIBADD="$pkg_cv_libcdata_LIBS"]) ]) AS_IF( [test "x$ac_cv_libcdata" = xcheck], [dnl Check for headers AC_CHECK_HEADERS([libcdata.h]) AS_IF( [test "x$ac_cv_header_libcdata_h" = xno], [ac_cv_libcdata=no], [ac_cv_libcdata=yes AX_CHECK_LIB_FUNCTIONS( [libcdata], [cdata], [[libcdata_get_version], [libcdata_array_initialize], [libcdata_array_free], [libcdata_array_empty], [libcdata_array_clone], [libcdata_array_resize], [libcdata_array_reverse], [libcdata_array_get_number_of_entries], [libcdata_array_get_entry_by_index], [libcdata_array_get_entry_by_value], [libcdata_array_set_entry_by_index], [libcdata_array_prepend_entry], [libcdata_array_append_entry], [libcdata_array_insert_entry], [libcdata_array_remove_entry], [libcdata_btree_initialize], [libcdata_btree_free], [libcdata_btree_get_number_of_values], [libcdata_btree_get_value_by_index], [libcdata_btree_get_value_by_value], [libcdata_btree_insert_value], [libcdata_btree_replace_value], [libcdata_btree_remove_value], [libcdata_list_initialize], [libcdata_list_free], [libcdata_list_empty], [libcdata_list_clone], [libcdata_list_get_number_of_elements], [libcdata_list_get_first_element], [libcdata_list_get_last_element], [libcdata_list_get_element_by_index], [libcdata_list_get_value_by_index], [libcdata_list_prepend_element], [libcdata_list_prepend_value], [libcdata_list_append_element], [libcdata_list_append_value], [libcdata_list_insert_element], [libcdata_list_insert_element_with_existing], [libcdata_list_insert_value], [libcdata_list_insert_value_with_existing], [libcdata_list_remove_element], [libcdata_list_element_initialize], [libcdata_list_element_free], [libcdata_list_element_get_value], [libcdata_list_element_set_value], [libcdata_list_element_get_previous_element], [libcdata_list_element_set_previous_element], [libcdata_list_element_get_next_element], [libcdata_list_element_get_elements], [libcdata_list_element_set_elements], [libcdata_range_list_initialize], [libcdata_range_list_free], [libcdata_range_list_empty], [libcdata_range_list_clone], [libcdata_range_list_get_number_of_elements], [libcdata_range_list_insert_range], [libcdata_range_list_insert_range_list], [libcdata_range_list_remove_range], [libcdata_range_list_get_range_by_index], [libcdata_range_list_get_range_at_offset], [libcdata_range_list_range_is_present], [libcdata_range_list_range_has_overlapping_range], [libcdata_range_list_get_spanning_range], [libcdata_tree_node_initialize], [libcdata_tree_node_free], [libcdata_tree_node_empty], [libcdata_tree_node_clone], [libcdata_tree_node_get_value], [libcdata_tree_node_set_value], [libcdata_tree_node_get_parent_node], [libcdata_tree_node_set_parent_node], [libcdata_tree_node_get_previous_node], [libcdata_tree_node_set_previous_node], [libcdata_tree_node_get_next_node], [libcdata_tree_node_set_next_node], [libcdata_tree_node_get_nodes], [libcdata_tree_node_set_nodes], [libcdata_tree_node_append_node], [libcdata_tree_node_append_value], [libcdata_tree_node_insert_node], [libcdata_tree_node_insert_value], [libcdata_tree_node_replace_node], [libcdata_tree_node_remove_node], [libcdata_tree_node_get_number_of_sub_nodes], [libcdata_tree_node_get_sub_node_by_index], [libcdata_tree_node_get_leaf_node_list]]) ac_cv_libcdata_LIBADD="-lcdata"]) ]) AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE([libcdata]) ]) AS_IF( [test "x$ac_cv_libcdata" = xyes], [AC_DEFINE( [HAVE_LIBCDATA], [1], [Define to 1 if you have the `cdata' library (-lcdata).]) ]) AS_IF( [test "x$ac_cv_libcdata" = xyes], [AC_SUBST( [HAVE_LIBCDATA], [1]) ], [AC_SUBST( [HAVE_LIBCDATA], [0]) ]) ]) dnl Function to detect if libcdata dependencies are available AC_DEFUN([AX_LIBCDATA_CHECK_LOCAL], [dnl No additional checks. ac_cv_libcdata_CPPFLAGS="-I../libcdata -I\$(top_srcdir)/libcdata"; ac_cv_libcdata_LIBADD="../libcdata/libcdata.la"; ac_cv_libcdata=local ]) dnl Function to detect how to enable libcdata AC_DEFUN([AX_LIBCDATA_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [libcdata], [libcdata], [search for libcdata in includedir and libdir or in the specified DIR, or no if to use local version], [auto-detect], [DIR]) dnl Check for a shared library version AX_LIBCDATA_CHECK_LIB dnl Check if the dependencies for the local library version AS_IF( [test "x$ac_cv_libcdata" != xyes], [AX_LIBCDATA_CHECK_LOCAL AC_DEFINE( [HAVE_LOCAL_LIBCDATA], [1], [Define to 1 if the local version of libcdata is used.]) AC_SUBST( [HAVE_LOCAL_LIBCDATA], [1]) ]) AM_CONDITIONAL( [HAVE_LOCAL_LIBCDATA], [test "x$ac_cv_libcdata" = xlocal]) AS_IF( [test "x$ac_cv_libcdata_CPPFLAGS" != "x"], [AC_SUBST( [LIBCDATA_CPPFLAGS], [$ac_cv_libcdata_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libcdata_LIBADD" != "x"], [AC_SUBST( [LIBCDATA_LIBADD], [$ac_cv_libcdata_LIBADD]) ]) AS_IF( [test "x$ac_cv_libcdata" = xyes], [AC_SUBST( [ax_libcdata_pc_libs_private], [-lcdata]) ]) AS_IF( [test "x$ac_cv_libcdata" = xyes], [AC_SUBST( [ax_libcdata_spec_requires], [libcdata]) AC_SUBST( [ax_libcdata_spec_build_requires], [libcdata-devel]) ]) ]) ================================================ FILE: m4/libcerror.m4 ================================================ dnl Checks for libcerror required headers and functions dnl dnl Version: 20240513 dnl Function to detect if libcerror is available dnl ac_libcerror_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l arguments AC_DEFUN([AX_LIBCERROR_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_libcerror" = xno], [ac_cv_libcerror=no], [ac_cv_libcerror=check dnl Check if the directory provided as parameter exists dnl For both --with-libcerror which returns "yes" and --with-libcerror= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_libcerror" != x && test "x$ac_cv_with_libcerror" != xauto-detect && test "x$ac_cv_with_libcerror" != xyes], [AX_CHECK_LIB_DIRECTORY_EXISTS([libcerror])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [libcerror], [libcerror >= 20120425], [ac_cv_libcerror=yes], [ac_cv_libcerror=check]) ]) AS_IF( [test "x$ac_cv_libcerror" = xyes], [ac_cv_libcerror_CPPFLAGS="$pkg_cv_libcerror_CFLAGS" ac_cv_libcerror_LIBADD="$pkg_cv_libcerror_LIBS"]) ]) AS_IF( [test "x$ac_cv_libcerror" = xcheck], [dnl Check for headers AC_CHECK_HEADERS([libcerror.h]) AS_IF( [test "x$ac_cv_header_libcerror_h" = xno], [ac_cv_libcerror=no], [ac_cv_libcerror=yes AX_CHECK_LIB_FUNCTIONS( [libcerror], [cerror], [[libcerror_get_version], [libcerror_error_free], [libcerror_error_set], [libcerror_error_matches], [libcerror_error_fprint], [libcerror_error_sprint], [libcerror_error_backtrace_fprint], [libcerror_error_backtrace_sprint], [libcerror_system_set_error]]) ac_cv_libcerror_LIBADD="-lcerror"]) ]) AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE([libcerror]) ]) AS_IF( [test "x$ac_cv_libcerror" = xyes], [AC_DEFINE( [HAVE_LIBCERROR], [1], [Define to 1 if you have the `cerror' library (-lcerror).]) ]) AS_IF( [test "x$ac_cv_libcerror" = xyes], [AC_SUBST( [HAVE_LIBCERROR], [1]) ], [AC_SUBST( [HAVE_LIBCERROR], [0]) ]) ]) dnl Function to detect if libcerror dependencies are available AC_DEFUN([AX_LIBCERROR_CHECK_LOCAL], [dnl Headers included in libcerror/libcerror_error.c AC_CHECK_HEADERS([stdarg.h varargs.h]) AS_IF( [test "x$ac_cv_header_stdarg_h" != xyes && test "x$ac_cv_header_varargs_h" != xyes], [AC_MSG_FAILURE( [Missing headers: stdarg.h and varargs.h], [1]) ]) dnl Wide character string functions used in libcerror/libcerror_error.c AS_IF( [test "x$ac_cv_enable_wide_character_type" != xno], [AC_CHECK_FUNCS([wcstombs]) AS_IF( [test "x$ac_cv_func_wcstombs" != xyes], [AC_MSG_FAILURE( [Missing function: wcstombs], [1]) ]) ]) dnl Check for error string functions used in libcerror/libcerror_system.c AC_FUNC_STRERROR_R() AS_IF( [test "x$ac_cv_have_decl_strerror_r" != xyes], [AC_CHECK_FUNCS([strerror]) AS_IF( [test "x$ac_cv_func_strerror" != xyes], [AC_MSG_FAILURE( [Missing functions: strerror_r and strerror], [1]) ]) ]) ac_cv_libcerror_CPPFLAGS="-I../libcerror -I\$(top_srcdir)/libcerror"; ac_cv_libcerror_LIBADD="../libcerror/libcerror.la"; ac_cv_libcerror=local ]) dnl Function to detect how to enable libcerror AC_DEFUN([AX_LIBCERROR_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [libcerror], [libcerror], [search for libcerror in includedir and libdir or in the specified DIR, or no if to use local version], [auto-detect], [DIR]) dnl Check for a shared library version AX_LIBCERROR_CHECK_LIB dnl Check if the dependencies for the local library version AS_IF( [test "x$ac_cv_libcerror" != xyes], [AX_LIBCERROR_CHECK_LOCAL AC_DEFINE( [HAVE_LOCAL_LIBCERROR], [1], [Define to 1 if the local version of libcerror is used.]) AC_SUBST( [HAVE_LOCAL_LIBCERROR], [1]) ]) AM_CONDITIONAL( [HAVE_LOCAL_LIBCERROR], [test "x$ac_cv_libcerror" = xlocal]) AS_IF( [test "x$ac_cv_libcerror_CPPFLAGS" != "x"], [AC_SUBST( [LIBCERROR_CPPFLAGS], [$ac_cv_libcerror_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libcerror_LIBADD" != "x"], [AC_SUBST( [LIBCERROR_LIBADD], [$ac_cv_libcerror_LIBADD]) ]) AS_IF( [test "x$ac_cv_libcerror" = xyes], [AC_SUBST( [ax_libcerror_pc_libs_private], [-lcerror]) ]) AS_IF( [test "x$ac_cv_libcerror" = xyes], [AC_SUBST( [ax_libcerror_spec_requires], [libcerror]) AC_SUBST( [ax_libcerror_spec_build_requires], [libcerror-devel]) ]) ]) ================================================ FILE: m4/libcfile.m4 ================================================ dnl Checks for libcfile required headers and functions dnl dnl Version: 20240514 dnl Function to detect if libcfile is available dnl ac_libcfile_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l arguments AC_DEFUN([AX_LIBCFILE_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_libcfile" = xno], [ac_cv_libcfile=no], [ac_cv_libcfile=check dnl Check if the directory provided as parameter exists dnl For both --with-libcfile which returns "yes" and --with-libcfile= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_libcfile" != x && test "x$ac_cv_with_libcfile" != xauto-detect && test "x$ac_cv_with_libcfile" != xyes], [AX_CHECK_LIB_DIRECTORY_EXISTS([libcfile])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [libcfile], [libcfile >= 20160409], [ac_cv_libcfile=yes], [ac_cv_libcfile=check]) ]) AS_IF( [test "x$ac_cv_libcfile" = xyes && test "x$ac_cv_enable_wide_character_type" != xno], [AC_CACHE_CHECK( [whether libcfile/features.h defines LIBCFILE_HAVE_WIDE_CHARACTER_TYPE as 1], [ac_cv_header_libcfile_features_h_have_wide_character_type], [AC_LANG_PUSH(C) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [[#include ]], [[#if !defined( LIBCFILE_HAVE_WIDE_CHARACTER_TYPE ) || ( LIBCFILE_HAVE_WIDE_CHARACTER_TYPE != 1 ) #error LIBCFILE_HAVE_WIDE_CHARACTER_TYPE not defined #endif]] )], [ac_cv_header_libcfile_features_h_have_wide_character_type=yes], [ac_cv_header_libcfile_features_h_have_wide_character_type=no]) AC_LANG_POP(C)], [ac_cv_header_libcfile_features_h_have_wide_character_type=no]) AS_IF( [test "x$ac_cv_header_libcfile_features_h_have_wide_character_type" = xno], [ac_cv_libcfile=no]) ]) AS_IF( [test "x$ac_cv_libcfile" = xyes], [ac_cv_libcfile_CPPFLAGS="$pkg_cv_libcfile_CFLAGS" ac_cv_libcfile_LIBADD="$pkg_cv_libcfile_LIBS"]) ]) AS_IF( [test "x$ac_cv_libcfile" = xcheck], [dnl Check for headers AC_CHECK_HEADERS([libcfile.h]) AS_IF( [test "x$ac_cv_header_libcfile_h" = xno], [ac_cv_libcfile=no], [ac_cv_libcfile=yes AX_CHECK_LIB_FUNCTIONS( [libcfile], [cfile], [[libcfile_get_version], [libcfile_file_initialize], [libcfile_file_free], [libcfile_file_open], [libcfile_file_open_with_error_code], [libcfile_file_close], [libcfile_file_read_buffer], [libcfile_file_read_buffer_with_error_code], [libcfile_file_write_buffer], [libcfile_file_write_buffer_with_error_code], [libcfile_file_seek_offset], [libcfile_file_resize], [libcfile_file_is_open], [libcfile_file_get_offset], [libcfile_file_get_size], [libcfile_file_is_device], [libcfile_file_io_control_read], [libcfile_file_io_control_read_with_error_code], [libcfile_file_exists], [libcfile_file_remove]]) AS_IF( [test "x$ac_cv_enable_wide_character_type" != xno], [AX_CHECK_LIB_FUNCTIONS( [libcfile], [cfile], [[libcfile_file_open_wide], [libcfile_file_open_wide_with_error_code], [libcfile_file_exists_wide], [libcfile_file_remove_wide]]) ]) ac_cv_libcfile_LIBADD="-lcfile"]) ]) AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE([libcfile]) ]) AS_IF( [test "x$ac_cv_libcfile" = xyes], [AC_DEFINE( [HAVE_LIBCFILE], [1], [Define to 1 if you have the `cfile' library (-lcfile).]) ]) AS_IF( [test "x$ac_cv_libcfile" = xyes], [AC_SUBST( [HAVE_LIBCFILE], [1]) ], [AC_SUBST( [HAVE_LIBCFILE], [0]) ]) ]) dnl Function to detect if posix_fadvise is available AC_DEFUN([AX_LIBCFILE_CHECK_FUNC_POSIX_FADVISE], [AC_CHECK_FUNCS([posix_fadvise]) AS_IF( [test "x$ac_cv_func_posix_fadvise" = xyes], [AC_MSG_CHECKING( [whether posix_fadvise can be linked]) SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wall -Werror" AC_LANG_PUSH(C) AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#include ]], [[#if !defined( POSIX_FADV_SEQUENTIAL ) #define POSIX_FADV_SEQUENTIAL 2 #endif posix_fadvise( 0, 0, 0, POSIX_FADV_SEQUENTIAL )]] )], [ac_cv_func_posix_fadvise=yes], [ac_cv_func_posix_fadvise=no]) AC_LANG_POP(C) CFLAGS="$SAVE_CFLAGS" AS_IF( [test "x$ac_cv_func_posix_fadvise" = xyes], [AC_MSG_RESULT( [yes]) AC_DEFINE( [HAVE_POSIX_FADVISE], [1], [Define to 1 if you have the posix_fadvise function.]) ], [AC_MSG_RESULT( [no]) ]) ]) ]) dnl Function to detect if libcfile dependencies are available AC_DEFUN([AX_LIBCFILE_CHECK_LOCAL], [dnl Headers included in libcfile/libcfile_file.c and libcfile/libcfile_support.c AC_CHECK_HEADERS([errno.h stdio.h sys/stat.h]) dnl Headers included in libcfile/libcfile_file.c AC_CHECK_HEADERS([cygwin/fs.h fcntl.h linux/fs.h sys/disk.h sys/disklabel.h sys/ioctl.h unistd.h]) dnl File input/output functions used in libcfile/libcfile_file.c AC_CHECK_FUNCS([close fstat ftruncate ioctl lseek open read write]) AS_IF( [test "x$ac_cv_func_close" != xyes], [AC_MSG_FAILURE( [Missing function: close], [1]) ]) AX_LIBCFILE_CHECK_FUNC_POSIX_FADVISE AS_IF( [test "x$ac_cv_func_fstat" != xyes], [AC_MSG_FAILURE( [Missing function: fstat], [1]) ]) AS_IF( [test "x$ac_cv_func_ftruncate" != xyes], [AC_MSG_FAILURE( [Missing function: ftruncate], [1]) ]) AS_IF( [test x"$ac_cv_enable_winapi" = xno], [AS_IF( [test "x$ac_cv_func_ioctl" != xyes], [AC_MSG_FAILURE( [Missing function: ioctl], [1]) ]) ]) AS_IF( [test "x$ac_cv_func_lseek" != xyes], [AC_MSG_FAILURE( [Missing function: lseek], [1]) ]) AS_IF( [test "x$ac_cv_func_open" != xyes], [AC_MSG_FAILURE( [Missing function: open], [1]) ]) AS_IF( [test "x$ac_cv_func_read" != xyes], [AC_MSG_FAILURE( [Missing function: read], [1]) ]) AS_IF( [test "x$ac_cv_func_write" != xyes], [AC_MSG_FAILURE( [Missing function: write], [1]) ]) dnl File input/output functions used in libcfile/libcfile_support.c AC_CHECK_FUNCS([stat unlink]) AS_IF( [test "x$ac_cv_func_stat" != xyes], [AC_MSG_FAILURE( [Missing function: stat], [1]) ]) AS_IF( [test "x$ac_cv_func_unlink" != xyes], [AC_MSG_FAILURE( [Missing function: unlink], [1]) ]) ac_cv_libcfile_CPPFLAGS="-I../libcfile -I\$(top_srcdir)/libcfile"; ac_cv_libcfile_LIBADD="../libcfile/libcfile.la"; ac_cv_libcfile=local ]) dnl Function to detect how to enable libcfile AC_DEFUN([AX_LIBCFILE_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [libcfile], [libcfile], [search for libcfile in includedir and libdir or in the specified DIR, or no if to use local version], [auto-detect], [DIR]) dnl Check for a shared library version AX_LIBCFILE_CHECK_LIB dnl Check if the dependencies for the local library version AS_IF( [test "x$ac_cv_libcfile" != xyes], [AX_LIBCFILE_CHECK_LOCAL AC_DEFINE( [HAVE_LOCAL_LIBCFILE], [1], [Define to 1 if the local version of libcfile is used.]) AC_SUBST( [HAVE_LOCAL_LIBCFILE], [1]) ]) AM_CONDITIONAL( [HAVE_LOCAL_LIBCFILE], [test "x$ac_cv_libcfile" = xlocal]) AS_IF( [test "x$ac_cv_libcfile_CPPFLAGS" != "x"], [AC_SUBST( [LIBCFILE_CPPFLAGS], [$ac_cv_libcfile_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libcfile_LIBADD" != "x"], [AC_SUBST( [LIBCFILE_LIBADD], [$ac_cv_libcfile_LIBADD]) ]) AS_IF( [test "x$ac_cv_libcfile" = xyes], [AC_SUBST( [ax_libcfile_pc_libs_private], [-lcfile]) ]) AS_IF( [test "x$ac_cv_libcfile" = xyes], [AC_SUBST( [ax_libcfile_spec_requires], [libcfile]) AC_SUBST( [ax_libcfile_spec_build_requires], [libcfile-devel]) ]) ]) ================================================ FILE: m4/libclocale.m4 ================================================ dnl Checks for libclocale required headers and functions dnl dnl Version: 20240513 dnl Function to detect if libclocale is available dnl ac_libclocale_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l arguments AC_DEFUN([AX_LIBCLOCALE_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_libclocale" = xno], [ac_cv_libclocale=no], [ac_cv_libclocale=check dnl Check if the directory provided as parameter exists dnl For both --with-libclocale which returns "yes" and --with-libclocale= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_libclocale" != x && test "x$ac_cv_with_libclocale" != xauto-detect && test "x$ac_cv_with_libclocale" != xyes], [AX_CHECK_LIB_DIRECTORY_EXISTS([libclocale])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [libclocale], [libclocale >= 20120425], [ac_cv_libclocale=yes], [ac_cv_libclocale=check]) ]) AS_IF( [test "x$ac_cv_libclocale" = xyes && test "x$ac_cv_enable_wide_character_type" != xno], [AC_CACHE_CHECK( [whether libclocale/features.h defines LIBCLOCALE_HAVE_WIDE_CHARACTER_TYPE as 1], [ac_cv_header_libclocale_features_h_have_wide_character_type], [AC_LANG_PUSH(C) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [[#include ]], [[#if !defined( LIBCLOCALE_HAVE_WIDE_CHARACTER_TYPE ) || ( LIBCLOCALE_HAVE_WIDE_CHARACTER_TYPE != 1 ) #error LIBCLOCALE_HAVE_WIDE_CHARACTER_TYPE not defined #endif]] )], [ac_cv_header_libclocale_features_h_have_wide_character_type=yes], [ac_cv_header_libclocale_features_h_have_wide_character_type=no]) AC_LANG_POP(C)], [ac_cv_header_libclocale_features_h_have_wide_character_type=no]) AS_IF( [test "x$ac_cv_header_libclocale_features_h_have_wide_character_type" = xno], [ac_cv_libclocale=no]) ]) AS_IF( [test "x$ac_cv_libclocale" = xyes], [ac_cv_libclocale_CPPFLAGS="$pkg_cv_libclocale_CFLAGS" ac_cv_libclocale_LIBADD="$pkg_cv_libclocale_LIBS"]) ]) AS_IF( [test "x$ac_cv_libclocale" = xcheck], [dnl Check for headers AC_CHECK_HEADERS([libclocale.h]) AS_IF( [test "x$ac_cv_header_libclocale_h" = xno], [ac_cv_libclocale=no], [ac_cv_libclocale=yes AX_CHECK_LIB_FUNCTIONS( [libclocale], [clocale], [[libclocale_get_version], [libclocale_codepage], [libclocale_codepage_get], [libclocale_codepage_set], [libclocale_codepage_copy_from_string], [libclocale_locale_get_codepage], [libclocale_locale_get_decimal_point], [libclocale_initialize]]) AS_IF( [test "x$ac_cv_enable_wide_character_type" != xno], [AC_CHECK_LIB( clocale, libclocale_codepage_copy_from_string_wide, [ac_cv_libclocale_dummy=yes], [ac_cv_libclocale=no]) ]) ac_cv_libclocale_LIBADD="-lclocale"]) ]) AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE([libclocale]) ]) AS_IF( [test "x$ac_cv_libclocale" = xyes], [AC_DEFINE( [HAVE_LIBCLOCALE], [1], [Define to 1 if you have the `clocale' library (-lclocale).]) ]) AS_IF( [test "x$ac_cv_libclocale" = xyes], [AC_SUBST( [HAVE_LIBCLOCALE], [1]) ], [AC_SUBST( [HAVE_LIBCLOCALE], [0]) ]) ]) dnl Function to detect whether nl_langinfo supports CODESET AC_DEFUN([AX_LIBCLOCALE_CHECK_FUNC_LANGINFO_CODESET], [AC_CHECK_FUNCS([nl_langinfo]) AS_IF( [test "x$ac_cv_func_nl_langinfo" = xyes], [AC_CACHE_CHECK( [for nl_langinfo CODESET support], [ac_cv_cv_langinfo_codeset], [AC_LANG_PUSH(C) AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#include ]], [[char* charset = nl_langinfo( CODESET );]] )], [ac_cv_cv_langinfo_codeset=yes], [ac_cv_cv_langinfo_codeset=no]) AC_LANG_POP(C) ]) ], [ac_cv_cv_langinfo_codeset=no]) AS_IF( [test "x$ac_cv_cv_langinfo_codeset" = xyes], [AC_DEFINE( [HAVE_LANGINFO_CODESET], [1], [Define if nl_langinfo has CODESET support.]) ]) ]) dnl Function to detect if libclocale dependencies are available AC_DEFUN([AX_LIBCLOCALE_CHECK_LOCAL], [dnl Headers included in libclocale/libclocale_locale.c AC_CHECK_HEADERS([langinfo.h locale.h]) dnl Check for environment functions in libclocale/libclocale_locale.c AC_CHECK_FUNCS([getenv]) AS_IF( [test "x$ac_cv_func_getenv" != xyes], [AC_MSG_FAILURE( [Missing function: getenv], [1]) ]) dnl Check for localization functions in libclocale/libclocale_locale.c AS_IF( [test "x$ac_cv_enable_winapi" = xno], [AC_CHECK_FUNCS([localeconv]) AS_IF( [test "x$ac_cv_func_localeconv" != xyes], [AC_MSG_FAILURE( [Missing function: localeconv], [1]) ]) ]) AC_CHECK_FUNCS([setlocale]) AS_IF( [test "x$ac_cv_func_setlocale" != xyes], [AC_MSG_FAILURE( [Missing function: setlocale], [1]) ]) AX_LIBCLOCALE_CHECK_FUNC_LANGINFO_CODESET ac_cv_libclocale_CPPFLAGS="-I../libclocale -I\$(top_srcdir)/libclocale"; ac_cv_libclocale_LIBADD="../libclocale/libclocale.la"; ac_cv_libclocale=local ]) dnl Function to detect how to enable libclocale AC_DEFUN([AX_LIBCLOCALE_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [libclocale], [libclocale], [search for libclocale in includedir and libdir or in the specified DIR, or no if to use local version], [auto-detect], [DIR]) dnl Check for a shared library version AX_LIBCLOCALE_CHECK_LIB dnl Check if the dependencies for the local library version AS_IF( [test "x$ac_cv_libclocale" != xyes], [AX_LIBCLOCALE_CHECK_LOCAL AC_DEFINE( [HAVE_LOCAL_LIBCLOCALE], [1], [Define to 1 if the local version of libclocale is used.]) AC_SUBST( [HAVE_LOCAL_LIBCLOCALE], [1]) ]) AM_CONDITIONAL( [HAVE_LOCAL_LIBCLOCALE], [test "x$ac_cv_libclocale" = xlocal]) AS_IF( [test "x$ac_cv_libclocale_CPPFLAGS" != "x"], [AC_SUBST( [LIBCLOCALE_CPPFLAGS], [$ac_cv_libclocale_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libclocale_LIBADD" != "x"], [AC_SUBST( [LIBCLOCALE_LIBADD], [$ac_cv_libclocale_LIBADD]) ]) AS_IF( [test "x$ac_cv_libclocale" = xyes], [AC_SUBST( [ax_libclocale_pc_libs_private], [-lclocale]) ]) AS_IF( [test "x$ac_cv_libclocale" = xyes], [AC_SUBST( [ax_libclocale_spec_requires], [libclocale]) AC_SUBST( [ax_libclocale_spec_build_requires], [libclocale-devel]) ]) ]) ================================================ FILE: m4/libcnotify.m4 ================================================ dnl Checks for libcnotify required headers and functions dnl dnl Version: 20240513 dnl Function to detect if libcnotify is available dnl ac_libcnotify_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l arguments AC_DEFUN([AX_LIBCNOTIFY_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_libcnotify" = xno], [ac_cv_libcnotify=no], [ac_cv_libcnotify=check dnl Check if the directory provided as parameter exists dnl For both --with-libcnotify which returns "yes" and --with-libcnotify= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_libcnotify" != x && test "x$ac_cv_with_libcnotify" != xauto-detect && test "x$ac_cv_with_libcnotify" != xyes], [AX_CHECK_LIB_DIRECTORY_EXISTS([libcnotify])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [libcnotify], [libcnotify >= 20120425], [ac_cv_libcnotify=yes], [ac_cv_libcnotify=check]) ]) AS_IF( [test "x$ac_cv_libcnotify" = xyes], [ac_cv_libcnotify_CPPFLAGS="$pkg_cv_libcnotify_CFLAGS" ac_cv_libcnotify_LIBADD="$pkg_cv_libcnotify_LIBS"]) ]) AS_IF( [test "x$ac_cv_libcnotify" = xcheck], [dnl Check for headers AC_CHECK_HEADERS([libcnotify.h]) AS_IF( [test "x$ac_cv_header_libcnotify_h" = xno], [ac_cv_libcnotify=no], [ac_cv_libcnotify=yes AX_CHECK_LIB_FUNCTIONS( [libcnotify], [cnotify], [[libcnotify_get_version], [libcnotify_printf], [libcnotify_print_data], [libcnotify_print_error_backtrace], [libcnotify_stream_set], [libcnotify_stream_open], [libcnotify_stream_close], [libcnotify_verbose_set]]) ac_cv_libcnotify_LIBADD="-lcnotify"]) ]) AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE([libcnotify]) ]) AS_IF( [test "x$ac_cv_libcnotify" = xyes], [AC_DEFINE( [HAVE_LIBCNOTIFY], [1], [Define to 1 if you have the `cnotify' library (-lcnotify).]) ]) AS_IF( [test "x$ac_cv_libcnotify" = xyes], [AC_SUBST( [HAVE_LIBCNOTIFY], [1]) ], [AC_SUBST( [HAVE_LIBCNOTIFY], [0]) ]) ]) dnl Function to detect if libcnotify dependencies are available AC_DEFUN([AX_LIBCNOTIFY_CHECK_LOCAL], [dnl Headers included in libcnotify/libcnotify_print.c AC_CHECK_HEADERS([stdarg.h varargs.h]) AS_IF( [test "x$ac_cv_header_stdarg_h" != xyes && test "x$ac_cv_header_varargs_h" != xyes], [AC_MSG_FAILURE( [Missing headers: stdarg.h and varargs.h], [1]) ]) dnl Headers included in libcnotify/libcnotify_stream.c AC_CHECK_HEADERS([errno.h]) ac_cv_libcnotify_CPPFLAGS="-I../libcnotify -I\$(top_srcdir)/libcnotify"; ac_cv_libcnotify_LIBADD="../libcnotify/libcnotify.la"; ac_cv_libcnotify=local ]) dnl Function to detect how to enable libcnotify AC_DEFUN([AX_LIBCNOTIFY_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [libcnotify], [libcnotify], [search for libcnotify in includedir and libdir or in the specified DIR, or no if to use local version], [auto-detect], [DIR]) dnl Check for a shared library version AX_LIBCNOTIFY_CHECK_LIB dnl Check if the dependencies for the local library version AS_IF( [test "x$ac_cv_libcnotify" != xyes], [AX_LIBCNOTIFY_CHECK_LOCAL AC_DEFINE( [HAVE_LOCAL_LIBCNOTIFY], [1], [Define to 1 if the local version of libcnotify is used.]) AC_SUBST( [HAVE_LOCAL_LIBCNOTIFY], [1]) ]) AM_CONDITIONAL( [HAVE_LOCAL_LIBCNOTIFY], [test "x$ac_cv_libcnotify" = xlocal]) AS_IF( [test "x$ac_cv_libcnotify_CPPFLAGS" != "x"], [AC_SUBST( [LIBCNOTIFY_CPPFLAGS], [$ac_cv_libcnotify_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libcnotify_LIBADD" != "x"], [AC_SUBST( [LIBCNOTIFY_LIBADD], [$ac_cv_libcnotify_LIBADD]) ]) AS_IF( [test "x$ac_cv_libcnotify" = xyes], [AC_SUBST( [ax_libcnotify_pc_libs_private], [-lcnotify]) ]) AS_IF( [test "x$ac_cv_libcnotify" = xyes], [AC_SUBST( [ax_libcnotify_spec_requires], [libcnotify]) AC_SUBST( [ax_libcnotify_spec_build_requires], [libcnotify-devel]) ]) ]) ================================================ FILE: m4/libcpath.m4 ================================================ dnl Checks for libcpath required headers and functions dnl dnl Version: 20240518 dnl Function to detect if libcpath is available dnl ac_libcpath_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l arguments AC_DEFUN([AX_LIBCPATH_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_libcpath" = xno], [ac_cv_libcpath=no], [ac_cv_libcpath=check dnl Check if the directory provided as parameter exists dnl For both --with-libcpath which returns "yes" and --with-libcpath= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_libcpath" != x && test "x$ac_cv_with_libcpath" != xauto-detect && test "x$ac_cv_with_libcpath" != xyes], [AX_CHECK_LIB_DIRECTORY_EXISTS([libcpath])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [libcpath], [libcpath >= 20180716], [ac_cv_libcpath=yes], [ac_cv_libcpath=check]) ]) AS_IF( [test "x$ac_cv_libcpath" = xyes && test "x$ac_cv_enable_wide_character_type" != xno], [AC_CACHE_CHECK( [whether libcpath/features.h defines LIBCPATH_HAVE_WIDE_CHARACTER_TYPE as 1], [ac_cv_header_libcpath_features_h_have_wide_character_type], [AC_LANG_PUSH(C) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [[#include ]], [[#if !defined( LIBCPATH_HAVE_WIDE_CHARACTER_TYPE ) || ( LIBCPATH_HAVE_WIDE_CHARACTER_TYPE != 1 ) #error LIBCPATH_HAVE_WIDE_CHARACTER_TYPE not defined #endif]] )], [ac_cv_header_libcpath_features_h_have_wide_character_type=yes], [ac_cv_header_libcpath_features_h_have_wide_character_type=no]) AC_LANG_POP(C)], [ac_cv_header_libcpath_features_h_have_wide_character_type=no]) AS_IF( [test "x$ac_cv_header_libcpath_features_h_have_wide_character_type" = xno], [ac_cv_libcpath=no]) ]) AS_IF( [test "x$ac_cv_libcpath" = xyes], [ac_cv_libcpath_CPPFLAGS="$pkg_cv_libcpath_CFLAGS" ac_cv_libcpath_LIBADD="$pkg_cv_libcpath_LIBS"]) ]) AS_IF( [test "x$ac_cv_libcpath" = xcheck], [dnl Check for headers AC_CHECK_HEADERS([libcpath.h]) AS_IF( [test "x$ac_cv_header_libcpath_h" = xno], [ac_cv_libcpath=no], [ac_cv_libcpath=yes AX_CHECK_LIB_FUNCTIONS( [libcpath], [cpath], [[libcpath_get_version], [libcpath_path_change_directory], [libcpath_path_get_current_working_directory], [libcpath_path_get_full_path], [libcpath_path_get_sanitized_filename], [libcpath_path_get_sanitized_path], [libcpath_path_join], [libcpath_path_make_directory]]) AS_IF( [test "x$ac_cv_enable_wide_character_type" != xno], [AX_CHECK_LIB_FUNCTIONS( [libcpath], [cpath], [[libcpath_path_change_directory_wide], [libcpath_path_get_current_working_directory_wide], [libcpath_path_get_full_path_wide], [libcpath_path_get_sanitized_filename_wide], [libcpath_path_get_sanitized_path_wide], [libcpath_path_join_wide], [libcpath_path_make_directory_wide]]) ]) ac_cv_libcpath_LIBADD="-lcpath"]) ]) AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE([libcpath]) ]) AS_IF( [test "x$ac_cv_libcpath" = xyes], [AC_DEFINE( [HAVE_LIBCPATH], [1], [Define to 1 if you have the `cpath' library (-lcpath).]) ]) AS_IF( [test "x$ac_cv_libcpath" = xyes], [AC_SUBST( [HAVE_LIBCPATH], [1]) ], [AC_SUBST( [HAVE_LIBCPATH], [0]) ]) ]) dnl Function to detect if mkdir is available dnl Also checks how to use mkdir AC_DEFUN([AX_LIBCPATH_CHECK_FUNC_MKDIR], [AC_CHECK_FUNCS([mkdir]) AS_IF( [test "x$ac_cv_func_mkdir" = xyes], [AC_MSG_CHECKING( [how to use mkdir]) SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wall -Werror" AC_LANG_PUSH(C) AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#include #include ]], [[mkdir( "", 0 )]] )], [AC_MSG_RESULT( [with additional mode argument]) ac_cv_cv_mkdir_mode=yes], [ac_cv_cv_mkdir_mode=no]) AS_IF( [test "x$ac_cv_cv_mkdir_mode" = xno], [AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#include ]], [[mkdir( "" )]] )], [AC_MSG_RESULT( [with single argument]) ac_cv_cv_mkdir=yes], [ac_cv_cv_mkdir=no]) ]) AC_LANG_POP(C) CFLAGS="$SAVE_CFLAGS" AS_IF( [test "x$ac_cv_cv_mkdir_mode" = xno && test "x$ac_cv_cv_mkdir" = xno], [AC_MSG_WARN( [unknown]) ac_cv_func_mkdir=no]) AS_IF( [test "x$ac_cv_func_mkdir" = xyes], [AC_DEFINE( [HAVE_MKDIR], [1], [Define to 1 if you have the mkdir function.]) ]) AS_IF( [test "x$ac_cv_cv_mkdir_mode" = xyes], [AC_DEFINE( [HAVE_MKDIR_MODE], [1], [Define to 1 if you have the mkdir function with a second mode argument.]) ]) ]) AS_IF( [test "x$ac_cv_func_mkdir" = xno], [AC_MSG_FAILURE( [Missing function: mkdir], [1]) ]) ]) dnl Function to detect if libcpath dependencies are available AC_DEFUN([AX_LIBCPATH_CHECK_LOCAL], [dnl Headers included in libcpath/libcpath_path.h AC_CHECK_HEADERS([errno.h sys/stat.h sys/syslimits.h]) dnl Path functions used in libcpath/libcpath_path.h AC_CHECK_FUNCS([chdir getcwd]) AS_IF( [test "x$ac_cv_func_chdir" != xyes], [AC_MSG_FAILURE( [Missing functions: chdir], [1]) ]) AS_IF( [test "x$ac_cv_func_getcwd" != xyes], [AC_MSG_FAILURE( [Missing functions: getcwd], [1]) ]) AX_LIBCPATH_CHECK_FUNC_MKDIR ac_cv_libcpath_CPPFLAGS="-I../libcpath -I\$(top_srcdir)/libcpath"; ac_cv_libcpath_LIBADD="../libcpath/libcpath.la"; ac_cv_libcpath=local ]) dnl Function to detect how to enable libcpath AC_DEFUN([AX_LIBCPATH_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [libcpath], [libcpath], [search for libcpath in includedir and libdir or in the specified DIR, or no if to use local version], [auto-detect], [DIR]) dnl Check for a shared library version AX_LIBCPATH_CHECK_LIB dnl Check if the dependencies for the local library version AS_IF( [test "x$ac_cv_libcpath" != xyes], [AX_LIBCPATH_CHECK_LOCAL AC_DEFINE( [HAVE_LOCAL_LIBCPATH], [1], [Define to 1 if the local version of libcpath is used.]) AC_SUBST( [HAVE_LOCAL_LIBCPATH], [1]) ]) AM_CONDITIONAL( [HAVE_LOCAL_LIBCPATH], [test "x$ac_cv_libcpath" = xlocal]) AS_IF( [test "x$ac_cv_libcpath_CPPFLAGS" != "x"], [AC_SUBST( [LIBCPATH_CPPFLAGS], [$ac_cv_libcpath_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libcpath_LIBADD" != "x"], [AC_SUBST( [LIBCPATH_LIBADD], [$ac_cv_libcpath_LIBADD]) ]) AS_IF( [test "x$ac_cv_libcpath" = xyes], [AC_SUBST( [ax_libcpath_pc_libs_private], [-lcpath]) ]) AS_IF( [test "x$ac_cv_libcpath" = xyes], [AC_SUBST( [ax_libcpath_spec_requires], [libcpath]) AC_SUBST( [ax_libcpath_spec_build_requires], [libcpath-devel]) ]) ]) ================================================ FILE: m4/libcrypto.m4 ================================================ dnl Checks for libcrypto required headers and functions dnl dnl Version: 20251208 dnl Function to detect whether openssl/evp.h can be used in combination with zlib.h AC_DEFUN([AX_LIBCRYPTO_CHECK_OPENSSL_EVP_ZLIB_COMPATIBILE], [AC_CACHE_CHECK( [if openssl/evp.h can be used in combination with zlib.h], [ac_cv_openssl_evp_zlib_compatible], [AC_LANG_PUSH(C) AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#include #include ]], [[ ]] )], [ac_cv_openssl_evp_zlib_compatible=yes], [ac_cv_openssl_evp_zlib_compatible=no]) AC_LANG_POP(C)]) ]) dnl Function to detect whether EVP_CipherInit_ex can be used with duplicate keys. AC_DEFUN([AX_LIBCRYPTO_CHECK_XTS_DUPLICATE_KEYS_SUPPORT], [AC_CACHE_CHECK( [if `EVP_CipherInit_ex' can be used with duplicate keys], [ac_cv_openssl_xts_duplicate_keys], [AC_LANG_PUSH(C) ac_cv_libcrypto_backup_LIBS="$LIBS" LIBS="$LIBS $ac_cv_libcrypto_LIBADD" AC_RUN_IFELSE( [AC_LANG_PROGRAM( [[#include #include #include ]], [[unsigned char key[ 16 ] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; int result = 0; #if defined( HAVE_EVP_CIPHER_CTX_INIT ) EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init( &ctx ); #else EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); #endif result = EVP_CipherInit_ex(ctx, EVP_aes_128_xts(), NULL, key, key, 0); #if defined( HAVE_EVP_CIPHER_CTX_INIT ) EVP_CIPHER_CTX_cleanup( &ctx ); #else EVP_CIPHER_CTX_free( ctx ); #endif if( result != 1 ) return( EXIT_FAILURE ); return( EXIT_SUCCESS ); ]] )], [ac_cv_openssl_xts_duplicate_keys=yes], [ac_cv_openssl_xts_duplicate_keys=no]) LIBS="$ac_cv_libcrypto_backup_LIBS" AC_LANG_POP(C)]) ]) dnl Function to detect if libcrypto (openssl) EVP functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_OPENSSL_EVP], [AC_CHECK_HEADERS([openssl/evp.h]) AS_IF( [test "x$ac_cv_header_openssl_evp_h" = xno], [ac_cv_libcrypto_evp=no], [AX_LIBCRYPTO_CHECK_OPENSSL_EVP_ZLIB_COMPATIBILE AS_IF( [test "x$ac_cv_openssl_evp_zlib_compatible" = xyes], [ac_cv_libcrypto_evp=yes], [ac_cv_libcrypto_evp=no]) ]) AS_IF( [test "x$ac_cv_libcrypto_evp" = xyes], [AC_DEFINE( [HAVE_OPENSSL_EVP_H], [1], [Define to 1 if you have the header file.]) AC_SUBST( [HAVE_OPENSSL_EVP_H], [1]) ], [AC_SUBST( [HAVE_OPENSSL_EVP_H], [0]) ]) ]) dnl Function to detect if libcrypto (openssl) EVP MD functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_OPENSSL_EVP_MD], [ac_cv_libcrypto_evp_md=yes AC_CHECK_LIB( crypto, EVP_MD_CTX_new, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_dummy=no]) AS_IF( [test "x$ac_cv_lib_crypto_EVP_MD_CTX_new" = xyes], [dnl Check for the new EVP API functions AC_CHECK_LIB( crypto, EVP_MD_CTX_free, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_md=no]) ], [dnl Check for the old EVP API functions AC_CHECK_LIB( crypto, EVP_MD_CTX_init, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_md=no]) AC_CHECK_LIB( crypto, EVP_MD_CTX_cleanup, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_md=no]) AC_CHECK_LIB( crypto, ERR_remove_thread_state, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_md=no]) ]) AC_CHECK_LIB( crypto, EVP_DigestInit_ex2, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_dummy=no]) AS_IF( [test "x$ac_cv_lib_crypto_EVP_DigestInit_ex2" = xyes], [dnl Check for OpenSSL 3 API functions AC_CHECK_LIB( crypto, EVP_MD_CTX_reset, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_md=no]) AC_CHECK_LIB( crypto, EVP_MD_fetch, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_md=no]) AC_CHECK_LIB( crypto, EVP_MD_free, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_md=no]) ], [AC_CHECK_LIB( crypto, EVP_DigestInit_ex, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_md=no]) ]) AC_CHECK_LIB( crypto, EVP_DigestUpdate, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_md=no]) AC_CHECK_LIB( crypto, EVP_DigestFinal_ex, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_md=no]) AS_IF( [test "x$ac_cv_enable_openssl_evp_md" = xyes && test "x$ac_cv_libcrypto_evp_md" = xno], [AC_MSG_FAILURE( [Missing OpenSSL EVP MD support], [1]) ]) AS_IF( [test "x$ac_cv_lib_crypto_EVP_MD_CTX_init" = xyes], [AC_DEFINE( [HAVE_EVP_MD_CTX_INIT], [1], [Define to 1 if you have the `EVP_MD_CTX_init' function".]) ]) AS_IF( [test "x$ac_cv_lib_crypto_EVP_MD_CTX_cleanup" = xyes], [AC_DEFINE( [HAVE_EVP_MD_CTX_CLEANUP], [1], [Define to 1 if you have the `EVP_MD_CTX_cleanup' function".]) ]) AS_IF( [test "x$ac_cv_lib_crypto_EVP_DigestInit_ex2" = xyes], [AC_DEFINE( [HAVE_EVP_DIGESTINIT_EX2], [1], [Define to 1 if you have the `EVP_DigestInit_ex2' function".]) ]) ]) dnl Function to detect if openssl EVP MD5 functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_OPENSSL_EVP_MD5], [AC_CHECK_LIB( crypto, EVP_md5, [ac_cv_libcrypto_md5=libcrypto_evp], [ac_cv_libcrypto_md5=no]) AS_IF( [test "x$ac_cv_libcrypto_md5" = xlibcrypto_evp], [AC_DEFINE( [HAVE_EVP_MD5], [1], [Define to 1 if you have the `EVP_md5' function".]) ]) ]) dnl Function to detect if openssl EVP SHA1 functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_OPENSSL_EVP_SHA1], [AC_CHECK_LIB( crypto, EVP_sha1, [ac_cv_libcrypto_sha1=libcrypto_evp], [ac_cv_libcrypto_sha1=no]) AS_IF( [test "x$ac_cv_libcrypto_sha1" = xlibcrypto_evp], [AC_DEFINE( [HAVE_EVP_SHA1], [1], [Define to 1 if you have the `EVP_sha1' function".]) ]) ]) dnl Function to detect if openssl EVP SHA224 functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_OPENSSL_EVP_SHA224], [AC_CHECK_LIB( crypto, EVP_sha224, [ac_cv_libcrypto_sha224=libcrypto_evp], [ac_cv_libcrypto_sha224=no]) AS_IF( [test "x$ac_cv_libcrypto_sha224" = xlibcrypto_evp], [AC_DEFINE( [HAVE_EVP_SHA224], [1], [Define to 1 if you have the `EVP_sha224' function".]) ]) ]) dnl Function to detect if openssl EVP SHA256 functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_OPENSSL_EVP_SHA256], [AC_CHECK_LIB( crypto, EVP_sha256, [ac_cv_libcrypto_sha256=libcrypto_evp], [ac_cv_libcrypto_sha256=no]) AS_IF( [test "x$ac_cv_libcrypto_sha256" = xlibcrypto_evp], [AC_DEFINE( [HAVE_EVP_SHA256], [1], [Define to 1 if you have the `EVP_sha256' function".]) ]) ]) dnl Function to detect if openssl EVP SHA512 functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_OPENSSL_EVP_SHA512], [AC_CHECK_LIB( crypto, EVP_sha512, [ac_cv_libcrypto_sha512=libcrypto_evp], [ac_cv_libcrypto_sha512=no]) AS_IF( [test "x$ac_cv_libcrypto_sha512" = xlibcrypto_evp], [AC_DEFINE( [HAVE_EVP_SHA512], [1], [Define to 1 if you have the `EVP_sha512' function".]) ]) ]) dnl Function to detect if openssl MD5 functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_OPENSSL_MD5], [AC_CHECK_HEADERS([openssl/md5.h]) AS_IF( [test "x$ac_cv_header_openssl_md5_h" = xno], [ac_cv_libcrypto_md5=no], [ac_cv_libcrypto_md5=libcrypto AC_CHECK_LIB( crypto, MD5_Init, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_md5=no]) AC_CHECK_LIB( crypto, MD5_Update, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_md5=no]) AC_CHECK_LIB( crypto, MD5_Final, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_md5=no]) ]) AS_IF( [test "x$ac_cv_libcrypto" = xno && test "x$ac_cv_libcrypto_md5" = xlibcrypto], [ac_cv_libcrypto=yes]) ]) dnl Function to detect if openssl SHA1 functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_OPENSSL_SHA1], [AC_CHECK_HEADERS([openssl/sha.h]) AS_IF( [test "x$ac_cv_header_openssl_sha_h" = xno], [ac_cv_libcrypto_sha1=no], [ac_cv_libcrypto_sha1=libcrypto AC_CHECK_LIB( crypto, SHA1_Init, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_sha1=no]) AC_CHECK_LIB( crypto, SHA1_Update, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_sha1=no]) AC_CHECK_LIB( crypto, SHA1_Final, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_sha1=no]) ]) AS_IF( [test "x$ac_cv_libcrypto" = xno && test "x$ac_cv_libcrypto_sha1" = xlibcrypto], [ac_cv_libcrypto=yes]) ]) dnl Function to detect if openssl SHA224 functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_OPENSSL_SHA224], [AC_CHECK_HEADERS([openssl/sha.h]) AS_IF( [test "x$ac_cv_header_openssl_sha_h" = xno], [ac_cv_libcrypto_sha224=no], [ac_cv_libcrypto_sha224=libcrypto AC_CHECK_LIB( crypto, SHA224_Init, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_sha224=no]) AC_CHECK_LIB( crypto, SHA224_Update, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_sha224=no]) AC_CHECK_LIB( crypto, SHA224_Final, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_sha224=no]) ]) AS_IF( [test "x$ac_cv_libcrypto" = xno && test "x$ac_cv_libcrypto_sha224" = xlibcrypto], [ac_cv_libcrypto=yes]) ]) dnl Function to detect if openssl SHA256 functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_OPENSSL_SHA256], [AC_CHECK_HEADERS([openssl/sha.h]) AS_IF( [test "x$ac_cv_header_openssl_sha_h" = xno], [ac_cv_libcrypto_sha256=no], [ac_cv_libcrypto_sha256=libcrypto AC_CHECK_LIB( crypto, SHA256_Init, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_sha256=no]) AC_CHECK_LIB( crypto, SHA256_Update, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_sha256=no]) AC_CHECK_LIB( crypto, SHA256_Final, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_sha256=no]) ]) AS_IF( [test "x$ac_cv_libcrypto" = xno && test "x$ac_cv_libcrypto_sha256" = xlibcrypto], [ac_cv_libcrypto=yes]) ]) dnl Function to detect if openssl SHA512 functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_OPENSSL_SHA512], [AC_CHECK_HEADERS([openssl/sha.h]) AS_IF( [test "x$ac_cv_header_openssl_sha_h" = xno], [ac_cv_libcrypto_sha512=no], [ac_cv_libcrypto_sha512=libcrypto AC_CHECK_LIB( crypto, SHA512_Init, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_sha512=no]) AC_CHECK_LIB( crypto, SHA512_Update, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_sha512=no]) AC_CHECK_LIB( crypto, SHA512_Final, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_sha512=no]) ]) AS_IF( [test "x$ac_cv_libcrypto" = xno && test "x$ac_cv_libcrypto_sha512" = xlibcrypto], [ac_cv_libcrypto=yes]) ]) dnl Function to detect if openssl EVP CIPHER functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_OPENSSL_EVP_CIPHER], [ac_cv_libcrypto_evp_cipher=yes dnl Check if all required libcrypto (openssl) EVP CIPHER functions are available AC_CHECK_LIB( crypto, EVP_CIPHER_CTX_new, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_dummy=no]) AS_IF( [test "x$ac_cv_lib_crypto_EVP_CIPHER_CTX_new" = xyes], [dnl Check for the new EVP API functions AC_CHECK_LIB( crypto, EVP_CIPHER_CTX_free, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_cipher=no]) ], [dnl Check for the old EVP API functions AC_CHECK_LIB( crypto, EVP_CIPHER_CTX_init, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_cipher=no]) AC_CHECK_LIB( crypto, EVP_CIPHER_CTX_cleanup, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_cipher=no]) AC_CHECK_LIB( crypto, ERR_remove_thread_state, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_cipher=no]) ]) AC_CHECK_LIB( crypto, EVP_CipherInit_ex2, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_dummy=no]) AS_IF( [test "x$ac_cv_lib_crypto_EVP_CipherInit_ex2" = xyes], [dnl Check for OpenSSL 3 API functions AC_CHECK_LIB( crypto, EVP_CIPHER_CTX_reset, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_cipher=no]) AC_CHECK_LIB( crypto, EVP_CIPHER_fetch, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_cipher=no]) AC_CHECK_LIB( crypto, EVP_CIPHER_free, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_cipher=no]) ], [AC_CHECK_LIB( crypto, EVP_CipherInit_ex, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_cipher=no]) AC_CHECK_LIB( crypto, EVP_CIPHER_CTX_set_padding, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_cipher=no]) ]) AC_CHECK_LIB( crypto, EVP_CipherUpdate, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_cipher=no]) AC_CHECK_LIB( crypto, EVP_CipherFinal_ex, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_evp_cipher=no]) AS_IF( [test "x$ac_cv_enable_openssl_evp_cipher" = xyes && test "x$ac_cv_libcrypto_evp_cipher" = xno], [AC_MSG_FAILURE( [Missing OpenSSL EVP CIPHER support], [1]) ]) AS_IF( [test "x$ac_cv_lib_crypto_EVP_CIPHER_CTX_init" = xyes], [AC_DEFINE( [HAVE_EVP_CIPHER_CTX_INIT], [1], [Define to 1 if you have the `EVP_CIPHER_CTX_init' function".]) ]) AS_IF( [test "x$ac_cv_lib_crypto_EVP_CIPHER_CTX_cleanup" = xyes], [AC_DEFINE( [HAVE_EVP_CIPHER_CTX_CLEANUP], [1], [Define to 1 if you have the `EVP_CIPHER_CTX_cleanup' function".]) ]) AS_IF( [test "x$ac_cv_lib_crypto_EVP_CipherInit_ex2" = xyes], [AC_DEFINE( [HAVE_EVP_CIPHERINIT_EX2], [1], [Define to 1 if you have the `EVP_CipherInit_ex2' function".]) ]) ]) dnl Function to detect if openssl AES-CBC and AES-ECB functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_OPENSSL_AES], [AC_CHECK_HEADERS([openssl/aes.h]) AS_IF( [test "x$ac_cv_header_openssl_aes_h" = xno], [ac_cv_libcrypto_aes_cbc=no ac_cv_libcrypto_aes_ecb=no], [ac_cv_libcrypto_aes_cbc=libcrypto ac_cv_libcrypto_aes_ecb=libcrypto AC_CHECK_LIB( crypto, AES_set_decrypt_key, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_aes_cbc=no, ac_cv_libcrypto_aes_ecb=no]) AC_CHECK_LIB( crypto, AES_set_encrypt_key, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_aes_cbc=no, ac_cv_libcrypto_aes_ecb=no]) AC_CHECK_LIB( crypto, AES_cbc_encrypt, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_aes_cbc=no]) AC_CHECK_LIB( crypto, AES_ecb_encrypt, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_aes_ecb=no]) AS_IF( [test "x$ac_cv_lib_crypto_AES_cbc_encrypt" = xyes], [AC_DEFINE( [HAVE_AES_CBC_ENCRYPT], [1], [Define to 1 if you have the `AES_cbc_encrypt' function".]) ]) AS_IF( [test "x$ac_cv_lib_crypto_AES_ecb_encrypt" = xyes], [AC_DEFINE( [HAVE_AES_ECB_ENCRYPT], [1], [Define to 1 if you have the `AES_ecb_encrypt' function".]) ]) ]) AS_IF( [test "x$ac_cv_libcrypto" = xno], [AS_IF( [test "x$ac_cv_libcrypto_aes_cbc" = xno || test "x$ac_cv_libcrypto_aes_ecb" = xno], [ac_cv_libcrypto=yes]) ]) dnl ac_cv_libcrypto_aes is deprecated but kept for backwards compatibility AS_IF( [test "x$ac_cv_libcrypto_aes_cbc" = xno || test "x$ac_cv_libcrypto_aes_ecb" = xno], [ac_cv_libcrypto_aes=no], [ac_cv_libcrypto_aes=libcrypto]) ]) dnl Function to detect if libcrypto (openssl) dependencies are available AC_DEFUN([AX_LIBCRYPTO_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_openssl" = xno], [ac_cv_libcrypto=no], [dnl Check if the directory provided as parameter exists dnl For both --with-openssl which returns "yes" and --with-openssl= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_openssl" != x && test "x$ac_cv_with_openssl" != xauto-detect && test "x$ac_cv_with_openssl" != xyes], [AS_IF( [test -d "$ac_cv_with_openssl"], [CFLAGS="$CFLAGS -I${ac_cv_with_openssl}/include" LDFLAGS="$LDFLAGS -L${ac_cv_with_openssl}/lib"], [AC_MSG_FAILURE( [no such directory: $ac_cv_with_openssl], [1]) ])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [openssl], [openssl >= 1.0], [ac_cv_libcrypto=yes ac_cv_libcrypto_evp=yes], [ac_cv_libcrypto=no ac_cv_libcrypto_evp=no]) ]) AS_IF( [test "x$ac_cv_libcrypto" = xyes], [ac_cv_libcrypto_CPPFLAGS="$pkg_cv_openssl_CFLAGS" ac_cv_libcrypto_LIBADD="$pkg_cv_openssl_LIBS"]) ]) AS_IF( [test "x$ac_cv_libcrypto" != xyes], [dnl Check for headers AC_CHECK_HEADERS([openssl/opensslv.h]) AS_IF( [test "x$ac_cv_header_openssl_opensslv" = xyes], [ac_cv_libcrypto=yes]) ]) ]) AX_LIBCRYPTO_CHECK_OPENSSL_EVP AS_IF( [test "x$ac_cv_libcrypto" != xno], [AC_DEFINE( [HAVE_LIBCRYPTO], [1], [Define to 1 if you have the 'crypto' library (-lcrypto).]) ac_cv_libcrypto_CPPFLAGS="$openssl_CFLAGS" ac_cv_libcrypto_LIBADD="$openssl_LIBS" AS_IF( [test "x$ac_cv_libcrypto_LIBADD" = x], [ac_cv_libcrypto_LIBADD="-lcrypto"]) dnl On Cygwin also link zlib since libcrypto relies on it AS_CASE( [$host], [*cygwin*], [ac_cv_libcrypto_LIBADD="$ac_cv_libcrypto_LIBADD -lz"]) dnl Enforce the dynamic loader library to be included if available AC_CHECK_LIB( dl, dlopen, [AC_SUBST( [LIBDL_LIBADD], ["-ldl"])], []) ]) ]) ]) dnl Function to detect if libcrypto MD5 functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_MD5], [ac_cv_libcrypto_md5=no dnl Check for libcrypto (openssl) EVP MD support AS_IF( [test "x$ac_cv_libcrypto_evp" = xyes && test "x$ac_cv_libcrypto_evp_md" != xyes], [AX_LIBCRYPTO_CHECK_OPENSSL_EVP_MD]) dnl Check for libcrypto (openssl) EVP MD5 support AS_IF( [test "x$ac_cv_libcrypto_evp_md" = xyes], [AX_LIBCRYPTO_CHECK_OPENSSL_EVP_MD5]) dnl Check for libcrypto (openssl) MD5 support AS_IF( [test "x$ac_cv_libcrypto_md5" = xno], [AX_LIBCRYPTO_CHECK_OPENSSL_MD5]) ]) dnl Function to detect if libcrypto SHA1 functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_SHA1], [ac_cv_libcrypto_sha1=no dnl Check for libcrypto (openssl) EVP MD support AS_IF( [test "x$ac_cv_libcrypto_evp" = xyes && test "x$ac_cv_enable_openssl_evp_md" != xno && test "x$ac_cv_libcrypto_evp_md" != xyes], [AX_LIBCRYPTO_CHECK_OPENSSL_EVP_MD]) dnl Check for libcrypto (openssl) EVP SHA1 support AS_IF( [test "x$ac_cv_libcrypto_evp_md" = xyes], [AX_LIBCRYPTO_CHECK_OPENSSL_EVP_SHA1]) dnl Check for libcrypto (openssl) SHA1 support AS_IF( [test "x$ac_cv_libcrypto_sha1" = xno], [AX_LIBCRYPTO_CHECK_OPENSSL_SHA1]) ]) dnl Function to detect if libcrypto SHA224 functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_SHA224], [ac_cv_libcrypto_sha224=no dnl Check for libcrypto (openssl) EVP MD support AS_IF( [test "x$ac_cv_libcrypto_evp" = xyes && test "x$ac_cv_enable_openssl_evp_md" != xno && test "x$ac_cv_libcrypto_evp_md" != xyes], [AX_LIBCRYPTO_CHECK_OPENSSL_EVP_MD]) dnl Check for libcrypto (openssl) EVP SHA224 support AS_IF( [test "x$ac_cv_libcrypto_evp_md" = xyes], [AX_LIBCRYPTO_CHECK_OPENSSL_EVP_SHA224]) dnl Check for libcrypto (openssl) SHA224 support AS_IF( [test "x$ac_cv_libcrypto_sha224" = xno], [AX_LIBCRYPTO_CHECK_OPENSSL_SHA224]) ]) dnl Function to detect if libcrypto SHA256 functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_SHA256], [ac_cv_libcrypto_sha256=no dnl Check for libcrypto (openssl) EVP MD support AS_IF( [test "x$ac_cv_libcrypto_evp" = xyes && test "x$ac_cv_enable_openssl_evp_md" != xno && test "x$ac_cv_libcrypto_evp_md" != xyes], [AX_LIBCRYPTO_CHECK_OPENSSL_EVP_MD]) dnl Check for libcrypto (openssl) EVP SHA256 support AS_IF( [test "x$ac_cv_libcrypto_evp_md" = xyes], [AX_LIBCRYPTO_CHECK_OPENSSL_EVP_SHA256]) dnl Check for libcrypto (openssl) SHA256 support AS_IF( [test "x$ac_cv_libcrypto_sha256" = xno], [AX_LIBCRYPTO_CHECK_OPENSSL_SHA256]) ]) dnl Function to detect if libcrypto SHA512 functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_SHA512], [ac_cv_libcrypto_sha512=no dnl Check for libcrypto (openssl) EVP MD support AS_IF( [test "x$ac_cv_libcrypto_evp" = xyes && test "x$ac_cv_enable_openssl_evp_md" != xno && test "x$ac_cv_libcrypto_evp_md" != xyes], [AX_LIBCRYPTO_CHECK_OPENSSL_EVP_MD]) dnl Check for libcrypto (openssl) EVP SHA512 support AS_IF( [test "x$ac_cv_libcrypto_evp_md" = xyes], [AX_LIBCRYPTO_CHECK_OPENSSL_EVP_SHA512]) dnl Check for libcrypto (openssl) SHA512 support AS_IF( [test "x$ac_cv_libcrypto_sha512" = xno], [AX_LIBCRYPTO_CHECK_OPENSSL_SHA512]) ]) dnl Function to detect if libcrypto AES-CBC and AES-ECB functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_AES], [dnl Check for libcrypto (openssl) EVP CIPHER AES-CBC and AES-ECB support AX_LIBCRYPTO_CHECK_AES_CBC AX_LIBCRYPTO_CHECK_AES_ECB dnl ac_cv_libcrypto_aes is deprecated but kept for backwards compatibility AS_IF( [test "x$ac_cv_libcrypto_aes_cbc" = xno || test "x$ac_cv_libcrypto_aes_ecb" = xno], [ac_cv_libcrypto_aes=no], [ac_cv_libcrypto_aes=libcrypto_evp]) dnl Check for libcrypto (openssl) AES-CBC and AES-ECB support AS_IF( [test "x$ac_cv_libcrypto_aes_cbc" = xno || test "x$ac_cv_libcrypto_aes_ecb" = xno], [AX_LIBCRYPTO_CHECK_OPENSSL_AES]) ]) dnl Function to detect if libcrypto AES-CBC functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_AES_CBC], [AS_IF( [test "x$ac_cv_libcrypto_evp" = xyes && test "x$ac_cv_enable_openssl_evp_cipher" != xno && test "x$ac_cv_libcrypto_evp_cipher" != xyes], [AX_LIBCRYPTO_CHECK_OPENSSL_EVP_CIPHER]) AS_IF( [test "x$ac_cv_libcrypto_evp_cipher" != xyes], [ac_cv_libcrypto_aes_cbc=no], [ac_cv_libcrypto_aes_cbc=libcrypto_evp AC_CHECK_LIB( crypto, EVP_aes_128_cbc, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_aes_cbc=no]) AC_CHECK_LIB( crypto, EVP_aes_192_cbc, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_aes_cbc=no]) AC_CHECK_LIB( crypto, EVP_aes_256_cbc, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_aes_cbc=no]) AS_IF( [test "x$ac_cv_lib_crypto_EVP_aes_128_cbc" = xyes && test "x$ac_cv_lib_crypto_EVP_aes_192_cbc" = xyes && test "x$ac_cv_lib_crypto_EVP_aes_256_cbc" = xyes], [AC_DEFINE( [HAVE_EVP_CRYPTO_AES_CBC], [1], [Define to 1 if you have the `EVP_aes_128_cbc', `EVP_aes_192_cbc' and `EVP_aes_256_cbc' functions".]) ]) ]) ]) dnl Function to detect if libcrypto AES-ECB functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_AES_ECB], [AS_IF( [test "x$ac_cv_libcrypto_evp" = xyes && test "x$ac_cv_enable_openssl_evp_cipher" != xno && test "x$ac_cv_libcrypto_evp_cipher" != xyes], [AX_LIBCRYPTO_CHECK_OPENSSL_EVP_CIPHER]) AS_IF( [test "x$ac_cv_libcrypto_evp_cipher" != xyes], [ac_cv_libcrypto_aes_ecb=no], [ac_cv_libcrypto_aes_ecb=libcrypto_evp AC_CHECK_LIB( crypto, EVP_aes_128_ecb, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_aes_ecb=no]) AC_CHECK_LIB( crypto, EVP_aes_192_ecb, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_aes_ecb=no]) AC_CHECK_LIB( crypto, EVP_aes_256_ecb, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_aes_ecb=no]) AS_IF( [test "x$ac_cv_lib_crypto_EVP_aes_128_ecb" = xyes && test "x$ac_cv_lib_crypto_EVP_aes_192_ecb" = xyes && test "x$ac_cv_lib_crypto_EVP_aes_256_ecb" = xyes], [AC_DEFINE( [HAVE_EVP_CRYPTO_AES_ECB], [1], [Define to 1 if you have the `EVP_aes_128_ecb', `EVP_aes_192_ecb' and `EVP_aes_256_ecb' functions".]) ]) ]) ]) dnl Function to detect if libcrypto AES-XTS functions are available AC_DEFUN([AX_LIBCRYPTO_CHECK_AES_XTS], [AS_IF( [test "x$ac_cv_libcrypto_evp" = xyes && test "x$ac_cv_enable_openssl_evp_cipher" != xno && test "x$ac_cv_libcrypto_evp_cipher" != xyes], [AX_LIBCRYPTO_CHECK_OPENSSL_EVP_CIPHER]) AS_IF( [test "x$ac_cv_libcrypto_evp_cipher" != xyes], [ac_cv_libcrypto_aes_xts=no], [ac_cv_libcrypto_aes_xts=libcrypto_evp AC_CHECK_LIB( crypto, EVP_aes_128_xts, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_aes_xts=no]) AC_CHECK_LIB( crypto, EVP_aes_256_xts, [ac_cv_libcrypto_dummy=yes], [ac_cv_libcrypto_aes_xts=no]) dnl OpenSSL 1.1.1c will error with "xts duplicated keys". AX_LIBCRYPTO_CHECK_XTS_DUPLICATE_KEYS_SUPPORT AS_IF( [test "x$ac_cv_openssl_xts_duplicate_keys" = xno], [ac_cv_libcrypto_aes_xts=no], [AS_IF( [test "x$ac_cv_lib_crypto_EVP_aes_128_xts" = xyes && test "x$ac_cv_lib_crypto_EVP_aes_256_xts" = xyes], [AC_DEFINE( [HAVE_EVP_CRYPTO_AES_XTS], [1], [Define to 1 if you have the `EVP_aes_128_xts' and `EVP_aes_256_xts' functions".]) ]) ]) ]) ]) dnl Function to detect how to enable libcrypto (openssl) AC_DEFUN([AX_LIBCRYPTO_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [openssl], [openssl], [search for OpenSSL in includedir and libdir or in the specified DIR, or no if not to use OpenSSL], [auto-detect], [DIR]) AX_COMMON_ARG_ENABLE( [openssl-evp-cipher], [openssl_evp_cipher], [enable OpenSSL EVP CIPHER support, or no to disable], [auto-detect]) AX_COMMON_ARG_ENABLE( [openssl-evp-md], [openssl_evp_md], [enable OpenSSL EVP MD support, or no to disable], [auto-detect]) AS_IF( [test "x$ac_cv_enable_static_executables" != xyes], [dnl Check for a shared library version AX_LIBCRYPTO_CHECK_LIB]) AS_IF( [test "x$ac_cv_libcrypto_CPPFLAGS" != "x"], [AC_SUBST( [LIBCRYPTO_CPPFLAGS], [$ac_cv_libcrypto_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libcrypto_LIBADD" != "x"], [AC_SUBST( [LIBCRYPTO_LIBADD], [$ac_cv_libcrypto_LIBADD]) ]) AS_IF( [test "x$ac_cv_libcrypto" != xno], [AC_SUBST( [ax_libcrypto_pc_libs_private], [-lcrypto]) ]) AS_IF( [test "x$ac_cv_libcrypto" != xno], [AC_SUBST( [ax_libcrypto_spec_requires], [openssl]) AC_SUBST( [ax_libcrypto_spec_build_requires], [openssl-devel]) ]) ]) ================================================ FILE: m4/libcsplit.m4 ================================================ dnl Checks for libcsplit required headers and functions dnl dnl Version: 20240513 dnl Function to detect if libcsplit is available dnl ac_libcsplit_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l arguments AC_DEFUN([AX_LIBCSPLIT_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_libcsplit" = xno], [ac_cv_libcsplit=no], [ac_cv_libcsplit=check dnl Check if the directory provided as parameter exists dnl For both --with-libcsplit which returns "yes" and --with-libcsplit= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_libcsplit" != x && test "x$ac_cv_with_libcsplit" != xauto-detect && test "x$ac_cv_with_libcsplit" != xyes], [AX_CHECK_LIB_DIRECTORY_EXISTS([libcsplit])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [libcsplit], [libcsplit >= 20120701], [ac_cv_libcsplit=yes], [ac_cv_libcsplit=check]) ]) AS_IF( [test "x$ac_cv_libcsplit" = xyes && test "x$ac_cv_enable_wide_character_type" != xno], [AC_CACHE_CHECK( [whether libcsplit/features.h defines LIBCSPLIT_HAVE_WIDE_CHARACTER_TYPE as 1], [ac_cv_header_libcsplit_features_h_have_wide_character_type], [AC_LANG_PUSH(C) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [[#include ]], [[#if !defined( LIBCSPLIT_HAVE_WIDE_CHARACTER_TYPE ) || ( LIBCSPLIT_HAVE_WIDE_CHARACTER_TYPE != 1 ) #error LIBCSPLIT_HAVE_WIDE_CHARACTER_TYPE not defined #endif]] )], [ac_cv_header_libcsplit_features_h_have_wide_character_type=yes], [ac_cv_header_libcsplit_features_h_have_wide_character_type=no]) AC_LANG_POP(C)], [ac_cv_header_libcsplit_features_h_have_wide_character_type=no]) AS_IF( [test "x$ac_cv_header_libcsplit_features_h_have_wide_character_type" = xno], [ac_cv_libcsplit=no]) ]) AS_IF( [test "x$ac_cv_libcsplit" = xyes], [ac_cv_libcsplit_CPPFLAGS="$pkg_cv_libcsplit_CFLAGS" ac_cv_libcsplit_LIBADD="$pkg_cv_libcsplit_LIBS"]) ]) AS_IF( [test "x$ac_cv_libcsplit" = xcheck], [dnl Check for headers AC_CHECK_HEADERS([libcsplit.h]) AS_IF( [test "x$ac_cv_header_libcsplit_h" = xno], [ac_cv_libcsplit=no], [ac_cv_libcsplit=yes AX_CHECK_LIB_FUNCTIONS( [libcsplit], [csplit], [[libcsplit_get_version], [libcsplit_narrow_string_split], [libcsplit_narrow_split_string_free], [libcsplit_narrow_split_string_get_string], [libcsplit_narrow_split_string_get_number_of_segments], [libcsplit_narrow_split_string_get_segment_by_index], [libcsplit_narrow_split_string_set_segment_by_index]]) dnl Wide string functions AS_IF( [test "x$ac_cv_enable_wide_character_type" != xno], [AX_CHECK_LIB_FUNCTIONS( [libcsplit], [csplit], [[libcsplit_wide_string_split], [libcsplit_wide_split_string_free], [libcsplit_wide_split_string_get_string], [libcsplit_wide_split_string_get_number_of_segments], [libcsplit_wide_split_string_get_segment_by_index], [libcsplit_wide_split_string_set_segment_by_index]]) ]) ac_cv_libcsplit_LIBADD="-lcsplit"]) ]) AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE([libcsplit]) ]) AS_IF( [test "x$ac_cv_libcsplit" = xyes], [AC_DEFINE( [HAVE_LIBCSPLIT], [1], [Define to 1 if you have the `csplit' library (-lcsplit).]) ]) AS_IF( [test "x$ac_cv_libcsplit" = xyes], [AC_SUBST( [HAVE_LIBCSPLIT], [1]) ], [AC_SUBST( [HAVE_LIBCSPLIT], [0]) ]) ]) dnl Function to detect if libcsplit dependencies are available AC_DEFUN([AX_LIBCSPLIT_CHECK_LOCAL], [dnl No additional checks. ac_cv_libcsplit_CPPFLAGS="-I../libcsplit -I\$(top_srcdir)/libcsplit"; ac_cv_libcsplit_LIBADD="../libcsplit/libcsplit.la"; ac_cv_libcsplit=local ]) dnl Function to detect how to enable libcsplit AC_DEFUN([AX_LIBCSPLIT_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [libcsplit], [libcsplit], [search for libcsplit in includedir and libdir or in the specified DIR, or no if to use local version], [auto-detect], [DIR]) dnl Check for a shared library version AX_LIBCSPLIT_CHECK_LIB dnl Check if the dependencies for the local library version AS_IF( [test "x$ac_cv_libcsplit" != xyes], [AX_LIBCSPLIT_CHECK_LOCAL AC_DEFINE( [HAVE_LOCAL_LIBCSPLIT], [1], [Define to 1 if the local version of libcsplit is used.]) AC_SUBST( [HAVE_LOCAL_LIBCSPLIT], [1]) ]) AM_CONDITIONAL( [HAVE_LOCAL_LIBCSPLIT], [test "x$ac_cv_libcsplit" = xlocal]) AS_IF( [test "x$ac_cv_libcsplit_CPPFLAGS" != "x"], [AC_SUBST( [LIBCSPLIT_CPPFLAGS], [$ac_cv_libcsplit_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libcsplit_LIBADD" != "x"], [AC_SUBST( [LIBCSPLIT_LIBADD], [$ac_cv_libcsplit_LIBADD]) ]) AS_IF( [test "x$ac_cv_libcsplit" = xyes], [AC_SUBST( [ax_libcsplit_pc_libs_private], [-lcsplit]) ]) AS_IF( [test "x$ac_cv_libcsplit" = xyes], [AC_SUBST( [ax_libcsplit_spec_requires], [libcsplit]) AC_SUBST( [ax_libcsplit_spec_build_requires], [libcsplit-devel]) ]) ]) ================================================ FILE: m4/libcthreads.m4 ================================================ dnl Checks for libcthreads required headers and functions dnl dnl Version: 20240513 dnl Function to detect if libcthreads is available dnl ac_libcthreads_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l arguments AC_DEFUN([AX_LIBCTHREADS_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_libcthreads" = xno], [ac_cv_libcthreads=no], [ac_cv_libcthreads=check dnl Check if the directory provided as parameter exists dnl For both --with-libcthreads which returns "yes" and --with-libcthreads= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_libcthreads" != x && test "x$ac_cv_with_libcthreads" != xauto-detect && test "x$ac_cv_with_libcthreads" != xyes], [AX_CHECK_LIB_DIRECTORY_EXISTS([libcthreads])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [libcthreads], [libcthreads >= 20160404], [ac_cv_libcthreads=yes], [ac_cv_libcthreads=check]) ]) AS_IF( [test "x$ac_cv_libcthreads" = xyes], [ac_cv_libcthreads_CPPFLAGS="$pkg_cv_libcthreads_CFLAGS" ac_cv_libcthreads_LIBADD="$pkg_cv_libcthreads_LIBS"]) ]) AS_IF( [test "x$ac_cv_libcthreads" = xcheck], [dnl Check for headers AC_CHECK_HEADERS([libcthreads.h]) AS_IF( [test "x$ac_cv_header_libcthreads_h" = xno], [ac_cv_libcthreads=no], [ac_cv_libcthreads=yes AX_CHECK_LIB_FUNCTIONS( [libcthreads], [cthreads], [[libcthreads_get_version], [libcthreads_thread_create], [libcthreads_thread_join], [libcthreads_thread_attributes_initialize], [libcthreads_thread_attributes_free], [libcthreads_condition_initialize], [libcthreads_condition_free], [libcthreads_condition_broadcast], [libcthreads_condition_signal], [libcthreads_condition_wait], [libcthreads_lock_initialize], [libcthreads_lock_free], [libcthreads_lock_grab], [libcthreads_lock_release], [libcthreads_mutex_initialize], [libcthreads_mutex_free], [libcthreads_mutex_grab], [libcthreads_mutex_try_grab], [libcthreads_mutex_release], [libcthreads_read_write_lock_initialize], [libcthreads_read_write_lock_free], [libcthreads_read_write_lock_grab_for_read], [libcthreads_read_write_lock_grab_for_write], [libcthreads_read_write_lock_release_for_read], [libcthreads_read_write_lock_release_for_write], [libcthreads_queue_initialize], [libcthreads_queue_free], [libcthreads_queue_type_pop], [libcthreads_queue_pop], [libcthreads_queue_try_push], [libcthreads_queue_push], [libcthreads_queue_push_sorted], [libcthreads_thread_pool_create], [libcthreads_thread_pool_push], [libcthreads_thread_pool_push_sorted], [libcthreads_thread_pool_join]]) ac_cv_libcthreads_LIBADD="-lcthreads"]) ]) AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE([libcthreads]) ]) AS_IF( [test "x$ac_cv_libcthreads" = xyes], [AC_DEFINE( [HAVE_LIBCTHREADS], [1], [Define to 1 if you have the `cthreads' library (-lcthreads).]) ]) AS_IF( [test "x$ac_cv_libcthreads" = xyes], [ac_cv_libcthreads_multi_threading=libcthreads], [ac_cv_libcthreads_multi_threading=no]) AS_IF( [test "x$ac_cv_libcthreads" = xyes], [AC_SUBST( [HAVE_LIBCTHREADS], [1]) ], [AC_SUBST( [HAVE_LIBCTHREADS], [0]) ]) ]) dnl Function to detect if libcthreads dependencies are available AC_DEFUN([AX_LIBCTHREADS_CHECK_LOCAL], [AS_IF( [test "x$ac_cv_enable_winapi" = xno], [dnl Check for enabling pthread support AX_PTHREAD_CHECK_ENABLE ac_cv_libcthreads_multi_threading=$ac_cv_pthread], [ac_cv_libcthreads_multi_threading="winapi"]) AS_IF( [test "x$ac_cv_libcthreads_multi_threading" != xno], [ac_cv_libcthreads_CPPFLAGS="-I../libcthreads -I\$(top_srcdir)/libcthreads"; ac_cv_libcthreads_LIBADD="../libcthreads/libcthreads.la"; ac_cv_libcthreads=local], [ac_cv_libcthreads=no]) ]) dnl Function to detect how to enable libcthreads AC_DEFUN([AX_LIBCTHREADS_CHECK_ENABLE], [AX_COMMON_ARG_ENABLE( [multi-threading-support], [multi_threading_support], [enable multi-threading support], [yes]) AX_COMMON_ARG_WITH( [libcthreads], [libcthreads], [search for libcthreads in includedir and libdir or in the specified DIR, or no if to use local version], [auto-detect], [DIR]) AS_IF( [test "x$ac_cv_enable_multi_threading_support" = xno], [ac_cv_libcthreads="no" ac_cv_libcthreads_multi_threading="no"], [dnl Check for a shared library version AX_LIBCTHREADS_CHECK_LIB dnl Check if the dependencies for the local library version AS_IF( [test "x$ac_cv_libcthreads" != xyes], [AX_LIBCTHREADS_CHECK_LOCAL AC_DEFINE( [HAVE_LOCAL_LIBCTHREADS], [1], [Define to 1 if the local version of libcthreads is used.]) AC_SUBST( [HAVE_LOCAL_LIBCTHREADS], [1]) ]) ]) AM_CONDITIONAL( [HAVE_LOCAL_LIBCTHREADS], [test "x$ac_cv_libcthreads" = xlocal]) AS_IF( [test "x$ac_cv_libcthreads_CPPFLAGS" != "x"], [AC_SUBST( [LIBCTHREADS_CPPFLAGS], [$ac_cv_libcthreads_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libcthreads_LIBADD" != "x"], [AC_SUBST( [LIBCTHREADS_LIBADD], [$ac_cv_libcthreads_LIBADD]) ]) AS_IF( [test "x$ac_cv_libcthreads" != xno], [AC_DEFINE( [HAVE_MULTI_THREAD_SUPPORT], [1], [Define to 1 if multi thread support should be used.]) AC_SUBST( [HAVE_MULTI_THREAD_SUPPORT], [1]) ], [AC_SUBST( [HAVE_MULTI_THREAD_SUPPORT], [0]) ]) AS_IF( [test "x$ac_cv_libcthreads" = xyes], [AC_SUBST( [ax_libcthreads_pc_libs_private], [-lcthreads]) ]) AS_IF( [test "x$ac_cv_libcthreads" = xyes], [AC_SUBST( [ax_libcthreads_spec_requires], [libcthreads]) AC_SUBST( [ax_libcthreads_spec_build_requires], [libcthreads-devel]) ]) ]) ================================================ FILE: m4/libfcache.m4 ================================================ dnl Checks for libfcache required headers and functions dnl dnl Version: 20240514 dnl Function to detect if libfcache is available dnl ac_libfcache_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l arguments AC_DEFUN([AX_LIBFCACHE_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_libfcache" = xno], [ac_cv_libfcache=no], [ac_cv_libfcache=check dnl Check if the directory provided as parameter exists dnl For both --with-libfcache which returns "yes" and --with-libfcache= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_libfcache" != x && test "x$ac_cv_with_libfcache" != xauto-detect && test "x$ac_cv_with_libfcache" != xyes], [AX_CHECK_LIB_DIRECTORY_EXISTS([libfcache])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [libfcache], [libfcache >= 20191109], [ac_cv_libfcache=yes], [ac_cv_libfcache=check]) ]) AS_IF( [test "x$ac_cv_libfcache" = xyes], [ac_cv_libfcache_CPPFLAGS="$pkg_cv_libfcache_CFLAGS" ac_cv_libfcache_LIBADD="$pkg_cv_libfcache_LIBS"]) ]) AS_IF( [test "x$ac_cv_libfcache" = xcheck], [dnl Check for headers AC_CHECK_HEADERS([libfcache.h]) AS_IF( [test "x$ac_cv_header_libfcache_h" = xno], [ac_cv_libfcache=no], [ac_cv_libfcache=yes AX_CHECK_LIB_FUNCTIONS( [libfcache], [fcache], [[libfcache_get_version], [libfcache_cache_initialize], [libfcache_cache_free], [libfcache_cache_clone], [libfcache_cache_clear], [libfcache_cache_get_number_of_entries], [libfcache_cache_get_number_of_cache_values], [libfcache_cache_clear_value_by_index], [libfcache_cache_get_value_by_identifier], [libfcache_cache_get_value_by_index], [libfcache_cache_set_value_by_identifier], [libfcache_cache_set_value_by_index], [libfcache_cache_value_free], [libfcache_cache_value_clear], [libfcache_cache_value_get_identifier], [libfcache_cache_value_set_identifier], [libfcache_cache_value_get_value], [libfcache_cache_value_set_value], [libfcache_date_time_get_timestamp]]) ac_cv_libfcache_LIBADD="-lfcache"]) ]) AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE([libfcache]) ]) AS_IF( [test "x$ac_cv_libfcache" = xyes], [AC_DEFINE( [HAVE_LIBFCACHE], [1], [Define to 1 if you have the `fcache' library (-lfcache).]) ]) AS_IF( [test "x$ac_cv_libfcache" = xyes], [AC_SUBST( [HAVE_LIBFCACHE], [1]) ], [AC_SUBST( [HAVE_LIBFCACHE], [0]) ]) ]) dnl Function to detect if libfcache dependencies are available AC_DEFUN([AX_LIBFCACHE_CHECK_LOCAL], [dnl Types used in libfcache/libfcache_date_time.h AC_STRUCT_TM dnl Headers included in libfcache/libfcache_date_time.h AC_CHECK_HEADERS([sys/time.h]) dnl Date and time functions used in libfcache/libfcache_date_time.h AC_CHECK_FUNCS([clock_gettime time]) AS_IF( [test "x$ac_cv_func_time" != xyes], [AC_MSG_FAILURE( [Missing function: time], [1]) ]) ac_cv_libfcache_CPPFLAGS="-I../libfcache -I\$(top_srcdir)/libfcache"; ac_cv_libfcache_LIBADD="../libfcache/libfcache.la"; ac_cv_libfcache=local ]) dnl Function to detect how to enable libfcache AC_DEFUN([AX_LIBFCACHE_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [libfcache], [libfcache], [search for libfcache in includedir and libdir or in the specified DIR, or no if to use local version], [auto-detect], [DIR]) dnl Check for a shared library version AX_LIBFCACHE_CHECK_LIB dnl Check if the dependencies for the local library version AS_IF( [test "x$ac_cv_libfcache" != xyes], [AX_LIBFCACHE_CHECK_LOCAL AC_DEFINE( [HAVE_LOCAL_LIBFCACHE], [1], [Define to 1 if the local version of libfcache is used.]) AC_SUBST( [HAVE_LOCAL_LIBFCACHE], [1]) ]) AM_CONDITIONAL( [HAVE_LOCAL_LIBFCACHE], [test "x$ac_cv_libfcache" = xlocal]) AS_IF( [test "x$ac_cv_libfcache_CPPFLAGS" != "x"], [AC_SUBST( [LIBFCACHE_CPPFLAGS], [$ac_cv_libfcache_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libfcache_LIBADD" != "x"], [AC_SUBST( [LIBFCACHE_LIBADD], [$ac_cv_libfcache_LIBADD]) ]) AS_IF( [test "x$ac_cv_libfcache" = xyes], [AC_SUBST( [ax_libfcache_pc_libs_private], [-lfcache]) ]) AS_IF( [test "x$ac_cv_libfcache" = xyes], [AC_SUBST( [ax_libfcache_spec_requires], [libfcache]) AC_SUBST( [ax_libfcache_spec_build_requires], [libfcache-devel]) ]) ]) ================================================ FILE: m4/libfdata.m4 ================================================ dnl Functions for libfdata dnl dnl Version: 20240520 dnl Function to detect if libfdata is available dnl ac_libfdata_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l arguments AC_DEFUN([AX_LIBFDATA_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_libfdata" = xno], [ac_cv_libfdata=no], [ac_cv_libfdata=check dnl Check if the directory provided as parameter exists dnl For both --with-libfdata which returns "yes" and --with-libfdata= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_libfdata" != x && test "x$ac_cv_with_libfdata" != xauto-detect && test "x$ac_cv_with_libfdata" != xyes], [AX_CHECK_LIB_DIRECTORY_EXISTS([libfdata])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [libfdata], [libfdata >= 20201129], [ac_cv_libfdata=yes], [ac_cv_libfdata=check]) ]) AS_IF( [test "x$ac_cv_libfdata" = xyes], [ac_cv_libfdata_CPPFLAGS="$pkg_cv_libfdata_CFLAGS" ac_cv_libfdata_LIBADD="$pkg_cv_libfdata_LIBS"]) ]) AS_IF( [test "x$ac_cv_libfdata" = xcheck], [dnl Check for headers AC_CHECK_HEADERS([libfdata.h]) AS_IF( [test "x$ac_cv_header_libfdata_h" = xno], [ac_cv_libfdata=no], [ac_cv_libfdata=yes AX_CHECK_LIB_FUNCTIONS( [libfdata], [fdata], [[libfdata_get_version], [libfdata_area_initialize], [libfdata_area_free], [libfdata_area_clone], [libfdata_area_empty], [libfdata_area_resize], [libfdata_area_get_number_of_segments], [libfdata_area_get_segment_by_index], [libfdata_area_set_segment_by_index], [libfdata_area_prepend_segment], [libfdata_area_append_segment], [libfdata_area_get_element_data_size], [libfdata_area_get_element_value_at_offset], [libfdata_area_set_element_value_at_offset], [libfdata_area_get_size], [libfdata_list_initialize], [libfdata_list_free], [libfdata_list_clone], [libfdata_list_empty], [libfdata_list_resize], [libfdata_list_reverse], [libfdata_list_get_number_of_elements], [libfdata_list_get_list_element_by_index], [libfdata_list_get_element_by_index], [libfdata_list_set_element_by_index], [libfdata_list_prepend_element], [libfdata_list_append_element], [libfdata_list_append_list], [libfdata_list_is_element_set], [libfdata_list_get_element_mapped_range], [libfdata_list_get_mapped_offset], [libfdata_list_set_mapped_offset], [libfdata_list_get_mapped_size_by_index], [libfdata_list_set_mapped_size_by_index], [libfdata_list_get_element_by_index_with_mapped_size], [libfdata_list_set_element_by_index_with_mapped_size], [libfdata_list_append_element_with_mapped_size], [libfdata_list_get_element_index_at_offset], [libfdata_list_get_list_element_at_offset], [libfdata_list_get_element_at_offset], [libfdata_list_cache_element_value], [libfdata_list_get_element_value_by_index], [libfdata_list_get_element_value_at_offset], [libfdata_list_set_element_value_by_index], [libfdata_list_set_element_value_at_offset], [libfdata_list_get_size], [libfdata_list_element_get_mapped_size], [libfdata_list_element_set_mapped_size], [libfdata_list_element_get_element_value], [libfdata_list_element_set_element_value], [libfdata_list_element_get_mapped_size], [libfdata_list_element_set_mapped_size], [libfdata_list_element_get_element_value], [libfdata_list_element_set_element_value], [libfdata_stream_initialize], [libfdata_stream_free], [libfdata_stream_clone], [libfdata_stream_empty], [libfdata_stream_resize], [libfdata_stream_reverse], [libfdata_stream_get_number_of_segments], [libfdata_stream_get_segment_by_index], [libfdata_stream_set_segment_by_index], [libfdata_stream_prepend_segment], [libfdata_stream_append_segment], [libfdata_stream_set_mapped_size], [libfdata_stream_get_segment_mapped_range], [libfdata_stream_get_segment_index_at_offset], [libfdata_stream_get_segment_at_offset], [libfdata_stream_read_buffer], [libfdata_stream_read_buffer_at_offset], [libfdata_stream_write_buffer], [libfdata_stream_seek_offset], [libfdata_stream_get_offset], [libfdata_stream_get_size], [libfdata_range_list_initialize], [libfdata_range_list_free], [libfdata_range_list_clone], [libfdata_range_list_empty], [libfdata_range_list_get_list_element_at_offset], [libfdata_range_list_get_element_at_offset], [libfdata_range_list_insert_element], [libfdata_range_list_get_element_value_at_offset], [libfdata_range_list_set_element_value_at_offset], [libfdata_vector_initialize], [libfdata_vector_free], [libfdata_vector_clone], [libfdata_vector_empty], [libfdata_vector_resize], [libfdata_vector_get_number_of_segments], [libfdata_vector_get_segment_by_index], [libfdata_vector_set_segment_by_index], [libfdata_vector_prepend_segment], [libfdata_vector_append_segment], [libfdata_vector_get_element_data_size], [libfdata_vector_get_number_of_elements], [libfdata_vector_get_element_index_at_offset], [libfdata_vector_get_element_value_by_index], [libfdata_vector_get_element_value_at_offset], [libfdata_vector_set_element_value_by_index], [libfdata_vector_get_size]]) ac_cv_libfdata_LIBADD="-lfdata"]) ]) AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE([libfdata]) ]) AS_IF( [test "x$ac_cv_libfdata" = xyes], [AC_DEFINE( [HAVE_LIBFDATA], [1], [Define to 1 if you have the `fdata' library (-lfdata).]) ]) AS_IF( [test "x$ac_cv_libfdata" = xyes], [AC_SUBST( [HAVE_LIBFDATA], [1]) ], [AC_SUBST( [HAVE_LIBFDATA], [0]) ]) ]) dnl Function to detect if libfdata dependencies are available AC_DEFUN([AX_LIBFDATA_CHECK_LOCAL], [dnl No additional checks. ac_cv_libfdata_CPPFLAGS="-I../libfdata -I\$(top_srcdir)/libfdata"; ac_cv_libfdata_LIBADD="../libfdata/libfdata.la"; ac_cv_libfdata=local ]) dnl Function to detect how to enable libfdata AC_DEFUN([AX_LIBFDATA_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [libfdata], [libfdata], [search for libfdata in includedir and libdir or in the specified DIR, or no if to use local version], [auto-detect], [DIR]) dnl Check for a shared library version AX_LIBFDATA_CHECK_LIB dnl Check if the dependencies for the local library version AS_IF( [test "x$ac_cv_libfdata" != xyes], [AX_LIBFDATA_CHECK_LOCAL AC_DEFINE( [HAVE_LOCAL_LIBFDATA], [1], [Define to 1 if the local version of libfdata is used.]) AC_SUBST( [HAVE_LOCAL_LIBFDATA], [1]) ]) AM_CONDITIONAL( [HAVE_LOCAL_LIBFDATA], [test "x$ac_cv_libfdata" = xlocal]) AS_IF( [test "x$ac_cv_libfdata_CPPFLAGS" != "x"], [AC_SUBST( [LIBFDATA_CPPFLAGS], [$ac_cv_libfdata_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libfdata_LIBADD" != "x"], [AC_SUBST( [LIBFDATA_LIBADD], [$ac_cv_libfdata_LIBADD]) ]) AS_IF( [test "x$ac_cv_libfdata" = xyes], [AC_SUBST( [ax_libfdata_pc_libs_private], [-lfdata]) ]) AS_IF( [test "x$ac_cv_libfdata" = xyes], [AC_SUBST( [ax_libfdata_spec_requires], [libfdata]) AC_SUBST( [ax_libfdata_spec_build_requires], [libfdata-devel]) ]) ]) ================================================ FILE: m4/libfdatetime.m4 ================================================ dnl Checks for libfdatetime required headers and functions dnl dnl Version: 20240518 dnl Function to detect if libfdatetime is available dnl ac_libfdatetime_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l arguments AC_DEFUN([AX_LIBFDATETIME_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_libfdatetime" = xno], [ac_cv_libfdatetime=no], [ac_cv_libfdatetime=check dnl Check if the directory provided as parameter exists dnl For both --with-libfdatetime which returns "yes" and --with-libfdatetime= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_libfdatetime" != x && test "x$ac_cv_with_libfdatetime" != xauto-detect && test "x$ac_cv_with_libfdatetime" != xyes], [AX_CHECK_LIB_DIRECTORY_EXISTS([libfdatetime])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [libfdatetime], [libfdatetime >= 20180910], [ac_cv_libfdatetime=yes], [ac_cv_libfdatetime=check]) ]) AS_IF( [test "x$ac_cv_libfdatetime" = xyes], [ac_cv_libfdatetime_CPPFLAGS="$pkg_cv_libfdatetime_CFLAGS" ac_cv_libfdatetime_LIBADD="$pkg_cv_libfdatetime_LIBS"]) ]) AS_IF( [test "x$ac_cv_libfdatetime" = xcheck], [dnl Check for headers AC_CHECK_HEADERS([libfdatetime.h]) AS_IF( [test "x$ac_cv_header_libfdatetime_h" = xno], [ac_cv_libfdatetime=no], [ac_cv_libfdatetime=yes AX_CHECK_LIB_FUNCTIONS( [libfdatetime], [fdatetime], [[libfdatetime_get_version], [libfdatetime_fat_date_time_initialize], [libfdatetime_fat_date_time_free], [libfdatetime_fat_date_time_copy_from_byte_stream], [libfdatetime_fat_date_time_copy_from_32bit], [libfdatetime_fat_date_time_copy_to_32bit], [libfdatetime_fat_date_time_copy_to_utf8_string], [libfdatetime_fat_date_time_copy_to_utf8_string_with_index], [libfdatetime_fat_date_time_copy_to_utf16_string], [libfdatetime_fat_date_time_copy_to_utf16_string_with_index], [libfdatetime_fat_date_time_copy_to_utf32_string], [libfdatetime_fat_date_time_copy_to_utf32_string_with_index], [libfdatetime_filetime_initialize], [libfdatetime_filetime_free], [libfdatetime_filetime_copy_from_byte_stream], [libfdatetime_filetime_copy_from_64bit], [libfdatetime_filetime_copy_to_64bit], [libfdatetime_filetime_copy_to_utf8_string], [libfdatetime_filetime_copy_to_utf8_string_with_index], [libfdatetime_filetime_copy_to_utf16_string], [libfdatetime_filetime_copy_to_utf16_string_with_index], [libfdatetime_filetime_copy_to_utf32_string], [libfdatetime_filetime_copy_to_utf32_string_with_index], [libfdatetime_filetime_add], [libfdatetime_floatingtime_initialize], [libfdatetime_floatingtime_free], [libfdatetime_floatingtime_copy_from_byte_stream], [libfdatetime_floatingtime_copy_from_64bit], [libfdatetime_floatingtime_copy_to_64bit], [libfdatetime_floatingtime_copy_to_utf8_string], [libfdatetime_floatingtime_copy_to_utf8_string_with_index], [libfdatetime_floatingtime_copy_to_utf16_string], [libfdatetime_floatingtime_copy_to_utf16_string_with_index], [libfdatetime_floatingtime_copy_to_utf32_string], [libfdatetime_floatingtime_copy_to_utf32_string_with_index], [libfdatetime_hfs_time_initialize], [libfdatetime_hfs_time_free], [libfdatetime_hfs_time_copy_from_byte_stream], [libfdatetime_hfs_time_copy_from_32bit], [libfdatetime_hfs_time_copy_to_32bit], [libfdatetime_hfs_time_copy_to_utf8_string], [libfdatetime_hfs_time_copy_to_utf8_string_with_index], [libfdatetime_hfs_time_copy_to_utf16_string], [libfdatetime_hfs_time_copy_to_utf16_string_with_index], [libfdatetime_hfs_time_copy_to_utf32_string], [libfdatetime_hfs_time_copy_to_utf32_string_with_index], [libfdatetime_nsf_timedate_initialize], [libfdatetime_nsf_timedate_free], [libfdatetime_nsf_timedate_copy_from_byte_stream], [libfdatetime_nsf_timedate_copy_from_64bit], [libfdatetime_nsf_timedate_copy_to_64bit], [libfdatetime_nsf_timedate_copy_to_utf8_string], [libfdatetime_nsf_timedate_copy_to_utf8_string_with_index], [libfdatetime_nsf_timedate_copy_to_utf16_string], [libfdatetime_nsf_timedate_copy_to_utf16_string_with_index], [libfdatetime_nsf_timedate_copy_to_utf32_string], [libfdatetime_nsf_timedate_copy_to_utf32_string_with_index], [libfdatetime_posix_time_initialize], [libfdatetime_posix_time_free], [libfdatetime_posix_time_copy_from_byte_stream], [libfdatetime_posix_time_copy_from_32bit], [libfdatetime_posix_time_copy_to_32bit], [libfdatetime_posix_time_copy_from_64bit], [libfdatetime_posix_time_copy_to_64bit], [libfdatetime_posix_time_copy_to_utf8_string], [libfdatetime_posix_time_copy_to_utf8_string_with_index], [libfdatetime_posix_time_copy_to_utf16_string], [libfdatetime_posix_time_copy_to_utf16_string_with_index], [libfdatetime_posix_time_copy_to_utf32_string], [libfdatetime_posix_time_copy_to_utf32_string_with_index], [libfdatetime_systemetime_initialize], [libfdatetime_systemetime_free], [libfdatetime_systemetime_copy_from_byte_stream], [libfdatetime_systemetime_copy_to_utf8_string], [libfdatetime_systemetime_copy_to_utf8_string_with_index], [libfdatetime_systemetime_copy_to_utf16_string], [libfdatetime_systemetime_copy_to_utf16_string_with_index], [libfdatetime_systemetime_copy_to_utf32_string], [libfdatetime_systemetime_copy_to_utf32_string_with_index]]) ac_cv_libfdatetime_LIBADD="-lfdatetime"]) ]) AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE([libfdatetime]) ]) AS_IF( [test "x$ac_cv_libfdatetime" = xyes], [AC_DEFINE( [HAVE_LIBFDATETIME], [1], [Define to 1 if you have the `fdatetime' library (-lfdatetime).]) ]) AS_IF( [test "x$ac_cv_libfdatetime" = xyes], [AC_SUBST( [HAVE_LIBFDATETIME], [1]) ], [AC_SUBST( [HAVE_LIBFDATETIME], [0]) ]) ]) dnl Function to detect if libfdatetime dependencies are available AC_DEFUN([AX_LIBFDATETIME_CHECK_LOCAL], [dnl No additional checks. ac_cv_libfdatetime_CPPFLAGS="-I../libfdatetime -I\$(top_srcdir)/libfdatetime"; ac_cv_libfdatetime_LIBADD="../libfdatetime/libfdatetime.la"; ac_cv_libfdatetime=local ]) dnl Function to detect how to enable libfdatetime AC_DEFUN([AX_LIBFDATETIME_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [libfdatetime], [libfdatetime], [search for libfdatetime in includedir and libdir or in the specified DIR, or no if to use local version], [auto-detect], [DIR]) AX_LIBFDATETIME_CHECK_LIB dnl Check if the dependencies for the local library version AS_IF( [test "x$ac_cv_libfdatetime" != xyes], [AX_LIBFDATETIME_CHECK_LOCAL AC_DEFINE( [HAVE_LOCAL_LIBFDATETIME], [1], [Define to 1 if the local version of libfdatetime is used.]) AC_SUBST( [HAVE_LOCAL_LIBFDATETIME], [1]) ]) AM_CONDITIONAL( [HAVE_LOCAL_LIBFDATETIME], [test "x$ac_cv_libfdatetime" = xlocal]) AS_IF( [test "x$ac_cv_libfdatetime_CPPFLAGS" != "x"], [AC_SUBST( [LIBFDATETIME_CPPFLAGS], [$ac_cv_libfdatetime_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libfdatetime_LIBADD" != "x"], [AC_SUBST( [LIBFDATETIME_LIBADD], [$ac_cv_libfdatetime_LIBADD]) ]) AS_IF( [test "x$ac_cv_libfdatetime" = xyes], [AC_SUBST( [ax_libfdatetime_pc_libs_private], [-lfdatetime]) ]) AS_IF( [test "x$ac_cv_libfdatetime" = xyes], [AC_SUBST( [ax_libfdatetime_spec_requires], [libfdatetime]) AC_SUBST( [ax_libfdatetime_spec_build_requires], [libfdatetime-devel]) ]) ]) ================================================ FILE: m4/libfguid.m4 ================================================ dnl Checks for libfguid required headers and functions dnl dnl Version: 20240519 dnl Function to detect if libfguid is available dnl ac_libfguid_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l arguments AC_DEFUN([AX_LIBFGUID_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_libfguid" = xno], [ac_cv_libfguid=no], [ac_cv_libfguid=check dnl Check if the directory provided as parameter exists dnl For both --with-libfguid which returns "yes" and --with-libfguid= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_libfguid" != x && test "x$ac_cv_with_libfguid" != xauto-detect && test "x$ac_cv_with_libfguid" != xyes], [AX_CHECK_LIB_DIRECTORY_EXISTS([libfguid])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [libfguid], [libfguid >= 20120426], [ac_cv_libfguid=yes], [ac_cv_libfguid=check]) ]) AS_IF( [test "x$ac_cv_libfguid" = xyes], [ac_cv_libfguid_CPPFLAGS="$pkg_cv_libfguid_CFLAGS" ac_cv_libfguid_LIBADD="$pkg_cv_libfguid_LIBS"]) ]) AS_IF( [test "x$ac_cv_libfguid" = xcheck], [dnl Check for headers AC_CHECK_HEADERS([libfguid.h]) AS_IF( [test "x$ac_cv_header_libfguid_h" = xno], [ac_cv_libfguid=no], [ac_cv_libfguid=yes AX_CHECK_LIB_FUNCTIONS( [libfguid], [fguid], [[libfguid_get_version], [libfguid_identifier_initialize], [libfguid_identifier_free], [libfguid_identifier_copy_from_byte_stream], [libfguid_identifier_get_string_size], [libfguid_identifier_copy_to_utf8_string], [libfguid_identifier_copy_to_utf8_string_with_index], [libfguid_identifier_copy_to_utf16_string], [libfguid_identifier_copy_to_utf16_string_with_index], [libfguid_identifier_copy_to_utf32_string], [libfguid_identifier_copy_to_utf32_string_with_index]]) ac_cv_libfguid_LIBADD="-lfguid"]) ]) AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE([libfguid]) ]) AS_IF( [test "x$ac_cv_libfguid" = xyes], [AC_DEFINE( [HAVE_LIBFGUID], [1], [Define to 1 if you have the `fguid' library (-lfguid).]) ]) AS_IF( [test "x$ac_cv_libfguid" = xyes], [AC_SUBST( [HAVE_LIBFGUID], [1]) ], [AC_SUBST( [HAVE_LIBFGUID], [0]) ]) ]) dnl Function to detect if libfguid dependencies are available AC_DEFUN([AX_LIBFGUID_CHECK_LOCAL], [dnl No additional checks. ac_cv_libfguid_CPPFLAGS="-I../libfguid -I\$(top_srcdir)/libfguid"; ac_cv_libfguid_LIBADD="../libfguid/libfguid.la"; ac_cv_libfguid=local ]) dnl Function to detect how to enable libfguid AC_DEFUN([AX_LIBFGUID_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [libfguid], [libfguid], [search for libfguid in includedir and libdir or in the specified DIR, or no if to use local version], [auto-detect], [DIR]) dnl Check for a shared library version AX_LIBFGUID_CHECK_LIB dnl Check if the dependencies for the local library version AS_IF( [test "x$ac_cv_libfguid" != xyes], [AX_LIBFGUID_CHECK_LOCAL AC_DEFINE( [HAVE_LOCAL_LIBFGUID], [1], [Define to 1 if the local version of libfguid is used.]) AC_SUBST( [HAVE_LOCAL_LIBFGUID], [1]) ]) AM_CONDITIONAL( [HAVE_LOCAL_LIBFGUID], [test "x$ac_cv_libfguid" = xlocal]) AS_IF( [test "x$ac_cv_libfguid_CPPFLAGS" != "x"], [AC_SUBST( [LIBFGUID_CPPFLAGS], [$ac_cv_libfguid_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libfguid_LIBADD" != "x"], [AC_SUBST( [LIBFGUID_LIBADD], [$ac_cv_libfguid_LIBADD]) ]) AS_IF( [test "x$ac_cv_libfguid" = xyes], [AC_SUBST( [ax_libfguid_pc_libs_private], [-lfguid]) ]) AS_IF( [test "x$ac_cv_libfguid" = xyes], [AC_SUBST( [ax_libfguid_spec_requires], [libfguid]) AC_SUBST( [ax_libfguid_spec_build_requires], [libfguid-devel]) ]) ]) ================================================ FILE: m4/libfuse.m4 ================================================ dnl Checks for libfuse required headers and functions dnl dnl Version: 20240413 dnl Function to detect if libfuse is available dnl ac_libfuse_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l arguments AC_DEFUN([AX_LIBFUSE_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_libfuse" = xno], [ac_cv_libfuse=no], [dnl Check if the directory provided as parameter exists dnl For both --with-libfuse which returns "yes" and --with-libfuse= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_libfuse" != x && test "x$ac_cv_with_libfuse" != xauto-detect && test "x$ac_cv_with_libfuse" != xyes], [AS_IF( [test -d "$ac_cv_with_libfuse"], [CFLAGS="$CFLAGS -I${ac_cv_with_libfuse}/include" LDFLAGS="$LDFLAGS -L${ac_cv_with_libfuse}/lib"], [AC_MSG_FAILURE( [no such directory: $ac_cv_with_libfuse], [1]) ])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [fuse3], [fuse3 >= 3.0], [ac_cv_libfuse=libfuse3], [ac_cv_libfuse=no]) AS_IF( [test "x$ac_cv_libfuse" = xno], [PKG_CHECK_MODULES( [fuse], [fuse >= 2.6], [ac_cv_libfuse=libfuse], [ac_cv_libfuse=no]) ]) AS_IF( [test "x$ac_cv_libfuse" = xlibfuse3], [ac_cv_libfuse_CPPFLAGS="$pkg_cv_fuse3_CFLAGS -D_FILE_OFFSET_BITS=64" ac_cv_libfuse_LIBADD="$pkg_cv_fuse3_LIBS"]) AS_IF( [test "x$ac_cv_libfuse" = xlibfuse], [ac_cv_libfuse_CPPFLAGS="$pkg_cv_fuse_CFLAGS -D_FILE_OFFSET_BITS=64" ac_cv_libfuse_LIBADD="$pkg_cv_fuse_LIBS"]) ]) ]) backup_CPPFLAGS="$CPPFLAGS" dnl Check for libfuse and libfuse3 AS_IF( [test "x$ac_cv_libfuse" != xlibfuse && test "x$ac_cv_libfuse" != xlibfuse3], [dnl Check for headers CPPFLAGS="$backup_CPPFLAGS -DFUSE_USE_VERSION=30" AC_CHECK_HEADERS([fuse.h]) AS_IF( [test "x$ac_cv_header_fuse_h" = xyes], [ac_cv_libfuse=libfuse3], [CPPFLAGS="$backup_CPPFLAGS -DFUSE_USE_VERSION=26" AC_CHECK_HEADERS([fuse.h]) AS_IF( [test "x$ac_cv_header_fuse_h" = xyes], [ac_cv_libfuse=libfuse]) ]) AS_IF( [test "x$ac_cv_header_fuse_h" = xno], [ac_cv_libfuse=no], [dnl Check for the individual functions AC_CHECK_LIB( fuse, fuse_invalidate, [ac_cv_libfuse=libfuse], [ac_cv_libfuse=libfuse3]) AC_CHECK_LIB( fuse, fuse_daemonize, [ac_cv_libfuse_dummy=yes], [ac_cv_libfuse=no]) AC_CHECK_LIB( fuse, fuse_destroy, [ac_cv_libfuse_dummy=yes], [ac_cv_libfuse=no]) AC_CHECK_LIB( fuse, fuse_mount, [ac_cv_libfuse_dummy=yes], [ac_cv_libfuse=no]) AC_CHECK_LIB( fuse, fuse_new, [ac_cv_libfuse_dummy=yes], [ac_cv_libfuse=no]) dnl libfuse and libfuse3 require -D_FILE_OFFSET_BITS=64 to be set ac_cv_libfuse_CPPFLAGS="-D_FILE_OFFSET_BITS=64" AS_IF( [test "x$ac_cv_libfuse" = xlibfuse3], [ac_cv_libfuse_LIBADD="-lfuse3"], [ac_cv_libfuse_LIBADD="-lfuse"]) ]) ]) dnl Check for libosxfuse AS_IF( [test "x$ac_cv_with_libfuse" != xno && test "x$ac_cv_header_fuse_h" = xno], [CPPFLAGS="$backup_CPPFLAGS -DFUSE_USE_VERSION=26" AC_CHECK_HEADERS([osxfuse/fuse.h]) AS_IF( [test "x$ac_cv_header_osxfuse_fuse_h" = xno], [ac_cv_libfuse=no], [dnl Check for the individual functions ac_cv_libfuse=libosxfuse AC_CHECK_LIB( osxfuse, fuse_daemonize, [ac_cv_libfuse_dummy=yes], [ac_cv_libfuse=no]) AC_CHECK_LIB( osxfuse, fuse_destroy, [ac_cv_libfuse_dummy=yes], [ac_cv_libfuse=no]) AC_CHECK_LIB( osxfuse, fuse_mount, [ac_cv_libfuse_dummy=yes], [ac_cv_libfuse=no]) AC_CHECK_LIB( osxfuse, fuse_new, [ac_cv_libfuse_dummy=yes], [ac_cv_libfuse=no]) dnl libosxfuse requires -D_FILE_OFFSET_BITS=64 to be set ac_cv_libfuse_CPPFLAGS="-D_FILE_OFFSET_BITS=64" ac_cv_libfuse_LIBADD="-losxfuse"; ]) ]) AS_IF( [test "x$ac_cv_libfuse" != xyes && test "x$ac_cv_with_libfuse" != x && test "x$ac_cv_with_libfuse" != xauto-detect && test "x$ac_cv_with_libfuse" != xyes], [AC_MSG_FAILURE( [unable to find supported libfuse in directory: $ac_cv_with_libfuse], [1]) ]) CPPFLAGS="$backup_CPPFLAGS" ]) AS_IF( [test "x$ac_cv_libfuse" = xlibfuse], [AC_DEFINE( [HAVE_LIBFUSE], [1], [Define to 1 if you have the 'fuse' library (-lfuse).]) ]) AS_IF( [test "x$ac_cv_libfuse" = xlibfuse3], [AC_DEFINE( [HAVE_LIBFUSE3], [1], [Define to 1 if you have the 'fuse3' library (-lfuse3).]) ]) AS_IF( [test "x$ac_cv_libfuse" = xlibosxfuse], [AC_DEFINE( [HAVE_LIBOSXFUSE], [1], [Define to 1 if you have the 'osxfuse' library (-losxfuse).]) ]) AS_IF( [test "x$ac_cv_libfuse" != xno], [AC_SUBST( [HAVE_LIBFUSE], [1]) ], [AC_SUBST( [HAVE_LIBFUSE], [0]) ]) ]) dnl Function to detect how to enable libfuse AC_DEFUN([AX_LIBFUSE_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [libfuse], [libfuse], [search for libfuse in includedir and libdir or in the specified DIR, or no if not to use libfuse], [auto-detect], [DIR]) dnl Check for a shared library version AX_LIBFUSE_CHECK_LIB AS_IF( [test "x$ac_cv_libfuse_CPPFLAGS" != "x"], [AC_SUBST( [LIBFUSE_CPPFLAGS], [$ac_cv_libfuse_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libfuse_LIBADD" != "x"], [AC_SUBST( [LIBFUSE_LIBADD], [$ac_cv_libfuse_LIBADD]) ]) AS_IF( [test "x$ac_cv_libfuse" = xlibfuse], [AC_SUBST( [ax_libfuse_pc_libs_private], [-lfuse]) ]) AS_IF( [test "x$ac_cv_libfuse" = xlibfuse3], [AC_SUBST( [ax_libfuse_pc_libs_private], [-lfuse3]) ]) AS_IF( [test "x$ac_cv_libfuse" = xlibosxfuse], [AC_SUBST( [ax_libfuse_pc_libs_private], [-losxfuse]) ]) AS_IF( [test "x$ac_cv_libfuse" = xlibfuse], [AC_SUBST( [ax_libfuse_spec_requires], [fuse-libs]) AC_SUBST( [ax_libfuse_spec_build_requires], [fuse-devel]) ]) AS_IF( [test "x$ac_cv_libfuse" = xlibfuse3], [AC_SUBST( [ax_libfuse_spec_requires], [fuse3-libs]) AC_SUBST( [ax_libfuse_spec_build_requires], [fuse3-devel]) ]) ]) ================================================ FILE: m4/libfusn.m4 ================================================ dnl Checks for libfusn required headers and functions dnl dnl Version: 20240521 dnl Function to detect if libfusn is available dnl ac_libfusn_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l arguments AC_DEFUN([AX_LIBFUSN_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_libfusn" = xno], [ac_cv_libfusn=no], [ac_cv_libfusn=check dnl Check if the directory provided as parameter exists dnl For both --with-libfusn which returns "yes" and --with-libfusn= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_libfusn" != x && test "x$ac_cv_with_libfusn" != xauto-detect && test "x$ac_cv_with_libfusn" != xyes], [AX_CHECK_LIB_DIRECTORY_EXISTS([libfusn])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [libfusn], [libfusn >= 20180611], [ac_cv_libfusn=yes], [ac_cv_libfusn=check]) ]) AS_IF( [test "x$ac_cv_libfusn" = xyes], [ac_cv_libfusn_CPPFLAGS="$pkg_cv_libfusn_CFLAGS" ac_cv_libfusn_LIBADD="$pkg_cv_libfusn_LIBS"]) ]) AS_IF( [test "x$ac_cv_libfusn" = xcheck], [dnl Check for headers AC_CHECK_HEADERS([libfusn.h]) AS_IF( [test "x$ac_cv_header_libfusn_h" = xno], [ac_cv_libfusn=no], [ac_cv_libfusn=yes AX_CHECK_LIB_FUNCTIONS( [libfusn], [fusn], [[libfusn_get_version], [libfusn_record_initialize], [libfusn_record_free], [libfusn_record_copy_from_byte_stream], [libfusn_record_get_size], [libfusn_record_get_update_time], [libfusn_record_get_file_reference], [libfusn_record_get_parent_file_reference], [libfusn_record_get_update_sequence_number], [libfusn_record_get_update_reason_flags], [libfusn_record_get_update_source_flags], [libfusn_record_get_file_attribute_flags], [libfusn_record_get_utf8_name_size], [libfusn_record_get_utf8_name], [libfusn_record_get_utf16_name_size], [libfusn_record_get_utf16_name]]) ac_cv_libfusn_LIBADD="-lfusn"]) ]) AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE([libfusn]) ]) AS_IF( [test "x$ac_cv_libfusn" = xyes], [AC_DEFINE( [HAVE_LIBFUSN], [1], [Define to 1 if you have the `fusn' library (-lfusn).]) ]) AS_IF( [test "x$ac_cv_libfusn" = xyes], [AC_SUBST( [HAVE_LIBFUSN], [1]) ], [AC_SUBST( [HAVE_LIBFUSN], [0]) ]) ]) dnl Function to detect if libfusn dependencies are available AC_DEFUN([AX_LIBFUSN_CHECK_LOCAL], [dnl No additional checks. ac_cv_libfusn_CPPFLAGS="-I../libfusn -I\$(top_srcdir)/libfusn"; ac_cv_libfusn_LIBADD="../libfusn/libfusn.la"; ac_cv_libfusn=local ]) dnl Function to detect how to enable libfusn AC_DEFUN([AX_LIBFUSN_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [libfusn], [libfusn], [search for libfusn in includedir and libdir or in the specified DIR, or no if to use local version], [auto-detect], [DIR]) dnl Check for a shared library version AX_LIBFUSN_CHECK_LIB dnl Check if the dependencies for the local library version AS_IF( [test "x$ac_cv_libfusn" != xyes], [AX_LIBFUSN_CHECK_LOCAL AC_DEFINE( [HAVE_LOCAL_LIBFUSN], [1], [Define to 1 if the local version of libfusn is used.]) AC_SUBST( [HAVE_LOCAL_LIBFUSN], [1]) ]) AM_CONDITIONAL( [HAVE_LOCAL_LIBFUSN], [test "x$ac_cv_libfusn" = xlocal]) AS_IF( [test "x$ac_cv_libfusn_CPPFLAGS" != "x"], [AC_SUBST( [LIBFUSN_CPPFLAGS], [$ac_cv_libfusn_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libfusn_LIBADD" != "x"], [AC_SUBST( [LIBFUSN_LIBADD], [$ac_cv_libfusn_LIBADD]) ]) AS_IF( [test "x$ac_cv_libfusn" = xyes], [AC_SUBST( [ax_libfusn_pc_libs_private], [-lfusn]) ]) AS_IF( [test "x$ac_cv_libfusn" = xyes], [AC_SUBST( [ax_libfusn_spec_requires], [libfusn]) AC_SUBST( [ax_libfusn_spec_build_requires], [libfusn-devel]) ]) ]) ================================================ FILE: m4/libfwnt.m4 ================================================ dnl Checks for libfwnt required headers and functions dnl dnl Version: 20240519 dnl Function to detect if libfwnt is available dnl ac_libfwnt_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l arguments AC_DEFUN([AX_LIBFWNT_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_libfwnt" = xno], [ac_cv_libfwnt=no], [ac_cv_libfwnt=check dnl Check if the directory provided as parameter exists dnl For both --with-libfwnt which returns "yes" and --with-libfwnt= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_libfwnt" != x && test "x$ac_cv_with_libfwnt" != xauto-detect && test "x$ac_cv_with_libfwnt" != xyes], [AX_CHECK_LIB_DIRECTORY_EXISTS([libfwnt])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [libfwnt], [libfwnt >= 20191217], [ac_cv_libfwnt=yes], [ac_cv_libfwnt=check]) ]) AS_IF( [test "x$ac_cv_libfwnt" = xyes], [ac_cv_libfwnt_CPPFLAGS="$pkg_cv_libfwnt_CFLAGS" ac_cv_libfwnt_LIBADD="$pkg_cv_libfwnt_LIBS"]) ]) AS_IF( [test "x$ac_cv_libfwnt" = xcheck], [dnl Check for headers AC_CHECK_HEADERS([libfwnt.h]) AS_IF( [test "x$ac_cv_header_libfwnt_h" = xno], [ac_cv_libfwnt=no], [ac_cv_libfwnt=yes AX_CHECK_LIB_FUNCTIONS( [libfwnt], [fwnt], [[libfwnt_get_version], [libfwnt_array_initialize], [libfwnt_security_descriptor_initialize], [libfwnt_security_descriptor_free], [libfwnt_security_descriptor_copy_from_byte_stream], [libfwnt_security_descriptor_get_owner], [libfwnt_security_descriptor_get_group], [libfwnt_security_descriptor_get_discretionary_acl], [libfwnt_security_descriptor_get_system_acl], [libfwnt_security_identifier_initialize], [libfwnt_security_identifier_free], [libfwnt_security_identifier_copy_from_byte_stream], [libfwnt_security_identifier_get_string_size], [libfwnt_security_identifier_copy_to_utf8_string], [libfwnt_security_identifier_copy_to_utf8_string_with_index], [libfwnt_security_identifier_copy_to_utf16_string], [libfwnt_security_identifier_copy_to_utf16_string_with_index], [libfwnt_security_identifier_copy_to_utf32_string], [libfwnt_security_identifier_copy_to_utf32_string_with_index], [libfwnt_access_control_list_free], [libfwnt_access_control_list_get_number_of_entries], [libfwnt_access_control_list_get_entry_by_index], [libfwnt_access_control_entry_free], [libfwnt_access_control_entry_get_type], [libfwnt_access_control_entry_get_flags], [libfwnt_access_control_entry_get_access_mask], [libfwnt_access_control_entry_get_security_identifier], [libfwnt_lznt1_decompress], [libfwnt_lzx_decompress], [libfwnt_lzxpress_decompress], [libfwnt_lzxpress_huffman_decompress]]) ac_cv_libfwnt_LIBADD="-lfwnt"]) ]) AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE([libfwnt]) ]) AS_IF( [test "x$ac_cv_libfwnt" = xyes], [AC_DEFINE( [HAVE_LIBFWNT], [1], [Define to 1 if you have the `fwnt' library (-lfwnt).]) ]) AS_IF( [test "x$ac_cv_libfwnt" = xyes], [AC_SUBST( [HAVE_LIBFWNT], [1]) ], [AC_SUBST( [HAVE_LIBFWNT], [0]) ]) ]) dnl Function to detect if libfwnt dependencies are available AC_DEFUN([AX_LIBFWNT_CHECK_LOCAL], [dnl No additional checks. ac_cv_libfwnt_CPPFLAGS="-I../libfwnt -I\$(top_srcdir)/libfwnt"; ac_cv_libfwnt_LIBADD="../libfwnt/libfwnt.la"; ac_cv_libfwnt=local ]) dnl Function to detect how to enable libfwnt AC_DEFUN([AX_LIBFWNT_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [libfwnt], [libfwnt], [search for libfwnt in includedir and libdir or in the specified DIR, or no if to use local version], [auto-detect], [DIR]) dnl Check for a shared library version AX_LIBFWNT_CHECK_LIB dnl Check if the dependencies for the local library version AS_IF( [test "x$ac_cv_libfwnt" != xyes], [AX_LIBFWNT_CHECK_LOCAL AC_DEFINE( [HAVE_LOCAL_LIBFWNT], [1], [Define to 1 if the local version of libfwnt is used.]) AC_SUBST( [HAVE_LOCAL_LIBFWNT], [1]) ]) AM_CONDITIONAL( [HAVE_LOCAL_LIBFWNT], [test "x$ac_cv_libfwnt" = xlocal]) AS_IF( [test "x$ac_cv_libfwnt_CPPFLAGS" != "x"], [AC_SUBST( [LIBFWNT_CPPFLAGS], [$ac_cv_libfwnt_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libfwnt_LIBADD" != "x"], [AC_SUBST( [LIBFWNT_LIBADD], [$ac_cv_libfwnt_LIBADD]) ]) AS_IF( [test "x$ac_cv_libfwnt" = xyes], [AC_SUBST( [ax_libfwnt_pc_libs_private], [-lfwnt]) ]) AS_IF( [test "x$ac_cv_libfwnt" = xyes], [AC_SUBST( [ax_libfwnt_spec_requires], [libfwnt]) AC_SUBST( [ax_libfwnt_spec_build_requires], [libfwnt-devel]) ]) ]) ================================================ FILE: m4/libhmac.m4 ================================================ dnl Checks for libhmac required headers and functions dnl dnl Version: 20240520 dnl Function to detect if libhmac is available dnl ac_libhmac_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l arguments AC_DEFUN([AX_LIBHMAC_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_libhmac" = xno], [ac_cv_libhmac=no], [ac_cv_libhmac=check dnl Check if the directory provided as parameter exists dnl For both --with-libhmac which returns "yes" and --with-libhmac= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_libhmac" != x && test "x$ac_cv_with_libhmac" != xauto-detect && test "x$ac_cv_with_libhmac" != xyes], [AX_CHECK_LIB_DIRECTORY_EXISTS([libhmac])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [libhmac], [libhmac >= 20200104], [ac_cv_libhmac=yes], [ac_cv_libhmac=check]) ]) AS_IF( [test "x$ac_cv_libhmac" = xyes], [ac_cv_libhmac_CPPFLAGS="$pkg_cv_libhmac_CFLAGS" ac_cv_libhmac_LIBADD="$pkg_cv_libhmac_LIBS"]) ]) AS_IF( [test "x$ac_cv_libhmac" = xcheck], [dnl Check for headers AC_CHECK_HEADERS([libhmac.h]) AS_IF( [test "x$ac_cv_header_libhmac_h" = xno], [ac_cv_libhmac=no], [ac_cv_libhmac=yes AX_CHECK_LIB_FUNCTIONS( [libhmac], [hmac], [[libhmac_get_version], [libhmac_md5_initialize], [libhmac_md5_update], [libhmac_md5_finalize], [libhmac_md5_free], [libhmac_sha1_initialize], [libhmac_sha1_update], [libhmac_sha1_finalize], [libhmac_sha1_free], [libhmac_sha224_initialize], [libhmac_sha224_update], [libhmac_sha224_finalize], [libhmac_sha224_free], [libhmac_sha256_initialize], [libhmac_sha256_update], [libhmac_sha256_finalize], [libhmac_sha256_free], [libhmac_sha512_initialize], [libhmac_sha512_update], [libhmac_sha512_finalize], [libhmac_sha512_free]]) ac_cv_libhmac_LIBADD="-lhmac"]) ]) AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE([libhmac]) ]) AS_IF( [test "x$ac_cv_libhmac" = xyes], [AC_DEFINE( [HAVE_LIBHMAC], [1], [Define to 1 if you have the `hmac' library (-lhmac).]) ]) AS_IF( [test "x$ac_cv_libhmac" = xyes], [ac_cv_libhmac_md5=libhmac ac_cv_libhmac_sha1=libhmac ac_cv_libhmac_sha224=libhmac ac_cv_libhmac_sha256=libhmac ac_cv_libhmac_sha512=libhmac], [ac_cv_libhmac_md5=no ac_cv_libhmac_sha1=no ac_cv_libhmac_sha224=no ac_cv_libhmac_sha256=no ac_cv_libhmac_sha512=no]) AS_IF( [test "x$ac_cv_libhmac" = xyes], [AC_SUBST( [HAVE_LIBHMAC], [1]) ], [AC_SUBST( [HAVE_LIBHMAC], [0]) ]) ]) dnl Function to detect if libhmac dependencies are available AC_DEFUN([AX_LIBHMAC_CHECK_LOCAL], [dnl Check for libcrypto (openssl) support AX_LIBCRYPTO_CHECK_ENABLE AS_IF( [test "x$ac_cv_libcrypto" != xno], [AX_LIBCRYPTO_CHECK_MD5 AX_LIBCRYPTO_CHECK_SHA1 AX_LIBCRYPTO_CHECK_SHA224 AX_LIBCRYPTO_CHECK_SHA256 AX_LIBCRYPTO_CHECK_SHA512]) dnl Fallback to local versions if necessary AS_IF( [test "x$ac_cv_libcrypto" = xno || test "x$ac_cv_libcrypto_md5" = xno], [ac_cv_libhmac_md5=local], [ac_cv_libhmac_md5=$ac_cv_libcrypto_md5]) AS_IF( [test "x$ac_cv_libcrypto" = xno || test "x$ac_cv_libcrypto_sha1" = xno], [ac_cv_libhmac_sha1=local], [ac_cv_libhmac_sha1=$ac_cv_libcrypto_sha1]) AS_IF( [test "x$ac_cv_libcrypto" = xno || test "x$ac_cv_libcrypto_sha224" = xno], [ac_cv_libhmac_sha224=local], [ac_cv_libhmac_sha224=$ac_cv_libcrypto_sha224]) AS_IF( [test "x$ac_cv_libcrypto" = xno || test "x$ac_cv_libcrypto_sha256" = xno], [ac_cv_libhmac_sha256=local], [ac_cv_libhmac_sha256=$ac_cv_libcrypto_sha256]) AS_IF( [test "x$ac_cv_libcrypto" = xno || test "x$ac_cv_libcrypto_sha512" = xno], [ac_cv_libhmac_sha512=local], [ac_cv_libhmac_sha512=$ac_cv_libcrypto_sha512]) ac_cv_libhmac_CPPFLAGS="-I../libhmac -I\$(top_srcdir)/libhmac"; ac_cv_libhmac_LIBADD="../libhmac/libhmac.la"; ac_cv_libhmac=local ]) dnl Function to detect how to enable libhmac AC_DEFUN([AX_LIBHMAC_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [libhmac], [libhmac], [search for libhmac in includedir and libdir or in the specified DIR, or no if to use local version], [auto-detect], [DIR]) dnl Check for a shared library version AX_LIBHMAC_CHECK_LIB dnl Check if the dependencies for the local library version AS_IF( [test "x$ac_cv_libhmac" != xyes], [AX_LIBHMAC_CHECK_LOCAL AC_DEFINE( [HAVE_LOCAL_LIBHMAC], [1], [Define to 1 if the local version of libhmac is used.]) AC_SUBST( [HAVE_LOCAL_LIBHMAC], [1]) ]) AM_CONDITIONAL( [HAVE_LOCAL_LIBHMAC], [test "x$ac_cv_libhmac" = xlocal]) AS_IF( [test "x$ac_cv_libhmac_CPPFLAGS" != "x"], [AC_SUBST( [LIBHMAC_CPPFLAGS], [$ac_cv_libhmac_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libhmac_LIBADD" != "x"], [AC_SUBST( [LIBHMAC_LIBADD], [$ac_cv_libhmac_LIBADD]) ]) AS_IF( [test "x$ac_cv_libhmac" = xyes], [AC_SUBST( [ax_libhmac_pc_libs_private], [-lhmac]) ]) AS_IF( [test "x$ac_cv_libhmac" = xyes], [AC_SUBST( [ax_libhmac_spec_requires], [libhmac]) AC_SUBST( [ax_libhmac_spec_build_requires], [libhmac-devel]) ]) ]) ================================================ FILE: m4/libuna.m4 ================================================ dnl Checks for libuna or required headers and functions dnl dnl Version: 20240513 dnl Function to detect if libuna is available dnl ac_libuna_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l arguments AC_DEFUN([AX_LIBUNA_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_libuna" = xno], [ac_cv_libuna=no], [ac_cv_libuna=check dnl Check if the directory provided as parameter exists dnl For both --with-libuna which returns "yes" and --with-libuna= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_libuna" != x && test "x$ac_cv_with_libuna" != xauto-detect && test "x$ac_cv_with_libuna" != xyes], [AX_CHECK_LIB_DIRECTORY_EXISTS([libuna])], [dnl Check for a pkg-config file AS_IF( [test "x$cross_compiling" != "xyes" && test "x$PKGCONFIG" != "x"], [PKG_CHECK_MODULES( [libuna], [libuna >= 20230702], [ac_cv_libuna=yes], [ac_cv_libuna=check]) ]) AS_IF( [test "x$ac_cv_libuna" = xyes], [ac_cv_libuna_CPPFLAGS="$pkg_cv_libuna_CFLAGS" ac_cv_libuna_LIBADD="$pkg_cv_libuna_LIBS"]) ]) AS_IF( [test "x$ac_cv_libuna" = xcheck], [dnl Check for headers AC_CHECK_HEADERS([libuna.h]) AS_IF( [test "x$ac_cv_header_libuna_h" = xno], [ac_cv_libuna=no], [ac_cv_libuna=yes AX_CHECK_LIB_FUNCTIONS( [libuna], [una], [[libuna_get_version], [libuna_base16_stream_size_to_byte_stream], [libuna_base16_stream_copy_to_byte_stream], [libuna_base16_stream_size_from_byte_stream], [libuna_base16_stream_copy_from_byte_stream], [libuna_base16_stream_with_index_copy_from_byte_stream], [libuna_base32_quintuplet_copy_from_base32_stream], [libuna_base32_quintuplet_copy_to_base32_stream], [libuna_base32_quintuplet_copy_from_byte_stream], [libuna_base32_quintuplet_copy_to_byte_stream], [libuna_base32_stream_size_to_byte_stream], [libuna_base32_stream_copy_to_byte_stream], [libuna_base32_stream_size_from_byte_stream], [libuna_base32_stream_copy_from_byte_stream], [libuna_base32_stream_with_index_copy_from_byte_stream], [libuna_base64_triplet_copy_from_base64_stream], [libuna_base64_triplet_copy_to_base64_stream], [libuna_base64_triplet_copy_from_byte_stream], [libuna_base64_triplet_copy_to_byte_stream], [libuna_base64_stream_size_to_byte_stream], [libuna_base64_stream_copy_to_byte_stream], [libuna_base64_stream_size_from_byte_stream], [libuna_base64_stream_copy_from_byte_stream], [libuna_base64_stream_with_index_copy_from_byte_stream], [libuna_byte_stream_size_from_utf8], [libuna_byte_stream_copy_from_utf8], [libuna_byte_stream_size_from_utf16], [libuna_byte_stream_copy_from_utf16], [libuna_byte_stream_size_from_utf32], [libuna_byte_stream_copy_from_utf32], [libuna_unicode_character_size_to_byte_stream], [libuna_unicode_character_copy_from_byte_stream], [libuna_unicode_character_copy_to_byte_stream], [libuna_unicode_character_size_to_ucs2], [libuna_unicode_character_copy_from_ucs2], [libuna_unicode_character_copy_to_ucs2], [libuna_unicode_character_size_to_ucs4], [libuna_unicode_character_copy_from_ucs4], [libuna_unicode_character_copy_to_ucs4], [libuna_unicode_character_copy_from_utf7_stream], [libuna_unicode_character_copy_to_utf7_stream], [libuna_unicode_character_size_to_utf8], [libuna_unicode_character_copy_from_utf8], [libuna_unicode_character_copy_to_utf8], [libuna_unicode_character_size_to_utf8_rfc2279], [libuna_unicode_character_copy_from_utf8_rfc2279], [libuna_unicode_character_copy_to_utf8_rfc2279], [libuna_unicode_character_size_to_utf16], [libuna_unicode_character_copy_from_utf16], [libuna_unicode_character_copy_to_utf16], [libuna_unicode_character_copy_from_utf16_stream], [libuna_unicode_character_copy_to_utf16_stream], [libuna_unicode_character_copy_from_utf32], [libuna_unicode_character_copy_to_utf32], [libuna_unicode_character_copy_from_utf32_stream], [libuna_unicode_character_copy_to_utf32_stream], [libuna_utf8_stream_size_from_utf8], [libuna_utf8_stream_copy_from_utf8], [libuna_utf8_stream_size_from_utf16], [libuna_utf8_stream_copy_from_utf16], [libuna_utf8_stream_size_from_utf32], [libuna_utf8_stream_copy_from_utf32], [libuna_utf16_stream_size_from_utf8], [libuna_utf16_stream_copy_from_utf8], [libuna_utf16_stream_size_from_utf16], [libuna_utf16_stream_copy_from_utf16], [libuna_utf16_stream_size_from_utf32], [libuna_utf16_stream_copy_from_utf32], [libuna_utf32_stream_size_from_utf8], [libuna_utf32_stream_copy_from_utf8], [libuna_utf32_stream_size_from_utf16], [libuna_utf32_stream_copy_from_utf16], [libuna_utf32_stream_size_from_utf32], [libuna_utf32_stream_copy_from_utf32], [libuna_utf8_string_size_from_byte_stream], [libuna_utf8_string_copy_from_byte_stream], [libuna_utf8_string_with_index_copy_from_byte_stream], [libuna_utf8_string_compare_with_byte_stream], [libuna_utf8_string_size_from_utf7_stream], [libuna_utf8_string_copy_from_utf7_stream], [libuna_utf8_string_with_index_copy_from_utf7_stream], [libuna_utf8_string_compare_with_utf7_stream], [libuna_utf8_string_size_from_utf8_stream], [libuna_utf8_string_copy_from_utf8_stream], [libuna_utf8_string_with_index_copy_from_utf8_stream], [libuna_utf8_string_compare_with_utf8_stream], [libuna_utf8_string_size_from_utf16], [libuna_utf8_string_copy_from_utf16], [libuna_utf8_string_with_index_copy_from_utf16], [libuna_utf8_string_compare_with_utf16], [libuna_utf8_string_size_from_utf16_stream], [libuna_utf8_string_copy_from_utf16_stream], [libuna_utf8_string_with_index_copy_from_utf16_stream], [libuna_utf8_string_compare_with_utf16_stream], [libuna_utf8_string_size_from_utf32], [libuna_utf8_string_copy_from_utf32], [libuna_utf8_string_with_index_copy_from_utf32], [libuna_utf8_string_compare_with_utf32], [libuna_utf8_string_size_from_utf32_stream], [libuna_utf8_string_copy_from_utf32_stream], [libuna_utf8_string_with_index_copy_from_utf32_stream], [libuna_utf8_string_compare_with_utf32_stream], [libuna_utf8_string_size_from_scsu_stream], [libuna_utf8_string_copy_from_scsu_stream], [libuna_utf8_string_with_index_copy_from_scsu_stream], [libuna_utf16_string_size_from_byte_stream], [libuna_utf16_string_copy_from_byte_stream], [libuna_utf16_string_with_index_copy_from_byte_stream], [libuna_utf16_string_compare_with_byte_stream], [libuna_utf16_string_size_from_utf7_stream], [libuna_utf16_string_copy_from_utf7_stream], [libuna_utf16_string_with_index_copy_from_utf7_stream], [libuna_utf16_string_compare_with_utf7_stream], [libuna_utf16_string_size_from_utf8], [libuna_utf16_string_copy_from_utf8], [libuna_utf16_string_with_index_copy_from_utf8], [libuna_utf16_string_size_from_utf8_stream], [libuna_utf16_string_copy_from_utf8_stream], [libuna_utf16_string_with_index_copy_from_utf8_stream], [libuna_utf16_string_compare_with_utf8_stream], [libuna_utf16_string_size_from_utf16_stream], [libuna_utf16_string_copy_from_utf16_stream], [libuna_utf16_string_with_index_copy_from_utf16_stream], [libuna_utf16_string_compare_with_utf16_stream], [libuna_utf16_string_size_from_utf32], [libuna_utf16_string_copy_from_utf32], [libuna_utf16_string_with_index_copy_from_utf32], [libuna_utf16_string_compare_with_utf32], [libuna_utf16_string_size_from_utf32_stream], [libuna_utf16_string_copy_from_utf32_stream], [libuna_utf16_string_with_index_copy_from_utf32_stream], [libuna_utf16_string_compare_with_utf32_stream], [libuna_utf16_string_size_from_scsu_stream], [libuna_utf16_string_copy_from_scsu_stream], [libuna_utf16_string_with_index_copy_from_scsu_stream], [libuna_utf32_string_size_from_byte_stream], [libuna_utf32_string_copy_from_byte_stream], [libuna_utf32_string_with_index_copy_from_byte_stream], [libuna_utf32_string_compare_with_byte_stream], [libuna_utf32_string_size_from_utf7_stream], [libuna_utf32_string_copy_from_utf7_stream], [libuna_utf32_string_with_index_copy_from_utf7_stream], [libuna_utf32_string_compare_with_utf7_stream], [libuna_utf32_string_size_from_utf8_stream], [libuna_utf32_string_size_from_utf8], [libuna_utf32_string_copy_from_utf8], [libuna_utf32_string_copy_from_utf8_stream], [libuna_utf32_string_with_index_copy_from_utf8_stream], [libuna_utf32_string_compare_with_utf8_stream], [libuna_utf32_string_size_from_utf16], [libuna_utf32_string_copy_from_utf16], [libuna_utf32_string_with_index_copy_from_utf16], [libuna_utf32_string_size_from_utf16_stream], [libuna_utf32_string_copy_from_utf16_stream], [libuna_utf32_string_with_index_copy_from_utf16_stream], [libuna_utf32_string_compare_with_utf16_stream], [libuna_utf32_string_size_from_utf32_stream], [libuna_utf32_string_copy_from_utf32_stream], [libuna_utf32_string_with_index_copy_from_utf32_stream], [libuna_utf32_string_compare_with_utf32_stream], [libuna_utf32_string_size_from_scsu_stream], [libuna_utf32_string_copy_from_scsu_stream], [libuna_utf32_string_with_index_copy_from_scsu_stream]]) AX_CHECK_LIB_DEFINITIONS( [libuna], [[LIBUNA_COMPARE_LESS], [LIBUNA_COMPARE_EQUAL], [LIBUNA_COMPARE_GREATER], [LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE]]) ac_cv_libuna_LIBADD="-luna"]) ]) AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE([libuna]) ]) AS_IF( [test "x$ac_cv_libuna" = xyes], [AC_DEFINE( [HAVE_LIBUNA], [1], [Define to 1 if you have the `una' library (-luna).]) ]) AS_IF( [test "x$ac_cv_libuna" = xyes], [AC_SUBST( [HAVE_LIBUNA], [1]) ], [AC_SUBST( [HAVE_LIBUNA], [0]) ]) ]) dnl Function to detect if libuna dependencies are available AC_DEFUN([AX_LIBUNA_CHECK_LOCAL], [dnl No additional checks. ac_cv_libuna_CPPFLAGS="-I../libuna -I\$(top_srcdir)/libuna"; ac_cv_libuna_LIBADD="../libuna/libuna.la"; ac_cv_libuna=local ]) dnl Function to detect how to enable libuna AC_DEFUN([AX_LIBUNA_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [libuna], [libuna], [search for libuna in includedir and libdir or in the specified DIR, or no if to use local version], [auto-detect], [DIR]) dnl Check for a shared library version AX_LIBUNA_CHECK_LIB dnl Check if the dependencies for the local library version AS_IF( [test "x$ac_cv_libuna" != xyes], [AX_LIBUNA_CHECK_LOCAL AC_DEFINE( [HAVE_LOCAL_LIBUNA], [1], [Define to 1 if the local version of libuna is used.]) AC_SUBST( [HAVE_LOCAL_LIBUNA], [1]) ]) AM_CONDITIONAL( [HAVE_LOCAL_LIBUNA], [test "x$ac_cv_libuna" = xlocal]) AS_IF( [test "x$ac_cv_libuna_CPPFLAGS" != "x"], [AC_SUBST( [LIBUNA_CPPFLAGS], [$ac_cv_libuna_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_libuna_LIBADD" != "x"], [AC_SUBST( [LIBUNA_LIBADD], [$ac_cv_libuna_LIBADD]) ]) AS_IF( [test "x$ac_cv_libuna" = xyes], [AC_SUBST( [ax_libuna_pc_libs_private], [-luna]) ]) AS_IF( [test "x$ac_cv_libuna" = xyes], [AC_SUBST( [ax_libuna_spec_requires], [libuna]) AC_SUBST( [ax_libuna_spec_build_requires], [libuna-devel]) ]) ]) ================================================ FILE: m4/pthread.m4 ================================================ dnl Functions for pthread dnl dnl Version: 20240513 dnl Function to detect if pthread is available AC_DEFUN([AX_PTHREAD_CHECK_LIB], [AS_IF( [test "x$ac_cv_enable_shared_libs" = xno || test "x$ac_cv_with_pthread" = xno], [ac_cv_pthread=no], [ac_cv_pthread=check dnl Check if parameters were provided dnl For both --with-pthread which returns "yes" and --with-pthread= which returns "" dnl treat them as auto-detection. AS_IF( [test "x$ac_cv_with_pthread" != x && test "x$ac_cv_with_pthread" != xauto-detect && test "x$ac_cv_with_pthread" != xyes], [AX_CHECK_LIB_DIRECTORY_EXISTS([pthread])]) ]) AS_IF( [test "x$ac_cv_pthread" = xcheck], [dnl Check for headers AC_CHECK_HEADERS([pthread.h]) AS_IF( [test "x$ac_cv_header_pthread_h" = xno], [ac_cv_pthread=no], [ac_cv_pthread=yes AX_CHECK_LIB_FUNCTIONS( [pthread], [pthread], [[pthread_create], [pthread_exit], [pthread_join], [pthread_cond_init], [pthread_cond_destroy], [pthread_cond_broadcast], [pthread_cond_signal], [pthread_cond_wait], [pthread_mutex_init], [pthread_mutex_destroy], [pthread_mutex_lock], [pthread_mutex_trylock], [pthread_mutex_unlock], [pthread_rwlock_init], [pthread_rwlock_destroy], [pthread_rwlock_rdlock], [pthread_rwlock_wrlock], [pthread_rwlock_unlock]]) ac_cv_pthread_LIBADD="-lpthread" ]) AX_CHECK_LIB_DIRECTORY_MSG_ON_FAILURE([pthread]) ]) AS_IF( [test "x$ac_cv_pthread" = xpthread], [AC_DEFINE( [HAVE_PTHREAD], [1], [Define to 1 if you have the 'pthread' library (-lpthread).]) ]) AS_IF( [test "x$ac_cv_pthread" != xno], [AC_SUBST( [HAVE_PTHREAD], [1]) ], [AC_SUBST( [HAVE_PTHREAD], [0]) ]) ]) dnl Function to detect how to enable pthread AC_DEFUN([AX_PTHREAD_CHECK_ENABLE], [AX_COMMON_ARG_WITH( [pthread], [pthread], [search for pthread in includedir and libdir or in the specified DIR, or no if not to use pthread], [auto-detect], [DIR]) dnl Check for a shared library version AX_PTHREAD_CHECK_LIB AS_IF( [test "x$ac_cv_pthread_CPPFLAGS" != "x"], [AC_SUBST( [PTHREAD_CPPFLAGS], [$ac_cv_pthread_CPPFLAGS]) ]) AS_IF( [test "x$ac_cv_pthread_LIBADD" != "x"], [AC_SUBST( [PTHREAD_LIBADD], [$ac_cv_pthread_LIBADD]) ]) AS_IF( [test "x$ac_cv_pthread" = xpthread], [AC_SUBST( [ax_pthread_pc_libs_private], [-lpthread]) ]) ]) ================================================ FILE: m4/python.m4 ================================================ dnl Functions for Python bindings dnl dnl Version: 20251125 dnl Function to check if the python binary is available dnl "python${PYTHON_VERSION} python python# python#.#" AC_DEFUN([AX_PROG_PYTHON], [AS_IF( [test "x${PYTHON_VERSION}" != x], [ax_python_progs="python${PYTHON_VERSION}"], [ax_python_progs="python python3 python3.15 python3.14 python3.14 python3.12 python3.11 python3.10 python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2 python2.7 python2.6 python2.5"]) AC_CHECK_PROGS( [PYTHON], [$ax_python_progs]) AS_IF( [test "x${PYTHON}" != x], [ax_prog_python_version=`${PYTHON} -c "import sys; sys.stdout.write('%d.%d' % (sys.version_info[[0]], sys.version_info[[1]]))" 2>/dev/null`; ax_prog_python_platform=`${PYTHON} -c "import sys; sys.stdout.write(sys.platform)" 2>/dev/null`; AC_SUBST( [PYTHON_PLATFORM], [$ax_prog_python_platform]) ], [AC_MSG_ERROR( [Unable to find python]) ]) AC_SUBST( [PYTHON], [$PYTHON]) ]) dnl Function to check if the python-config binary is available dnl "python${PYTHON_VERSION}-config python-config" AC_DEFUN([AX_PROG_PYTHON_CONFIG], [AS_IF( [test "x${PYTHON_CONFIG}" = x && test "x${PYTHON_VERSION}" != x], [AC_CHECK_PROGS( [PYTHON_CONFIG], [python${PYTHON_VERSION}-config]) ]) AS_IF( [test "x${PYTHON_CONFIG}" = x], [AC_CHECK_PROGS( [PYTHON_CONFIG], [python-config python3-config python3.12-config python3.11-config python3.10-config python3.9-config python3.8-config python3.7-config python3.6-config python3.5-config python3.4-config python3.3-config python3.2-config python3.1-config python3.0-config python2-config python2.7-config python2.6-config python2.5-config]) ]) AS_IF( [test "x${PYTHON_CONFIG}" = x], [AC_MSG_ERROR( [Unable to find python-config]) ]) AC_SUBST( [PYTHON_CONFIG], [$PYTHON_CONFIG]) ]) dnl Function to detect if a Python build environment is available AC_DEFUN([AX_PYTHON_CHECK], [AX_PROG_PYTHON AX_PROG_PYTHON_CONFIG AS_IF( [test "x${PYTHON_CONFIG}" != x], [dnl Check for Python includes PYTHON_INCLUDES=`${PYTHON_CONFIG} --includes 2>/dev/null`; AC_MSG_CHECKING( [for Python includes]) AC_MSG_RESULT( [$PYTHON_INCLUDES]) dnl Check for Python libraries PYTHON_LDFLAGS=`${PYTHON_CONFIG} --ldflags 2>/dev/null`; AC_MSG_CHECKING( [for Python libraries]) AC_MSG_RESULT( [$PYTHON_LDFLAGS]) dnl For CygWin and MinGW add the -no-undefined linker flag AS_CASE( [$build], [*-*-cygwin*],[PYTHON_LDFLAGS="${PYTHON_LDFLAGS} -no-undefined"], [*-*-mingw*],[PYTHON_LDFLAGS="${PYTHON_LDFLAGS} -no-undefined"], [*-*-msys*],[PYTHON_LDFLAGS="${PYTHON_LDFLAGS} -no-undefined"], [*],[]) dnl Check for the existence of Python.h BACKUP_CPPFLAGS="${CPPFLAGS}" CPPFLAGS="${CPPFLAGS} ${PYTHON_INCLUDES}" AC_CHECK_HEADERS( [Python.h], [ac_cv_header_python_h=yes], [ac_cv_header_python_h=no]) CPPFLAGS="${BACKUP_CPPFLAGS}" ]) AS_IF( [test "x${ac_cv_header_python_h}" != xyes], [ac_cv_enable_python=no], [ac_cv_enable_python=${ax_prog_python_version} AC_SUBST( [PYTHON_CPPFLAGS], [$PYTHON_INCLUDES]) AC_SUBST( [PYTHON_LDFLAGS], [$PYTHON_LDFLAGS]) dnl Check for Python prefix AS_IF( [test "x${ac_cv_with_pyprefix}" = x || test "x${ac_cv_with_pyprefix}" = xno], [ax_python_prefix="\${prefix}"], [ax_python_prefix=`${PYTHON_CONFIG} --prefix 2>/dev/null`]) AC_SUBST( [PYTHON_PREFIX], [$ax_python_prefix]) dnl Check for Python exec-prefix AS_IF( [test "x${ac_cv_with_pyprefix}" = x || test "x${ac_cv_with_pyprefix}" = xno], [ax_python_exec_prefix="\${exec_prefix}"], [ax_python_exec_prefix=`${PYTHON_CONFIG} --exec-prefix 2>/dev/null`]) AC_SUBST( [PYTHON_EXEC_PREFIX], [$ax_python_exec_prefix]) dnl Check for Python library directory ax_python_pythondir_suffix=`${PYTHON} -c "import sys; import distutils.sysconfig; sys.stdout.write(distutils.sysconfig.get_python_lib(0, 0, prefix=''))" 2>/dev/null`; AS_IF( [test "x${ac_cv_with_pythondir}" = x || test "x${ac_cv_with_pythondir}" = xno], [AS_IF( [test "x${ac_cv_with_pyprefix}" = x || test "x${ac_cv_with_pyprefix}" = xno], [ax_python_pythondir="${ax_python_prefix}/${ax_python_pythondir_suffix}"], [ax_python_pythondir=`${PYTHON} -c "import sys; import distutils.sysconfig; sys.stdout.write(distutils.sysconfig.get_python_lib()) " 2>/dev/null`])], [ax_python_pythondir=$ac_cv_with_pythondir]) AC_SUBST( [pythondir], [$ax_python_pythondir]) dnl Check for Python platform specific library directory ax_python_pyexecdir_suffix=`${PYTHON} -c "import sys; import distutils.sysconfig; sys.stdout.write(distutils.sysconfig.get_python_lib(1, 0, prefix=''))" 2>/dev/null`; ax_python_library_dir=`${PYTHON} -c "import sys; import distutils.sysconfig; sys.stdout.write(distutils.sysconfig.get_python_lib(True)) " 2>/dev/null`; AS_IF( [test "x${ac_cv_with_pyprefix}" = x || test "x${ac_cv_with_pyprefix}" = xno], [ax_python_pyexecdir="${ax_python_exec_prefix}/${ax_python_pyexecdir_suffix}"], [ax_python_pyexecdir=$ax_python_library_dir]) AC_SUBST( [pyexecdir], [$ax_python_pyexecdir]) AC_SUBST( [PYTHON_LIBRARY_DIR], [$ax_python_pyexecdir_suffix]) AC_SUBST( [PYTHON_PACKAGE_DIR], [$ax_python_library_dir]) ]) ]) dnl Function to determine the prefix of pythondir AC_DEFUN([AX_PYTHON_CHECK_PYPREFIX], [AX_COMMON_ARG_WITH( [pyprefix], [pyprefix], [use `python-config --prefix' to determine the prefix of pythondir instead of --prefix], [no], [no]) ]) dnl Function to detect if to enable Python AC_DEFUN([AX_PYTHON_CHECK_ENABLE], [AX_PYTHON_CHECK_PYPREFIX AX_COMMON_ARG_ENABLE( [python], [python], [build Python bindings], [no]) AX_COMMON_ARG_WITH( [pythondir], [pythondir], [use to specify the Python directory (pythondir)], [no], [no]) AS_IF( [test "x${ac_cv_enable_python}" != xno], [AX_PYTHON_CHECK]) AM_CONDITIONAL( HAVE_PYTHON, [test "x${ac_cv_enable_python}" != xno]) AM_CONDITIONAL( HAVE_PYTHON_TESTS, [test "x${ac_cv_enable_python}" != xno]) ]) ]) ================================================ FILE: m4/tests.m4 ================================================ dnl Functions for testing dnl dnl Version: 20200712 dnl Function to detect if tests dependencies are available AC_DEFUN([AX_TESTS_CHECK_LOCAL], [AC_CHECK_HEADERS([dlfcn.h]) AC_CHECK_FUNCS([fmemopen getopt mkstemp setenv tzset unlink]) AC_CHECK_LIB( dl, dlsym) AS_IF( [test "x$lt_cv_prog_gnu_ld" = xyes && test "x$ac_cv_lib_dl_dlsym" = xyes], [AC_DEFINE( [HAVE_GNU_DL_DLSYM], [1], [Define to 1 if dlsym function is available in GNU dl.]) ]) ]) dnl Function to detect if OSS-Fuzz build environment is available AC_DEFUN([AX_TESTS_CHECK_OSSFUZZ], [AM_CONDITIONAL( HAVE_LIB_FUZZING_ENGINE, [test "x${LIB_FUZZING_ENGINE}" != x]) AC_SUBST( [LIB_FUZZING_ENGINE], ["${LIB_FUZZING_ENGINE}"]) ]) ================================================ FILE: m4/types.m4 ================================================ dnl Functions for type definitions dnl dnl Version: 20180727 dnl Function to detect if type definitions are available AC_DEFUN([AX_TYPES_CHECK_LOCAL], [AS_IF( [test "x$ac_cv_enable_winapi" = xyes], [ac_cv_enable_wide_character_type=yes]) AS_IF( [test "x$ac_cv_enable_wide_character_type" = xyes], [AC_DEFINE( [HAVE_WIDE_CHARACTER_TYPE], [1], [Define to 1 if wide character type should be used.]) AC_SUBST( [HAVE_WIDE_CHARACTER_TYPE], [1]) ], [AC_SUBST( [HAVE_WIDE_CHARACTER_TYPE], [0]) ]) AC_CHECK_HEADERS([sys/types.h inttypes.h stdint.h wchar.h]) AS_IF( [test "x$ac_cv_header_sys_types_h" = xyes], [AC_SUBST( [HAVE_SYS_TYPES_H], [1])], [AC_SUBST( [HAVE_SYS_TYPES_H], [0]) ]) AS_IF( [test "x$ac_cv_header_inttypes_h" = xyes], [AC_SUBST( [HAVE_INTTYPES_H], [1])], [AC_SUBST( [HAVE_INTTYPES_H], [0]) ]) AS_IF( [test "x$ac_cv_header_stdint_h" = xyes], [AC_SUBST( [HAVE_STDINT_H], [1])], [AC_SUBST( [HAVE_STDINT_H], [0]) ]) AS_IF( [test "x$ac_cv_header_wchar_h" = xyes], [AC_SUBST( [HAVE_WCHAR_H], [1]) ], [AC_SUBST( [HAVE_WCHAR_H], [0]) ]) AC_TYPE_MODE_T AC_TYPE_OFF_T AC_TYPE_SIZE_T AC_CHECK_TYPE( [size32_t], [AC_SUBST( [HAVE_SIZE32_T], [1])], [AC_SUBST( [HAVE_SIZE32_T], [0]) ]) AC_CHECK_TYPE( [ssize32_t], [AC_SUBST( [HAVE_SSIZE32_T], [1])], [AC_SUBST( [HAVE_SSIZE32_T], [0]) ]) AC_CHECK_TYPE( [size64_t], [AC_SUBST( [HAVE_SIZE64_T], [1])], [AC_SUBST( [HAVE_SIZE64_T], [0]) ]) AC_CHECK_TYPE( [ssize64_t], [AC_SUBST( [HAVE_SSIZE64_T], [1])], [AC_SUBST( [HAVE_SSIZE64_T], [0]) ]) AC_CHECK_TYPE( [off64_t], [AC_SUBST( [HAVE_OFF64_T], [1])], [AC_SUBST( [HAVE_OFF64_T], [0]) ]) AC_CHECK_TYPE([ssize_t]) AC_CHECK_TYPE([u64]) AC_CHECK_SIZEOF([int]) AC_CHECK_SIZEOF([long]) AC_CHECK_SIZEOF([off_t]) AC_CHECK_SIZEOF([size_t]) AS_IF( [test "x$ac_cv_header_wchar_h" = xyes], [AC_CHECK_SIZEOF([wchar_t])]) ]) ================================================ FILE: manuals/Makefile.am ================================================ man_MANS = \ fsntfsinfo.1 \ libfsntfs.3 EXTRA_DIST = \ fsntfsinfo.1 \ libfsntfs.3 DISTCLEANFILES = \ Makefile \ Makefile.in ================================================ FILE: manuals/fsntfsinfo.1 ================================================ .Dd May 21, 2024 .Dt fsntfsinfo .Os libfsntfs .Sh NAME .Nm fsntfsinfo .Nd determines information about a New Technology File System (NTFS) volume .Sh SYNOPSIS .Nm fsntfsinfo .Op Fl B Ar bodyfile .Op Fl E Ar mft_entry_index .Op Fl F Ar file_entry .Op Fl o Ar offset .Op Fl dhHUvV .Ar source .Sh DESCRIPTION .Nm fsntfsinfo is a utility to determine information about a New Technology File System (NTFS) volume .Pp .Nm fsntfsinfo is part of the .Nm libfsntfs package. .Nm libfsntfs is a library to access the New Technology File System (NTFS) format .Pp .Ar source is the source file. .Pp The options are as follows: .Bl -tag -width Ds .It Fl B Ar bodyfile output file system hierarchy as a bodyfile .It Fl d calculate a MD5 hash of a file entry to include in the bodyfile .It Fl E Ar mft_entry_index show information about a specific MFT entry index or "all" .It Fl F Ar file_entry show information about a specific file entry path .It Fl h shows this help .It Fl H shows the file system hierarcy .It Fl o Ar offset specify the volume offset .It Fl U shows information from the USN change journal ($UsnJrnl) .It Fl v verbose output to stderr .It Fl V print version .El .Sh ENVIRONMENT None .Sh FILES None .Sh EXAMPLES .Bd -literal # fsntfsinfo ntfs-img-kw-1.dd fsntfsinfo 20240521 .sp New Technology File System information: .sp Volume information: Name : KW-SRCH-1 Version : 3.1 Serial number : ba50ed9250ed5623 Cluster block size : 512 MFT entry size : 1024 Index entry size : 4096 .sp .Ed .Sh DIAGNOSTICS Errors, verbose and debug output are printed to stderr when verbose output \-v is enabled. Verbose and debug output are only printed when enabled at compilation. .Sh BUGS Please report bugs of any kind to or on the project website: https://github.com/libyal/libfsntfs/ .Sh AUTHOR These man pages were written by Joachim Metz. .Sh COPYRIGHT Copyright 2010-2024, Joachim Metz . This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. .Sh SEE ALSO ================================================ FILE: manuals/libfsntfs.3 ================================================ .Dd February 8, 2026 .Dt libfsntfs 3 .Os libfsntfs .Sh NAME .Nm libfsntfs.h .Nd Library to access the New Technology File System (NTFS) format .Sh SYNOPSIS .In libfsntfs.h .Pp Support functions .Ft const char * .Fn libfsntfs_get_version "void" .Ft int .Fn libfsntfs_get_access_flags_read "void" .Ft int .Fn libfsntfs_get_codepage "int *codepage" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_set_codepage "int codepage" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_check_volume_signature "const char *filename" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_check_mft_metadata_file_signature "const char *filename" "libfsntfs_error_t **error" .Pp Available when compiled with wide character string support: .Ft int .Fn libfsntfs_check_volume_signature_wide "const wchar_t *filename" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_check_mft_metadata_file_signature_wide "const wchar_t *filename" "libfsntfs_error_t **error" .Pp Available when compiled with libbfio support: .Ft int .Fn libfsntfs_check_volume_signature_file_io_handle "libbfio_handle_t *file_io_handle" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_check_mft_metadata_file_signature_file_io_handle "libbfio_handle_t *file_io_handle" "libfsntfs_error_t **error" .Pp Notify functions .Ft void .Fn libfsntfs_notify_set_verbose "int verbose" .Ft int .Fn libfsntfs_notify_set_stream "FILE *stream" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_notify_stream_open "const char *filename" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_notify_stream_close "libfsntfs_error_t **error" .Pp Error functions .Ft void .Fn libfsntfs_error_free "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_error_fprint "libfsntfs_error_t *error" "FILE *stream" .Ft int .Fn libfsntfs_error_sprint "libfsntfs_error_t *error" "char *string" "size_t size" .Ft int .Fn libfsntfs_error_backtrace_fprint "libfsntfs_error_t *error" "FILE *stream" .Ft int .Fn libfsntfs_error_backtrace_sprint "libfsntfs_error_t *error" "char *string" "size_t size" .Pp Volume functions .Ft int .Fn libfsntfs_volume_initialize "libfsntfs_volume_t **volume" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_free "libfsntfs_volume_t **volume" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_signal_abort "libfsntfs_volume_t *volume" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_open "libfsntfs_volume_t *volume" "const char *filename" "int access_flags" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_close "libfsntfs_volume_t *volume" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_has_bitlocker_drive_encryption "libfsntfs_volume_t *volume" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_has_volume_shadow_snapshots "libfsntfs_volume_t *volume" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_get_bytes_per_sector "libfsntfs_volume_t *volume" "uint16_t *bytes_per_sector" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_get_cluster_block_size "libfsntfs_volume_t *volume" "size32_t *cluster_block_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_get_mft_entry_size "libfsntfs_volume_t *volume" "size32_t *mft_entry_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_get_index_entry_size "libfsntfs_volume_t *volume" "size32_t *index_entry_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_get_utf8_name_size "libfsntfs_volume_t *volume" "size_t *utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_get_utf8_name "libfsntfs_volume_t *volume" "uint8_t *utf8_string" "size_t utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_get_utf16_name_size "libfsntfs_volume_t *volume" "size_t *utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_get_utf16_name "libfsntfs_volume_t *volume" "uint16_t *utf16_string" "size_t utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_get_version "libfsntfs_volume_t *volume" "uint8_t *major_version" "uint8_t *minor_version" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_get_flags "libfsntfs_volume_t *volume" "uint16_t *flags" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_get_serial_number "libfsntfs_volume_t *volume" "uint64_t *serial_number" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_get_root_directory "libfsntfs_volume_t *volume" "libfsntfs_file_entry_t **file_entry" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_get_number_of_file_entries "libfsntfs_volume_t *volume" "uint64_t *number_of_file_entries" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_get_file_entry_by_index "libfsntfs_volume_t *volume" "uint64_t mft_entry_index" "libfsntfs_file_entry_t **file_entry" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_get_file_entry_by_utf8_path "libfsntfs_volume_t *volume" "const uint8_t *utf8_string" "size_t utf8_string_length" "libfsntfs_file_entry_t **file_entry" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_get_file_entry_by_utf16_path "libfsntfs_volume_t *volume" "const uint16_t *utf16_string" "size_t utf16_string_length" "libfsntfs_file_entry_t **file_entry" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_get_usn_change_journal "libfsntfs_volume_t *volume" "libfsntfs_usn_change_journal_t **usn_change_journal" "libfsntfs_error_t **error" .Pp Available when compiled with wide character string support: .Ft int .Fn libfsntfs_volume_open_wide "libfsntfs_volume_t *volume" "const wchar_t *filename" "int access_flags" "libfsntfs_error_t **error" .Pp Available when compiled with libbfio support: .Ft int .Fn libfsntfs_volume_open_file_io_handle "libfsntfs_volume_t *volume" "libbfio_handle_t *file_io_handle" "int access_flags" "libfsntfs_error_t **error" .Pp File entry functions .Ft int .Fn libfsntfs_file_entry_free "libfsntfs_file_entry_t **file_entry" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_is_empty "libfsntfs_file_entry_t *file_entry" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_is_allocated "libfsntfs_file_entry_t *file_entry" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_is_corrupted "libfsntfs_file_entry_t *file_entry" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_file_reference "libfsntfs_file_entry_t *file_entry" "uint64_t *file_reference" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_base_record_file_reference "libfsntfs_file_entry_t *file_entry" "uint64_t *file_reference" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_parent_file_reference "libfsntfs_file_entry_t *file_entry" "uint64_t *parent_file_reference" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_parent_file_reference_by_attribute_index "libfsntfs_file_entry_t *file_entry" "int attribute_index" "uint64_t *parent_file_reference" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_journal_sequence_number "libfsntfs_file_entry_t *file_entry" "uint64_t *journal_sequence_number" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_creation_time "libfsntfs_file_entry_t *file_entry" "uint64_t *filetime" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_modification_time "libfsntfs_file_entry_t *file_entry" "uint64_t *filetime" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_access_time "libfsntfs_file_entry_t *file_entry" "uint64_t *filetime" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_entry_modification_time "libfsntfs_file_entry_t *file_entry" "uint64_t *filetime" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_file_attribute_flags "libfsntfs_file_entry_t *file_entry" "uint32_t *file_attribute_flags" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_i30_file_reference "libfsntfs_file_entry_t *file_entry" "uint64_t *file_reference" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_i30_creation_time "libfsntfs_file_entry_t *file_entry" "uint64_t *filetime" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_i30_modification_time "libfsntfs_file_entry_t *file_entry" "uint64_t *filetime" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_i30_access_time "libfsntfs_file_entry_t *file_entry" "uint64_t *filetime" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_i30_entry_modification_time "libfsntfs_file_entry_t *file_entry" "uint64_t *filetime" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_i30_size "libfsntfs_file_entry_t *file_entry" "uint64_t *size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_i30_file_attribute_flags "libfsntfs_file_entry_t *file_entry" "uint32_t *file_attribute_flags" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_utf8_name_size "libfsntfs_file_entry_t *file_entry" "size_t *utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_utf8_name "libfsntfs_file_entry_t *file_entry" "uint8_t *utf8_string" "size_t utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_utf16_name_size "libfsntfs_file_entry_t *file_entry" "size_t *utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_utf16_name "libfsntfs_file_entry_t *file_entry" "uint16_t *utf16_string" "size_t utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_name_attribute_index "libfsntfs_file_entry_t *file_entry" "int *attribute_index" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_utf8_name_size_by_attribute_index "libfsntfs_file_entry_t *file_entry" "int attribute_index" "size_t *utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_utf8_name_by_attribute_index "libfsntfs_file_entry_t *file_entry" "int attribute_index" "uint8_t *utf8_string" "size_t utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_utf16_name_size_by_attribute_index "libfsntfs_file_entry_t *file_entry" "int attribute_index" "size_t *utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_utf16_name_by_attribute_index "libfsntfs_file_entry_t *file_entry" "int attribute_index" "uint16_t *utf16_string" "size_t utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_utf8_path_hint_size "libfsntfs_file_entry_t *file_entry" "int attribute_index" "size_t *utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_utf8_path_hint "libfsntfs_file_entry_t *file_entry" "int attribute_index" "uint8_t *utf8_string" "size_t utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_utf16_path_hint_size "libfsntfs_file_entry_t *file_entry" "int attribute_index" "size_t *utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_utf16_path_hint "libfsntfs_file_entry_t *file_entry" "int attribute_index" "uint16_t *utf16_string" "size_t utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_utf8_symbolic_link_target_size "libfsntfs_file_entry_t *file_entry" "size_t *utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_utf8_symbolic_link_target "libfsntfs_file_entry_t *file_entry" "uint8_t *utf8_string" "size_t utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_utf16_symbolic_link_target_size "libfsntfs_file_entry_t *file_entry" "size_t *utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_utf16_symbolic_link_target "libfsntfs_file_entry_t *file_entry" "uint16_t *utf16_string" "size_t utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_security_descriptor_size "libfsntfs_file_entry_t *file_entry" "size_t *data_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_security_descriptor "libfsntfs_file_entry_t *file_entry" "uint8_t *data" "size_t data_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_number_of_attributes "libfsntfs_file_entry_t *file_entry" "int *number_of_attributes" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_attribute_by_index "libfsntfs_file_entry_t *file_entry" "int attribute_index" "libfsntfs_attribute_t **attribute" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_has_directory_entries_index "libfsntfs_file_entry_t *file_entry" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_has_default_data_stream "libfsntfs_file_entry_t *file_entry" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_has_i30_entry "libfsntfs_file_entry_t *file_entry" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_is_symbolic_link "libfsntfs_file_entry_t *file_entry" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_number_of_alternate_data_streams "libfsntfs_file_entry_t *file_entry" "int *number_of_alternate_data_streams" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_alternate_data_stream_by_index "libfsntfs_file_entry_t *file_entry" "int alternate_data_stream_index" "libfsntfs_data_stream_t **alternate_data_stream" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_has_alternate_data_stream_by_utf8_name "libfsntfs_file_entry_t *file_entry" "const uint8_t *utf8_string" "size_t utf8_string_length" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_has_alternate_data_stream_by_utf16_name "libfsntfs_file_entry_t *file_entry" "const uint16_t *utf16_string" "size_t utf16_string_length" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_alternate_data_stream_by_utf8_name "libfsntfs_file_entry_t *file_entry" "const uint8_t *utf8_string" "size_t utf8_string_length" "libfsntfs_data_stream_t **alternate_data_stream" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_alternate_data_stream_by_utf16_name "libfsntfs_file_entry_t *file_entry" "const uint16_t *utf16_string" "size_t utf16_string_length" "libfsntfs_data_stream_t **alternate_data_stream" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_number_of_sub_file_entries "libfsntfs_file_entry_t *file_entry" "int *number_of_sub_file_entries" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_sub_file_entry_by_index "libfsntfs_file_entry_t *file_entry" "int sub_file_entry_index" "libfsntfs_file_entry_t **sub_file_entry" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_sub_file_entry_by_utf8_name "libfsntfs_file_entry_t *file_entry" "const uint8_t *utf8_string" "size_t utf8_string_length" "libfsntfs_file_entry_t **sub_file_entry" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_sub_file_entry_by_utf16_name "libfsntfs_file_entry_t *file_entry" "const uint16_t *utf16_string" "size_t utf16_string_length" "libfsntfs_file_entry_t **sub_file_entry" "libfsntfs_error_t **error" .Ft ssize_t .Fn libfsntfs_file_entry_read_buffer "libfsntfs_file_entry_t *file_entry" "void *buffer" "size_t buffer_size" "libfsntfs_error_t **error" .Ft ssize_t .Fn libfsntfs_file_entry_read_buffer_at_offset "libfsntfs_file_entry_t *file_entry" "void *buffer" "size_t buffer_size" "off64_t offset" "libfsntfs_error_t **error" .Ft off64_t .Fn libfsntfs_file_entry_seek_offset "libfsntfs_file_entry_t *file_entry" "off64_t offset" "int whence" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_offset "libfsntfs_file_entry_t *file_entry" "off64_t *offset" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_size "libfsntfs_file_entry_t *file_entry" "size64_t *size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_number_of_extents "libfsntfs_file_entry_t *file_entry" "int *number_of_extents" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_entry_get_extent_by_index "libfsntfs_file_entry_t *file_entry" "int extent_index" "off64_t *extent_offset" "size64_t *extent_size" "uint32_t *extent_flags" "libfsntfs_error_t **error" .Pp Attribute functions .Ft int .Fn libfsntfs_attribute_free "libfsntfs_attribute_t **attribute" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_attribute_get_type "libfsntfs_attribute_t *attribute" "uint32_t *type" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_attribute_get_data_flags "libfsntfs_attribute_t *attribute" "uint16_t *data_flags" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_attribute_get_utf8_name_size "libfsntfs_attribute_t *attribute" "size_t *utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_attribute_get_utf8_name "libfsntfs_attribute_t *attribute" "uint8_t *utf8_string" "size_t utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_attribute_get_utf16_name_size "libfsntfs_attribute_t *attribute" "size_t *utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_attribute_get_utf16_name "libfsntfs_attribute_t *attribute" "uint16_t *utf16_string" "size_t utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_attribute_get_data_vcn_range "libfsntfs_attribute_t *attribute" "uint64_t *data_first_vcn" "uint64_t *data_last_vcn" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_attribute_get_data_size "libfsntfs_attribute_t *attribute" "size64_t *data_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_attribute_get_valid_data_size "libfsntfs_attribute_t *attribute" "size64_t *valid_data_size" "libfsntfs_error_t **error" .Pp $ATTRIBUTE_LIST attribute functions .Ft int .Fn libfsntfs_attribute_list_attribute_get_number_of_entries "libfsntfs_attribute_t *attribute" "int *number_of_entries" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_attribute_list_attribute_get_entry_by_index "libfsntfs_attribute_t *attribute" "int entry_index" "libfsntfs_attribute_list_entry_t **entry" "libfsntfs_error_t **error" .Pp Attribute list entry functions .Ft int .Fn libfsntfs_attribute_list_entry_free "libfsntfs_attribute_list_entry_t **attribute_list_entry" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_attribute_list_entry_get_attribute_type "libfsntfs_attribute_list_entry_t *attribute_list_entry" "uint32_t *attribute_type" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_attribute_list_entry_get_file_reference "libfsntfs_attribute_list_entry_t *attribute_list_entry" "uint64_t *file_reference" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_attribute_list_entry_get_utf8_name_size "libfsntfs_attribute_list_entry_t *attribute_list_entry" "size_t *utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_attribute_list_entry_get_utf8_name "libfsntfs_attribute_list_entry_t *attribute_list_entry" "uint8_t *utf8_string" "size_t utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_attribute_list_entry_get_utf16_name_size "libfsntfs_attribute_list_entry_t *attribute_list_entry" "size_t *utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_attribute_list_entry_get_utf16_name "libfsntfs_attribute_list_entry_t *attribute_list_entry" "uint16_t *utf16_string" "size_t utf16_string_size" "libfsntfs_error_t **error" .Pp $FILE_NAME attribute functions .Ft int .Fn libfsntfs_file_name_attribute_get_parent_file_reference "libfsntfs_attribute_t *attribute" "uint64_t *parent_file_reference" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_name_attribute_get_creation_time "libfsntfs_attribute_t *attribute" "uint64_t *filetime" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_name_attribute_get_modification_time "libfsntfs_attribute_t *attribute" "uint64_t *filetime" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_name_attribute_get_access_time "libfsntfs_attribute_t *attribute" "uint64_t *filetime" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_name_attribute_get_entry_modification_time "libfsntfs_attribute_t *attribute" "uint64_t *filetime" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_name_attribute_get_file_attribute_flags "libfsntfs_attribute_t *attribute" "uint32_t *file_attribute_flags" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_name_attribute_get_name_space "libfsntfs_attribute_t *attribute" "uint8_t *name_space" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_name_attribute_get_utf8_name_size "libfsntfs_attribute_t *attribute" "size_t *utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_name_attribute_get_utf8_name "libfsntfs_attribute_t *attribute" "uint8_t *utf8_string" "size_t utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_name_attribute_get_utf16_name_size "libfsntfs_attribute_t *attribute" "size_t *utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_file_name_attribute_get_utf16_name "libfsntfs_attribute_t *attribute" "uint16_t *utf16_string" "size_t utf16_string_size" "libfsntfs_error_t **error" .Pp $OBJECT_ID attribute functions .Ft int .Fn libfsntfs_object_identifier_attribute_get_droid_file_identifier "libfsntfs_attribute_t *attribute" "uint8_t *guid" "size_t size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_object_identifier_attribute_get_birth_droid_volume_identifier "libfsntfs_attribute_t *attribute" "uint8_t *guid" "size_t size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_object_identifier_attribute_get_birth_droid_file_identifier "libfsntfs_attribute_t *attribute" "uint8_t *guid" "size_t size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_object_identifier_attribute_get_birth_droid_domain_identifier "libfsntfs_attribute_t *attribute" "uint8_t *guid" "size_t size" "libfsntfs_error_t **error" .Pp $REPARSE_POINT attribute functions .Ft int .Fn libfsntfs_reparse_point_attribute_get_tag "libfsntfs_attribute_t *attribute" "uint32_t *tag" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_reparse_point_attribute_get_compression_method "libfsntfs_attribute_t *attribute" "uint32_t *compression_method" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_reparse_point_attribute_get_utf8_substitute_name_size "libfsntfs_attribute_t *attribute" "size_t *utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_reparse_point_attribute_get_utf8_substitute_name "libfsntfs_attribute_t *attribute" "uint8_t *utf8_string" "size_t utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_reparse_point_attribute_get_utf16_substitute_name_size "libfsntfs_attribute_t *attribute" "size_t *utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_reparse_point_attribute_get_utf16_substitute_name "libfsntfs_attribute_t *attribute" "uint16_t *utf16_string" "size_t utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_reparse_point_attribute_get_utf8_print_name_size "libfsntfs_attribute_t *attribute" "size_t *utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_reparse_point_attribute_get_utf8_print_name "libfsntfs_attribute_t *attribute" "uint8_t *utf8_string" "size_t utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_reparse_point_attribute_get_utf16_print_name_size "libfsntfs_attribute_t *attribute" "size_t *utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_reparse_point_attribute_get_utf16_print_name "libfsntfs_attribute_t *attribute" "uint16_t *utf16_string" "size_t utf16_string_size" "libfsntfs_error_t **error" .Pp $SECURITY_DESCRIPTOR attribute functions .Ft int .Fn libfsntfs_security_descriptor_attribute_get_security_descriptor_size "libfsntfs_attribute_t *attribute" "size_t *data_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_security_descriptor_attribute_get_security_descriptor "libfsntfs_attribute_t *attribute" "uint8_t *data" "size_t data_size" "libfsntfs_error_t **error" .Pp $STANDARD_INFORMATION attribute functions .Ft int .Fn libfsntfs_standard_information_attribute_get_creation_time "libfsntfs_attribute_t *attribute" "uint64_t *filetime" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_standard_information_attribute_get_modification_time "libfsntfs_attribute_t *attribute" "uint64_t *filetime" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_standard_information_attribute_get_access_time "libfsntfs_attribute_t *attribute" "uint64_t *filetime" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_standard_information_attribute_get_entry_modification_time "libfsntfs_attribute_t *attribute" "uint64_t *filetime" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_standard_information_attribute_get_file_attribute_flags "libfsntfs_attribute_t *attribute" "uint32_t *file_attribute_flags" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_standard_information_attribute_get_owner_identifier "libfsntfs_attribute_t *attribute" "uint32_t *owner_identifier" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_standard_information_attribute_get_security_descriptor_identifier "libfsntfs_attribute_t *attribute" "uint32_t *security_descriptor_identifier" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_standard_information_attribute_get_update_sequence_number "libfsntfs_attribute_t *attribute" "uint64_t *update_sequence_number" "libfsntfs_error_t **error" .Pp $VOLUME_INFORMATION attribute functions .Ft int .Fn libfsntfs_volume_information_attribute_get_version "libfsntfs_attribute_t *attribute" "uint8_t *major_version" "uint8_t *minor_version" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_information_attribute_get_flags "libfsntfs_attribute_t *attribute" "uint16_t *flags" "libfsntfs_error_t **error" .Pp $VOLUME_NAME attribute functions .Ft int .Fn libfsntfs_volume_name_attribute_get_utf8_name_size "libfsntfs_attribute_t *attribute" "size_t *utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_name_attribute_get_utf8_name "libfsntfs_attribute_t *attribute" "uint8_t *utf8_string" "size_t utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_name_attribute_get_utf16_name_size "libfsntfs_attribute_t *attribute" "size_t *utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_volume_name_attribute_get_utf16_name "libfsntfs_attribute_t *attribute" "uint16_t *utf16_string" "size_t utf16_string_size" "libfsntfs_error_t **error" .Pp Data stream functions .Ft int .Fn libfsntfs_data_stream_free "libfsntfs_data_stream_t **data_stream" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_data_stream_get_utf8_name_size "libfsntfs_data_stream_t *data_stream" "size_t *utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_data_stream_get_utf8_name "libfsntfs_data_stream_t *data_stream" "uint8_t *utf8_string" "size_t utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_data_stream_get_utf16_name_size "libfsntfs_data_stream_t *data_stream" "size_t *utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_data_stream_get_utf16_name "libfsntfs_data_stream_t *data_stream" "uint16_t *utf16_string" "size_t utf16_string_size" "libfsntfs_error_t **error" .Ft ssize_t .Fn libfsntfs_data_stream_read_buffer "libfsntfs_data_stream_t *data_stream" "void *buffer" "size_t buffer_size" "libfsntfs_error_t **error" .Ft ssize_t .Fn libfsntfs_data_stream_read_buffer_at_offset "libfsntfs_data_stream_t *data_stream" "void *buffer" "size_t buffer_size" "off64_t offset" "libfsntfs_error_t **error" .Ft off64_t .Fn libfsntfs_data_stream_seek_offset "libfsntfs_data_stream_t *data_stream" "off64_t offset" "int whence" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_data_stream_get_offset "libfsntfs_data_stream_t *data_stream" "off64_t *offset" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_data_stream_get_size "libfsntfs_data_stream_t *data_stream" "size64_t *size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_data_stream_get_number_of_extents "libfsntfs_data_stream_t *data_stream" "int *number_of_extents" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_data_stream_get_extent_by_index "libfsntfs_data_stream_t *data_stream" "int extent_index" "off64_t *extent_offset" "size64_t *extent_size" "uint32_t *extent_flags" "libfsntfs_error_t **error" .Pp MFT metadata file functions .Ft int .Fn libfsntfs_mft_metadata_file_initialize "libfsntfs_mft_metadata_file_t **mft_metadata_file" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_mft_metadata_file_free "libfsntfs_mft_metadata_file_t **mft_metadata_file" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_mft_metadata_file_open "libfsntfs_mft_metadata_file_t *mft_metadata_file" "const char *filename" "int access_flags" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_mft_metadata_file_close "libfsntfs_mft_metadata_file_t *mft_metadata_file" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_mft_metadata_file_get_utf8_volume_name_size "libfsntfs_mft_metadata_file_t *mft_metadata_file" "size_t *utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_mft_metadata_file_get_utf8_volume_name "libfsntfs_mft_metadata_file_t *mft_metadata_file" "uint8_t *utf8_string" "size_t utf8_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_mft_metadata_file_get_utf16_volume_name_size "libfsntfs_mft_metadata_file_t *mft_metadata_file" "size_t *utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_mft_metadata_file_get_utf16_volume_name "libfsntfs_mft_metadata_file_t *mft_metadata_file" "uint16_t *utf16_string" "size_t utf16_string_size" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_mft_metadata_file_get_volume_version "libfsntfs_mft_metadata_file_t *mft_metadata_file" "uint8_t *major_version" "uint8_t *minor_version" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_mft_metadata_file_get_volume_flags "libfsntfs_mft_metadata_file_t *mft_metadata_file" "uint16_t *flags" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_mft_metadata_file_get_number_of_file_entries "libfsntfs_mft_metadata_file_t *mft_metadata_file" "uint64_t *number_of_file_entries" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_mft_metadata_file_get_file_entry_by_index "libfsntfs_mft_metadata_file_t *mft_metadata_file" "uint64_t mft_entry_index" "libfsntfs_file_entry_t **file_entry" "libfsntfs_error_t **error" .Pp Available when compiled with wide character string support: .Ft int .Fn libfsntfs_mft_metadata_file_open_wide "libfsntfs_mft_metadata_file_t *mft_metadata_file" "const wchar_t *filename" "int access_flags" "libfsntfs_error_t **error" .Pp Available when compiled with libbfio support: .Ft int .Fn libfsntfs_mft_metadata_file_open_file_io_handle "libfsntfs_mft_metadata_file_t *mft_metadata_file" "libbfio_handle_t *file_io_handle" "int access_flags" "libfsntfs_error_t **error" .Pp USN change journal functions .Ft int .Fn libfsntfs_usn_change_journal_free "libfsntfs_usn_change_journal_t **usn_change_journal" "libfsntfs_error_t **error" .Ft int .Fn libfsntfs_usn_change_journal_get_offset "libfsntfs_usn_change_journal_t *usn_change_journal" "off64_t *offset" "libfsntfs_error_t **error" .Ft ssize_t .Fn libfsntfs_usn_change_journal_read_usn_record "libfsntfs_usn_change_journal_t *usn_change_journal" "uint8_t *usn_record_data" "size_t usn_record_data_size" "libfsntfs_error_t **error" .Sh DESCRIPTION The .Fn libfsntfs_get_version function is used to retrieve the library version. .Sh RETURN VALUES Most of the functions return NULL or \-1 on error, dependent on the return type. For the actual return values see "libfsntfs.h". .Sh ENVIRONMENT None .Sh FILES None .Sh NOTES libfsntfs can be compiled with wide character support (wchar_t). .sp To compile libfsntfs with wide character support use: .Ar ./configure --enable-wide-character-type=yes or define: .Ar _UNICODE or .Ar UNICODE during compilation. .sp .Ar LIBFSNTFS_WIDE_CHARACTER_TYPE in libfsntfs/features.h can be used to determine if libfsntfs was compiled with wide character support. .Sh BUGS Please report bugs of any kind on the project issue tracker: https://github.com/libyal/libfsntfs/issues .Sh AUTHOR These man pages are generated from "libfsntfs.h". .Sh COPYRIGHT Copyright (C) 2010-2026, Joachim Metz . .sp This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. .Sh SEE ALSO the libfsntfs.h include file ================================================ FILE: msvscpp/Makefile.am ================================================ MSVSCPP_FILES = \ fsntfs_test_attribute/fsntfs_test_attribute.vcproj \ fsntfs_test_attribute_list_entry/fsntfs_test_attribute_list_entry.vcproj \ fsntfs_test_bitmap_values/fsntfs_test_bitmap_values.vcproj \ fsntfs_test_buffer_data_handle/fsntfs_test_buffer_data_handle.vcproj \ fsntfs_test_cluster_block/fsntfs_test_cluster_block.vcproj \ fsntfs_test_cluster_block_data/fsntfs_test_cluster_block_data.vcproj \ fsntfs_test_cluster_block_stream/fsntfs_test_cluster_block_stream.vcproj \ fsntfs_test_cluster_block_vector/fsntfs_test_cluster_block_vector.vcproj \ fsntfs_test_compressed_block/fsntfs_test_compressed_block.vcproj \ fsntfs_test_compressed_block_data_handle/fsntfs_test_compressed_block_data_handle.vcproj \ fsntfs_test_compressed_block_vector/fsntfs_test_compressed_block_vector.vcproj \ fsntfs_test_compressed_data_handle/fsntfs_test_compressed_data_handle.vcproj \ fsntfs_test_compression/fsntfs_test_compression.vcproj \ fsntfs_test_compression_unit_data_handle/fsntfs_test_compression_unit_data_handle.vcproj \ fsntfs_test_compression_unit_descriptor/fsntfs_test_compression_unit_descriptor.vcproj \ fsntfs_test_data_run/fsntfs_test_data_run.vcproj \ fsntfs_test_data_stream/fsntfs_test_data_stream.vcproj \ fsntfs_test_directory_entries_tree/fsntfs_test_directory_entries_tree.vcproj \ fsntfs_test_directory_entry/fsntfs_test_directory_entry.vcproj \ fsntfs_test_error/fsntfs_test_error.vcproj \ fsntfs_test_extent/fsntfs_test_extent.vcproj \ fsntfs_test_file_entry/fsntfs_test_file_entry.vcproj \ fsntfs_test_file_name_attribute/fsntfs_test_file_name_attribute.vcproj \ fsntfs_test_file_name_values/fsntfs_test_file_name_values.vcproj \ fsntfs_test_file_system/fsntfs_test_file_system.vcproj \ fsntfs_test_fixup_values/fsntfs_test_fixup_values.vcproj \ fsntfs_test_index/fsntfs_test_index.vcproj \ fsntfs_test_index_entry/fsntfs_test_index_entry.vcproj \ fsntfs_test_index_entry_header/fsntfs_test_index_entry_header.vcproj \ fsntfs_test_index_entry_vector/fsntfs_test_index_entry_vector.vcproj \ fsntfs_test_index_node/fsntfs_test_index_node.vcproj \ fsntfs_test_index_node_header/fsntfs_test_index_node_header.vcproj \ fsntfs_test_index_root_header/fsntfs_test_index_root_header.vcproj \ fsntfs_test_index_value/fsntfs_test_index_value.vcproj \ fsntfs_test_io_handle/fsntfs_test_io_handle.vcproj \ fsntfs_test_logged_utility_stream_values/fsntfs_test_logged_utility_stream_values.vcproj \ fsntfs_test_mft/fsntfs_test_mft.vcproj \ fsntfs_test_mft_attribute/fsntfs_test_mft_attribute.vcproj \ fsntfs_test_mft_attribute_list/fsntfs_test_mft_attribute_list.vcproj \ fsntfs_test_mft_attribute_list_entry/fsntfs_test_mft_attribute_list_entry.vcproj \ fsntfs_test_mft_entry/fsntfs_test_mft_entry.vcproj \ fsntfs_test_mft_entry_header/fsntfs_test_mft_entry_header.vcproj \ fsntfs_test_mft_metadata_file/fsntfs_test_mft_metadata_file.vcproj \ fsntfs_test_name/fsntfs_test_name.vcproj \ fsntfs_test_notify/fsntfs_test_notify.vcproj \ fsntfs_test_object_identifier_values/fsntfs_test_object_identifier_values.vcproj \ fsntfs_test_path_hint/fsntfs_test_path_hint.vcproj \ fsntfs_test_profiler/fsntfs_test_profiler.vcproj \ fsntfs_test_reparse_point_attribute/fsntfs_test_reparse_point_attribute.vcproj \ fsntfs_test_reparse_point_values/fsntfs_test_reparse_point_values.vcproj \ fsntfs_test_sds_index_value/fsntfs_test_sds_index_value.vcproj \ fsntfs_test_security_descriptor_index/fsntfs_test_security_descriptor_index.vcproj \ fsntfs_test_security_descriptor_index_value/fsntfs_test_security_descriptor_index_value.vcproj \ fsntfs_test_security_descriptor_values/fsntfs_test_security_descriptor_values.vcproj \ fsntfs_test_standard_information_values/fsntfs_test_standard_information_values.vcproj \ fsntfs_test_support/fsntfs_test_support.vcproj \ fsntfs_test_tools_bodyfile/fsntfs_test_tools_bodyfile.vcproj \ fsntfs_test_tools_digest_hash/fsntfs_test_tools_digest_hash.vcproj \ fsntfs_test_tools_info_handle/fsntfs_test_tools_info_handle.vcproj \ fsntfs_test_tools_mount_path_string/fsntfs_test_tools_mount_path_string.vcproj \ fsntfs_test_tools_output/fsntfs_test_tools_output.vcproj \ fsntfs_test_tools_path_string/fsntfs_test_tools_path_string.vcproj \ fsntfs_test_tools_signal/fsntfs_test_tools_signal.vcproj \ fsntfs_test_txf_data_values/fsntfs_test_txf_data_values.vcproj \ fsntfs_test_usn_change_journal/fsntfs_test_usn_change_journal.vcproj \ fsntfs_test_volume/fsntfs_test_volume.vcproj \ fsntfs_test_volume_header/fsntfs_test_volume_header.vcproj \ fsntfs_test_volume_information_attribute/fsntfs_test_volume_information_attribute.vcproj \ fsntfs_test_volume_information_values/fsntfs_test_volume_information_values.vcproj \ fsntfs_test_volume_name_attribute/fsntfs_test_volume_name_attribute.vcproj \ fsntfs_test_volume_name_values/fsntfs_test_volume_name_values.vcproj \ fsntfsinfo/fsntfsinfo.vcproj \ fsntfsmount/fsntfsmount.vcproj \ libbfio/libbfio.vcproj \ libcdata/libcdata.vcproj \ libcerror/libcerror.vcproj \ libcfile/libcfile.vcproj \ libclocale/libclocale.vcproj \ libcnotify/libcnotify.vcproj \ libcpath/libcpath.vcproj \ libcsplit/libcsplit.vcproj \ libcthreads/libcthreads.vcproj \ libfcache/libfcache.vcproj \ libfdata/libfdata.vcproj \ libfdatetime/libfdatetime.vcproj \ libfguid/libfguid.vcproj \ libfsntfs/libfsntfs.vcproj \ libfusn/libfusn.vcproj \ libfwnt/libfwnt.vcproj \ libhmac/libhmac.vcproj \ libuna/libuna.vcproj \ pyfsntfs/pyfsntfs.vcproj \ libfsntfs.sln EXTRA_DIST = \ $(MSVSCPP_FILES) DISTCLEANFILES = \ Makefile \ Makefile.in ================================================ FILE: msvscpp/fsntfs_test_attribute/fsntfs_test_attribute.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_attribute_list_entry/fsntfs_test_attribute_list_entry.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_bitmap_values/fsntfs_test_bitmap_values.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_buffer_data_handle/fsntfs_test_buffer_data_handle.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_cluster_block/fsntfs_test_cluster_block.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_cluster_block_data/fsntfs_test_cluster_block_data.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_cluster_block_stream/fsntfs_test_cluster_block_stream.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_cluster_block_vector/fsntfs_test_cluster_block_vector.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_compressed_block/fsntfs_test_compressed_block.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_compressed_block_data_handle/fsntfs_test_compressed_block_data_handle.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_compressed_block_vector/fsntfs_test_compressed_block_vector.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_compressed_data_handle/fsntfs_test_compressed_data_handle.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_compression/fsntfs_test_compression.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_compression_unit_data_handle/fsntfs_test_compression_unit_data_handle.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_compression_unit_descriptor/fsntfs_test_compression_unit_descriptor.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_data_run/fsntfs_test_data_run.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_data_stream/fsntfs_test_data_stream.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_directory_entries_tree/fsntfs_test_directory_entries_tree.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_directory_entry/fsntfs_test_directory_entry.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_error/fsntfs_test_error.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_extent/fsntfs_test_extent.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_file_entry/fsntfs_test_file_entry.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_file_name_attribute/fsntfs_test_file_name_attribute.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_file_name_values/fsntfs_test_file_name_values.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_file_system/fsntfs_test_file_system.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_fixup_values/fsntfs_test_fixup_values.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_index/fsntfs_test_index.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_index_entry/fsntfs_test_index_entry.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_index_entry_header/fsntfs_test_index_entry_header.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_index_entry_vector/fsntfs_test_index_entry_vector.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_index_node/fsntfs_test_index_node.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_index_node_header/fsntfs_test_index_node_header.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_index_root_header/fsntfs_test_index_root_header.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_index_value/fsntfs_test_index_value.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_io_handle/fsntfs_test_io_handle.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_logged_utility_stream_values/fsntfs_test_logged_utility_stream_values.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_mft/fsntfs_test_mft.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_mft_attribute/fsntfs_test_mft_attribute.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_mft_attribute_list/fsntfs_test_mft_attribute_list.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_mft_attribute_list_entry/fsntfs_test_mft_attribute_list_entry.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_mft_entry/fsntfs_test_mft_entry.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_mft_entry_header/fsntfs_test_mft_entry_header.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_mft_metadata_file/fsntfs_test_mft_metadata_file.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_name/fsntfs_test_name.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_notify/fsntfs_test_notify.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_object_identifier_values/fsntfs_test_object_identifier_values.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_path_hint/fsntfs_test_path_hint.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_profiler/fsntfs_test_profiler.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_reparse_point_attribute/fsntfs_test_reparse_point_attribute.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_reparse_point_values/fsntfs_test_reparse_point_values.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_sds_index_value/fsntfs_test_sds_index_value.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_security_descriptor_index/fsntfs_test_security_descriptor_index.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_security_descriptor_index_value/fsntfs_test_security_descriptor_index_value.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_security_descriptor_values/fsntfs_test_security_descriptor_values.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_standard_information_values/fsntfs_test_standard_information_values.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_support/fsntfs_test_support.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_tools_bodyfile/fsntfs_test_tools_bodyfile.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_tools_digest_hash/fsntfs_test_tools_digest_hash.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_tools_info_handle/fsntfs_test_tools_info_handle.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_tools_mount_path_string/fsntfs_test_tools_mount_path_string.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_tools_output/fsntfs_test_tools_output.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_tools_path_string/fsntfs_test_tools_path_string.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_tools_signal/fsntfs_test_tools_signal.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_txf_data_values/fsntfs_test_txf_data_values.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_usn_change_journal/fsntfs_test_usn_change_journal.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_volume/fsntfs_test_volume.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_volume_header/fsntfs_test_volume_header.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_volume_information_attribute/fsntfs_test_volume_information_attribute.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_volume_information_values/fsntfs_test_volume_information_values.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_volume_name_attribute/fsntfs_test_volume_name_attribute.vcproj ================================================ ================================================ FILE: msvscpp/fsntfs_test_volume_name_values/fsntfs_test_volume_name_values.vcproj ================================================ ================================================ FILE: msvscpp/fsntfsinfo/fsntfsinfo.vcproj ================================================ ================================================ FILE: msvscpp/fsntfsmount/fsntfsmount.vcproj ================================================ ================================================ FILE: msvscpp/libbfio/libbfio.vcproj ================================================ ================================================ FILE: msvscpp/libcdata/libcdata.vcproj ================================================ ================================================ FILE: msvscpp/libcerror/libcerror.vcproj ================================================ ================================================ FILE: msvscpp/libcfile/libcfile.vcproj ================================================ ================================================ FILE: msvscpp/libclocale/libclocale.vcproj ================================================ ================================================ FILE: msvscpp/libcnotify/libcnotify.vcproj ================================================ ================================================ FILE: msvscpp/libcpath/libcpath.vcproj ================================================ ================================================ FILE: msvscpp/libcsplit/libcsplit.vcproj ================================================ ================================================ FILE: msvscpp/libcthreads/libcthreads.vcproj ================================================ ================================================ FILE: msvscpp/libfcache/libfcache.vcproj ================================================ ================================================ FILE: msvscpp/libfdata/libfdata.vcproj ================================================ ================================================ FILE: msvscpp/libfdatetime/libfdatetime.vcproj ================================================ ================================================ FILE: msvscpp/libfguid/libfguid.vcproj ================================================ ================================================ FILE: msvscpp/libfsntfs/libfsntfs.vcproj ================================================ ================================================ FILE: msvscpp/libfsntfs.sln ================================================  Microsoft Visual Studio Solution File, Format Version 10.00 # Visual C++ Express 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfcache", "libfcache\libfcache.vcproj", "{D46D1213-A541-465A-B75B-B5BE4DF98CDB}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} {1EF7B932-7B1D-49DA-8D58-E9CF0101C1F7} = {1EF7B932-7B1D-49DA-8D58-E9CF0101C1F7} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfguid", "libfguid\libfguid.vcproj", "{AD1E9BC6-39CA-4913-8C16-15AD16F1BA78}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_attribute", "fsntfs_test_attribute\fsntfs_test_attribute.vcproj", "{14362056-DE51-456D-A0BA-1D4C346D8DF5}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_attribute_list_entry", "fsntfs_test_attribute_list_entry\fsntfs_test_attribute_list_entry.vcproj", "{9EE2BE40-B6A0-46C9-8AE9-B2B3DE079C44}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_bitmap_values", "fsntfs_test_bitmap_values\fsntfs_test_bitmap_values.vcproj", "{5AA63F16-3E2F-4570-B618-1940C0C0A9DD}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_buffer_data_handle", "fsntfs_test_buffer_data_handle\fsntfs_test_buffer_data_handle.vcproj", "{9F4E16E9-E314-4807-B923-4E1B5DD97275}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_cluster_block", "fsntfs_test_cluster_block\fsntfs_test_cluster_block.vcproj", "{1A1FAFF8-A1FE-4D75-BB39-3913E5ED5834}" ProjectSection(ProjectDependencies) = postProject {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_cluster_block_data", "fsntfs_test_cluster_block_data\fsntfs_test_cluster_block_data.vcproj", "{DB4FE956-0D15-47B3-89B4-2049D90A9FAC}" ProjectSection(ProjectDependencies) = postProject {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_cluster_block_stream", "fsntfs_test_cluster_block_stream\fsntfs_test_cluster_block_stream.vcproj", "{7075C461-7EE0-4BBB-BE45-4CA4D58CE945}" ProjectSection(ProjectDependencies) = postProject {D9725AED-6124-4225-AC2B-306A97F90607} = {D9725AED-6124-4225-AC2B-306A97F90607} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_cluster_block_vector", "fsntfs_test_cluster_block_vector\fsntfs_test_cluster_block_vector.vcproj", "{8DC89DA4-6CA8-421D-989F-E2F3A7F220F1}" ProjectSection(ProjectDependencies) = postProject {D9725AED-6124-4225-AC2B-306A97F90607} = {D9725AED-6124-4225-AC2B-306A97F90607} {D46D1213-A541-465A-B75B-B5BE4DF98CDB} = {D46D1213-A541-465A-B75B-B5BE4DF98CDB} {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_compressed_block", "fsntfs_test_compressed_block\fsntfs_test_compressed_block.vcproj", "{86801698-77FD-435B-8E13-1648210DEB78}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_compressed_block_data_handle", "fsntfs_test_compressed_block_data_handle\fsntfs_test_compressed_block_data_handle.vcproj", "{927EAE6C-E105-4D54-9EB2-CEED9DF847EA}" ProjectSection(ProjectDependencies) = postProject {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_compressed_block_vector", "fsntfs_test_compressed_block_vector\fsntfs_test_compressed_block_vector.vcproj", "{CF9B84E8-2B48-44DF-8669-EFC0E3449277}" ProjectSection(ProjectDependencies) = postProject {D9725AED-6124-4225-AC2B-306A97F90607} = {D9725AED-6124-4225-AC2B-306A97F90607} {D46D1213-A541-465A-B75B-B5BE4DF98CDB} = {D46D1213-A541-465A-B75B-B5BE4DF98CDB} {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_compressed_data_handle", "fsntfs_test_compressed_data_handle\fsntfs_test_compressed_data_handle.vcproj", "{B54DE37F-756A-4AA6-B433-37EE73615DC8}" ProjectSection(ProjectDependencies) = postProject {D9725AED-6124-4225-AC2B-306A97F90607} = {D9725AED-6124-4225-AC2B-306A97F90607} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_compression", "fsntfs_test_compression\fsntfs_test_compression.vcproj", "{0D77DCAA-02A7-4D35-8823-96BA88A7B132}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_compression_unit_data_handle", "fsntfs_test_compression_unit_data_handle\fsntfs_test_compression_unit_data_handle.vcproj", "{5D487897-C716-451D-839D-F9822EF149F4}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_compression_unit_descriptor", "fsntfs_test_compression_unit_descriptor\fsntfs_test_compression_unit_descriptor.vcproj", "{75B4E5D6-E008-4EE6-84A7-23A9F0C6F365}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_data_run", "fsntfs_test_data_run\fsntfs_test_data_run.vcproj", "{897B0517-4405-4BE7-960B-8FD8CFC1F632}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_data_stream", "fsntfs_test_data_stream\fsntfs_test_data_stream.vcproj", "{366722BE-D632-4011-A62D-21DA660F5266}" ProjectSection(ProjectDependencies) = postProject {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_directory_entries_tree", "fsntfs_test_directory_entries_tree\fsntfs_test_directory_entries_tree.vcproj", "{5336D7B9-8E2D-4309-A78B-B82C5A9535B0}" ProjectSection(ProjectDependencies) = postProject {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_directory_entry", "fsntfs_test_directory_entry\fsntfs_test_directory_entry.vcproj", "{872A52AC-56B8-4A03-998A-E991ABBB16CD}" ProjectSection(ProjectDependencies) = postProject {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_error", "fsntfs_test_error\fsntfs_test_error.vcproj", "{E70D7EBE-951C-4C94-845E-44766CED4367}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_extent", "fsntfs_test_extent\fsntfs_test_extent.vcproj", "{CEDB7153-D51D-4A20-B268-816AC7F79D85}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_file_entry", "fsntfs_test_file_entry\fsntfs_test_file_entry.vcproj", "{2DD0CA8E-CB50-4F0C-BAD1-67041D6912CC}" ProjectSection(ProjectDependencies) = postProject {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_file_name_attribute", "fsntfs_test_file_name_attribute\fsntfs_test_file_name_attribute.vcproj", "{2BB976E5-C6A6-4EFA-9112-C11FB1088136}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_file_name_values", "fsntfs_test_file_name_values\fsntfs_test_file_name_values.vcproj", "{4E267E4B-4F7C-4031-B8A3-D023803D6822}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_file_system", "fsntfs_test_file_system\fsntfs_test_file_system.vcproj", "{F09A00EE-2E4A-4E6A-90F4-9501DAAC5262}" ProjectSection(ProjectDependencies) = postProject {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_fixup_values", "fsntfs_test_fixup_values\fsntfs_test_fixup_values.vcproj", "{8D5F07FD-41A4-4755-8BEF-E56AAD7AFD64}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_index", "fsntfs_test_index\fsntfs_test_index.vcproj", "{BA6DC222-C14D-40D2-B2EF-A99EE46CF530}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_index_entry", "fsntfs_test_index_entry\fsntfs_test_index_entry.vcproj", "{5F5EFDC4-BB68-493C-B4CB-44C82892090C}" ProjectSection(ProjectDependencies) = postProject {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_index_entry_header", "fsntfs_test_index_entry_header\fsntfs_test_index_entry_header.vcproj", "{D5B437A3-9C0B-433C-9BD6-0D3B1FA4EDDB}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_index_entry_vector", "fsntfs_test_index_entry_vector\fsntfs_test_index_entry_vector.vcproj", "{60828C47-8A89-42DA-98CB-6775272A2FDC}" ProjectSection(ProjectDependencies) = postProject {D9725AED-6124-4225-AC2B-306A97F90607} = {D9725AED-6124-4225-AC2B-306A97F90607} {D46D1213-A541-465A-B75B-B5BE4DF98CDB} = {D46D1213-A541-465A-B75B-B5BE4DF98CDB} {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_index_node", "fsntfs_test_index_node\fsntfs_test_index_node.vcproj", "{85D3991B-8695-4DC7-A7BB-E88EB1E150D1}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_index_node_header", "fsntfs_test_index_node_header\fsntfs_test_index_node_header.vcproj", "{83A76DAD-2982-4A72-84B8-A355112A4A23}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_index_root_header", "fsntfs_test_index_root_header\fsntfs_test_index_root_header.vcproj", "{E6F1AE28-F1A0-423C-8810-0B5051E27384}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_index_value", "fsntfs_test_index_value\fsntfs_test_index_value.vcproj", "{A62A34CD-C110-49D8-A4D6-9047A82856CE}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_io_handle", "fsntfs_test_io_handle\fsntfs_test_io_handle.vcproj", "{B2142A8D-EB4B-40A7-9C59-472E5F4DF792}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_logged_utility_stream_values", "fsntfs_test_logged_utility_stream_values\fsntfs_test_logged_utility_stream_values.vcproj", "{8C4AE295-DF4B-48D6-9297-C86AB0C80DE9}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_mft", "fsntfs_test_mft\fsntfs_test_mft.vcproj", "{A3F12C14-08FF-412C-806B-8258A444B134}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_mft_attribute", "fsntfs_test_mft_attribute\fsntfs_test_mft_attribute.vcproj", "{33B72873-D87D-480A-8371-3334AEE49B6C}" ProjectSection(ProjectDependencies) = postProject {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_mft_attribute_list", "fsntfs_test_mft_attribute_list\fsntfs_test_mft_attribute_list.vcproj", "{160C2657-FEEE-45BC-959F-D68E6B07F619}" ProjectSection(ProjectDependencies) = postProject {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_mft_attribute_list_entry", "fsntfs_test_mft_attribute_list_entry\fsntfs_test_mft_attribute_list_entry.vcproj", "{4D7E70CE-57AD-430F-8387-BB518D767BD2}" ProjectSection(ProjectDependencies) = postProject {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_mft_entry", "fsntfs_test_mft_entry\fsntfs_test_mft_entry.vcproj", "{59700D23-BA81-4639-8F02-3F609FAB22EF}" ProjectSection(ProjectDependencies) = postProject {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_mft_entry_header", "fsntfs_test_mft_entry_header\fsntfs_test_mft_entry_header.vcproj", "{66977E3C-C885-454C-B1D7-67A232096535}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_mft_metadata_file", "fsntfs_test_mft_metadata_file\fsntfs_test_mft_metadata_file.vcproj", "{69500ADF-371A-43DE-B73E-8A4CA34CB16C}" ProjectSection(ProjectDependencies) = postProject {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_name", "fsntfs_test_name\fsntfs_test_name.vcproj", "{A6FA8C02-6C70-455E-9B1B-0A3315BCEEBE}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_notify", "fsntfs_test_notify\fsntfs_test_notify.vcproj", "{3C380B85-EC36-457F-A07A-05C9B56AD5F6}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_object_identifier_values", "fsntfs_test_object_identifier_values\fsntfs_test_object_identifier_values.vcproj", "{38C14533-3620-463E-9476-CCB8D224DCF6}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_path_hint", "fsntfs_test_path_hint\fsntfs_test_path_hint.vcproj", "{DD6F6ABC-6000-41DA-AD17-15297A2A3E35}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_profiler", "fsntfs_test_profiler\fsntfs_test_profiler.vcproj", "{BEB36450-DEDD-4262-AC86-ACBE007581F6}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_reparse_point_attribute", "fsntfs_test_reparse_point_attribute\fsntfs_test_reparse_point_attribute.vcproj", "{3B175834-2D21-4F9A-AB77-2BB94DAB3BEC}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_reparse_point_values", "fsntfs_test_reparse_point_values\fsntfs_test_reparse_point_values.vcproj", "{D47D7B9A-C9B6-4F52-8B13-14E7FE90200E}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_sds_index_value", "fsntfs_test_sds_index_value\fsntfs_test_sds_index_value.vcproj", "{0C5B426F-5F01-4A7F-8FE3-A372CE67F02A}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_security_descriptor_index", "fsntfs_test_security_descriptor_index\fsntfs_test_security_descriptor_index.vcproj", "{AF956C6B-4E27-487E-B795-7F8503A4B5AB}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_security_descriptor_index_value", "fsntfs_test_security_descriptor_index_value\fsntfs_test_security_descriptor_index_value.vcproj", "{B6B3A52D-BD01-4831-8F40-080721E5F3B8}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_security_descriptor_values", "fsntfs_test_security_descriptor_values\fsntfs_test_security_descriptor_values.vcproj", "{23AA7603-07B4-42EF-9535-8BA4C156504E}" ProjectSection(ProjectDependencies) = postProject {D9725AED-6124-4225-AC2B-306A97F90607} = {D9725AED-6124-4225-AC2B-306A97F90607} {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_standard_information_values", "fsntfs_test_standard_information_values\fsntfs_test_standard_information_values.vcproj", "{18FA643E-04FF-49E0-BAF4-EAFDA60A492E}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_support", "fsntfs_test_support\fsntfs_test_support.vcproj", "{A3CAA91B-F202-4B5E-B11B-367E05C097DC}" ProjectSection(ProjectDependencies) = postProject {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_tools_bodyfile", "fsntfs_test_tools_bodyfile\fsntfs_test_tools_bodyfile.vcproj", "{92D81AA9-3090-4B66-966F-EE4CAA062A18}" ProjectSection(ProjectDependencies) = postProject {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_tools_digest_hash", "fsntfs_test_tools_digest_hash\fsntfs_test_tools_digest_hash.vcproj", "{9BA6CBAE-1B19-41BE-9E46-0824CCD932E3}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_tools_info_handle", "fsntfs_test_tools_info_handle\fsntfs_test_tools_info_handle.vcproj", "{60D0DC49-FB23-4356-B93B-3083D6C7870F}" ProjectSection(ProjectDependencies) = postProject {6BA13A4B-8361-474A-8055-3A9F2437C3AC} = {6BA13A4B-8361-474A-8055-3A9F2437C3AC} {1860A9F0-4E82-4808-B6F0-59625D118021} = {1860A9F0-4E82-4808-B6F0-59625D118021} {CEE2C1FC-7AB1-4833-8AFC-8E0AD60CDCC9} = {CEE2C1FC-7AB1-4833-8AFC-8E0AD60CDCC9} {AD1E9BC6-39CA-4913-8C16-15AD16F1BA78} = {AD1E9BC6-39CA-4913-8C16-15AD16F1BA78} {A95C47C2-8CFA-4BBB-BD66-3B198323B409} = {A95C47C2-8CFA-4BBB-BD66-3B198323B409} {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_tools_mount_path_string", "fsntfs_test_tools_mount_path_string\fsntfs_test_tools_mount_path_string.vcproj", "{3F48737B-A8D7-418A-A448-40AFBAEA1733}" ProjectSection(ProjectDependencies) = postProject {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_tools_output", "fsntfs_test_tools_output\fsntfs_test_tools_output.vcproj", "{71D59C5D-6E61-4132-B33D-F52524422CB1}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_tools_path_string", "fsntfs_test_tools_path_string\fsntfs_test_tools_path_string.vcproj", "{DCDE74CC-6ABD-4F0B-9289-C4B19ADA76E4}" ProjectSection(ProjectDependencies) = postProject {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_tools_signal", "fsntfs_test_tools_signal\fsntfs_test_tools_signal.vcproj", "{DC6AD8F6-542A-48AC-8960-E62927C907FB}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_txf_data_values", "fsntfs_test_txf_data_values\fsntfs_test_txf_data_values.vcproj", "{1AFF43D1-88C8-44B6-A391-3CAA10B9E9CC}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_usn_change_journal", "fsntfs_test_usn_change_journal\fsntfs_test_usn_change_journal.vcproj", "{F2BB99F7-6BAB-4DC2-AF69-FCA14F085A9F}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_volume", "fsntfs_test_volume\fsntfs_test_volume.vcproj", "{B15D7487-46E8-4134-B095-DC601DD7F6C5}" ProjectSection(ProjectDependencies) = postProject {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_volume_header", "fsntfs_test_volume_header\fsntfs_test_volume_header.vcproj", "{568C781B-991A-4713-B035-C15BA84C13D1}" ProjectSection(ProjectDependencies) = postProject {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_volume_information_attribute", "fsntfs_test_volume_information_attribute\fsntfs_test_volume_information_attribute.vcproj", "{6F12D839-A7B1-4BEB-B249-B48BD7D374C7}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_volume_information_values", "fsntfs_test_volume_information_values\fsntfs_test_volume_information_values.vcproj", "{04F1B6AF-0358-4FD2-88F9-E609356E7097}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_volume_name_attribute", "fsntfs_test_volume_name_attribute\fsntfs_test_volume_name_attribute.vcproj", "{C5627F45-9745-4015-9E82-4CC28EE7278B}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfs_test_volume_name_values", "fsntfs_test_volume_name_values\fsntfs_test_volume_name_values.vcproj", "{3992C7C8-F4C6-4BAD-96FA-ED93C00BE24A}" ProjectSection(ProjectDependencies) = postProject {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libclocale", "libclocale\libclocale.vcproj", "{F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libbfio", "libbfio\libbfio.vcproj", "{B3CAA0DA-B778-4B69-8537-3AF7F9984F51}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} {1EF7B932-7B1D-49DA-8D58-E9CF0101C1F7} = {1EF7B932-7B1D-49DA-8D58-E9CF0101C1F7} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfsinfo", "fsntfsinfo\fsntfsinfo.vcproj", "{856D95C9-F063-4613-B8E2-ECB6FC9AB6D3}" ProjectSection(ProjectDependencies) = postProject {6BA13A4B-8361-474A-8055-3A9F2437C3AC} = {6BA13A4B-8361-474A-8055-3A9F2437C3AC} {1860A9F0-4E82-4808-B6F0-59625D118021} = {1860A9F0-4E82-4808-B6F0-59625D118021} {CEE2C1FC-7AB1-4833-8AFC-8E0AD60CDCC9} = {CEE2C1FC-7AB1-4833-8AFC-8E0AD60CDCC9} {AD1E9BC6-39CA-4913-8C16-15AD16F1BA78} = {AD1E9BC6-39CA-4913-8C16-15AD16F1BA78} {A95C47C2-8CFA-4BBB-BD66-3B198323B409} = {A95C47C2-8CFA-4BBB-BD66-3B198323B409} {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fsntfsmount", "fsntfsmount\fsntfsmount.vcproj", "{48BE6463-9726-40DA-AF2A-7F9E590C4B20}" ProjectSection(ProjectDependencies) = postProject {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfsntfs", "libfsntfs\libfsntfs.vcproj", "{D1CA56F0-00C0-4E8C-BD6F-8A15619A954D}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} {1EF7B932-7B1D-49DA-8D58-E9CF0101C1F7} = {1EF7B932-7B1D-49DA-8D58-E9CF0101C1F7} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {D46D1213-A541-465A-B75B-B5BE4DF98CDB} = {D46D1213-A541-465A-B75B-B5BE4DF98CDB} {D9725AED-6124-4225-AC2B-306A97F90607} = {D9725AED-6124-4225-AC2B-306A97F90607} {A95C47C2-8CFA-4BBB-BD66-3B198323B409} = {A95C47C2-8CFA-4BBB-BD66-3B198323B409} {AD1E9BC6-39CA-4913-8C16-15AD16F1BA78} = {AD1E9BC6-39CA-4913-8C16-15AD16F1BA78} {1860A9F0-4E82-4808-B6F0-59625D118021} = {1860A9F0-4E82-4808-B6F0-59625D118021} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfdatetime", "libfdatetime\libfdatetime.vcproj", "{A95C47C2-8CFA-4BBB-BD66-3B198323B409}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcfile", "libcfile\libcfile.vcproj", "{9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfwnt", "libfwnt\libfwnt.vcproj", "{1860A9F0-4E82-4808-B6F0-59625D118021}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} {1EF7B932-7B1D-49DA-8D58-E9CF0101C1F7} = {1EF7B932-7B1D-49DA-8D58-E9CF0101C1F7} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcthreads", "libcthreads\libcthreads.vcproj", "{1EF7B932-7B1D-49DA-8D58-E9CF0101C1F7}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pyfsntfs", "pyfsntfs\pyfsntfs.vcproj", "{7EC7E241-8C9E-40DC-8BF5-78FC90CEA990}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} = {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} = {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2} {5C1834B6-0BA9-4541-8770-D65A78F33958} = {5C1834B6-0BA9-4541-8770-D65A78F33958} {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} = {B3CAA0DA-B778-4B69-8537-3AF7F9984F51} {AD1E9BC6-39CA-4913-8C16-15AD16F1BA78} = {AD1E9BC6-39CA-4913-8C16-15AD16F1BA78} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcpath", "libcpath\libcpath.vcproj", "{5C1834B6-0BA9-4541-8770-D65A78F33958}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} = {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395} {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} = {9D9A7FB3-B049-4E4C-835A-D2516DC2F076} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfusn", "libfusn\libfusn.vcproj", "{CEE2C1FC-7AB1-4833-8AFC-8E0AD60CDCC9}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} = {8447CA5B-9D12-4DF0-B225-A25F4B288D2D} {A95C47C2-8CFA-4BBB-BD66-3B198323B409} = {A95C47C2-8CFA-4BBB-BD66-3B198323B409} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhmac", "libhmac\libhmac.vcproj", "{6BA13A4B-8361-474A-8055-3A9F2437C3AC}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libuna", "libuna\libuna.vcproj", "{8447CA5B-9D12-4DF0-B225-A25F4B288D2D}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcerror", "libcerror\libcerror.vcproj", "{4C79D798-FB54-4CD5-9067-9BDC8678478A}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcnotify", "libcnotify\libcnotify.vcproj", "{5641B37B-7AE7-450A-A433-7B83C73BC878}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfdata", "libfdata\libfdata.vcproj", "{D9725AED-6124-4225-AC2B-306A97F90607}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} {1EF7B932-7B1D-49DA-8D58-E9CF0101C1F7} = {1EF7B932-7B1D-49DA-8D58-E9CF0101C1F7} {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} = {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5} {5641B37B-7AE7-450A-A433-7B83C73BC878} = {5641B37B-7AE7-450A-A433-7B83C73BC878} {D46D1213-A541-465A-B75B-B5BE4DF98CDB} = {D46D1213-A541-465A-B75B-B5BE4DF98CDB} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcdata", "libcdata\libcdata.vcproj", "{F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} {1EF7B932-7B1D-49DA-8D58-E9CF0101C1F7} = {1EF7B932-7B1D-49DA-8D58-E9CF0101C1F7} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcsplit", "libcsplit\libcsplit.vcproj", "{9D9A7FB3-B049-4E4C-835A-D2516DC2F076}" ProjectSection(ProjectDependencies) = postProject {4C79D798-FB54-4CD5-9067-9BDC8678478A} = {4C79D798-FB54-4CD5-9067-9BDC8678478A} EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Release|Win32 = Release|Win32 VSDebug|Win32 = VSDebug|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {D46D1213-A541-465A-B75B-B5BE4DF98CDB}.Release|Win32.ActiveCfg = Release|Win32 {D46D1213-A541-465A-B75B-B5BE4DF98CDB}.Release|Win32.Build.0 = Release|Win32 {D46D1213-A541-465A-B75B-B5BE4DF98CDB}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {D46D1213-A541-465A-B75B-B5BE4DF98CDB}.VSDebug|Win32.Build.0 = VSDebug|Win32 {AD1E9BC6-39CA-4913-8C16-15AD16F1BA78}.Release|Win32.ActiveCfg = Release|Win32 {AD1E9BC6-39CA-4913-8C16-15AD16F1BA78}.Release|Win32.Build.0 = Release|Win32 {AD1E9BC6-39CA-4913-8C16-15AD16F1BA78}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {AD1E9BC6-39CA-4913-8C16-15AD16F1BA78}.VSDebug|Win32.Build.0 = VSDebug|Win32 {14362056-DE51-456D-A0BA-1D4C346D8DF5}.Release|Win32.ActiveCfg = Release|Win32 {14362056-DE51-456D-A0BA-1D4C346D8DF5}.Release|Win32.Build.0 = Release|Win32 {14362056-DE51-456D-A0BA-1D4C346D8DF5}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {14362056-DE51-456D-A0BA-1D4C346D8DF5}.VSDebug|Win32.Build.0 = VSDebug|Win32 {9EE2BE40-B6A0-46C9-8AE9-B2B3DE079C44}.Release|Win32.ActiveCfg = Release|Win32 {9EE2BE40-B6A0-46C9-8AE9-B2B3DE079C44}.Release|Win32.Build.0 = Release|Win32 {9EE2BE40-B6A0-46C9-8AE9-B2B3DE079C44}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {9EE2BE40-B6A0-46C9-8AE9-B2B3DE079C44}.VSDebug|Win32.Build.0 = VSDebug|Win32 {5AA63F16-3E2F-4570-B618-1940C0C0A9DD}.Release|Win32.ActiveCfg = Release|Win32 {5AA63F16-3E2F-4570-B618-1940C0C0A9DD}.Release|Win32.Build.0 = Release|Win32 {5AA63F16-3E2F-4570-B618-1940C0C0A9DD}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {5AA63F16-3E2F-4570-B618-1940C0C0A9DD}.VSDebug|Win32.Build.0 = VSDebug|Win32 {9F4E16E9-E314-4807-B923-4E1B5DD97275}.Release|Win32.ActiveCfg = Release|Win32 {9F4E16E9-E314-4807-B923-4E1B5DD97275}.Release|Win32.Build.0 = Release|Win32 {9F4E16E9-E314-4807-B923-4E1B5DD97275}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {9F4E16E9-E314-4807-B923-4E1B5DD97275}.VSDebug|Win32.Build.0 = VSDebug|Win32 {1A1FAFF8-A1FE-4D75-BB39-3913E5ED5834}.Release|Win32.ActiveCfg = Release|Win32 {1A1FAFF8-A1FE-4D75-BB39-3913E5ED5834}.Release|Win32.Build.0 = Release|Win32 {1A1FAFF8-A1FE-4D75-BB39-3913E5ED5834}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {1A1FAFF8-A1FE-4D75-BB39-3913E5ED5834}.VSDebug|Win32.Build.0 = VSDebug|Win32 {DB4FE956-0D15-47B3-89B4-2049D90A9FAC}.Release|Win32.ActiveCfg = Release|Win32 {DB4FE956-0D15-47B3-89B4-2049D90A9FAC}.Release|Win32.Build.0 = Release|Win32 {DB4FE956-0D15-47B3-89B4-2049D90A9FAC}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {DB4FE956-0D15-47B3-89B4-2049D90A9FAC}.VSDebug|Win32.Build.0 = VSDebug|Win32 {7075C461-7EE0-4BBB-BE45-4CA4D58CE945}.Release|Win32.ActiveCfg = Release|Win32 {7075C461-7EE0-4BBB-BE45-4CA4D58CE945}.Release|Win32.Build.0 = Release|Win32 {7075C461-7EE0-4BBB-BE45-4CA4D58CE945}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {7075C461-7EE0-4BBB-BE45-4CA4D58CE945}.VSDebug|Win32.Build.0 = VSDebug|Win32 {8DC89DA4-6CA8-421D-989F-E2F3A7F220F1}.Release|Win32.ActiveCfg = Release|Win32 {8DC89DA4-6CA8-421D-989F-E2F3A7F220F1}.Release|Win32.Build.0 = Release|Win32 {8DC89DA4-6CA8-421D-989F-E2F3A7F220F1}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {8DC89DA4-6CA8-421D-989F-E2F3A7F220F1}.VSDebug|Win32.Build.0 = VSDebug|Win32 {86801698-77FD-435B-8E13-1648210DEB78}.Release|Win32.ActiveCfg = Release|Win32 {86801698-77FD-435B-8E13-1648210DEB78}.Release|Win32.Build.0 = Release|Win32 {86801698-77FD-435B-8E13-1648210DEB78}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {86801698-77FD-435B-8E13-1648210DEB78}.VSDebug|Win32.Build.0 = VSDebug|Win32 {927EAE6C-E105-4D54-9EB2-CEED9DF847EA}.Release|Win32.ActiveCfg = Release|Win32 {927EAE6C-E105-4D54-9EB2-CEED9DF847EA}.Release|Win32.Build.0 = Release|Win32 {927EAE6C-E105-4D54-9EB2-CEED9DF847EA}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {927EAE6C-E105-4D54-9EB2-CEED9DF847EA}.VSDebug|Win32.Build.0 = VSDebug|Win32 {CF9B84E8-2B48-44DF-8669-EFC0E3449277}.Release|Win32.ActiveCfg = Release|Win32 {CF9B84E8-2B48-44DF-8669-EFC0E3449277}.Release|Win32.Build.0 = Release|Win32 {CF9B84E8-2B48-44DF-8669-EFC0E3449277}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {CF9B84E8-2B48-44DF-8669-EFC0E3449277}.VSDebug|Win32.Build.0 = VSDebug|Win32 {B54DE37F-756A-4AA6-B433-37EE73615DC8}.Release|Win32.ActiveCfg = Release|Win32 {B54DE37F-756A-4AA6-B433-37EE73615DC8}.Release|Win32.Build.0 = Release|Win32 {B54DE37F-756A-4AA6-B433-37EE73615DC8}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {B54DE37F-756A-4AA6-B433-37EE73615DC8}.VSDebug|Win32.Build.0 = VSDebug|Win32 {0D77DCAA-02A7-4D35-8823-96BA88A7B132}.Release|Win32.ActiveCfg = Release|Win32 {0D77DCAA-02A7-4D35-8823-96BA88A7B132}.Release|Win32.Build.0 = Release|Win32 {0D77DCAA-02A7-4D35-8823-96BA88A7B132}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {0D77DCAA-02A7-4D35-8823-96BA88A7B132}.VSDebug|Win32.Build.0 = VSDebug|Win32 {5D487897-C716-451D-839D-F9822EF149F4}.Release|Win32.ActiveCfg = Release|Win32 {5D487897-C716-451D-839D-F9822EF149F4}.Release|Win32.Build.0 = Release|Win32 {5D487897-C716-451D-839D-F9822EF149F4}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {5D487897-C716-451D-839D-F9822EF149F4}.VSDebug|Win32.Build.0 = VSDebug|Win32 {75B4E5D6-E008-4EE6-84A7-23A9F0C6F365}.Release|Win32.ActiveCfg = Release|Win32 {75B4E5D6-E008-4EE6-84A7-23A9F0C6F365}.Release|Win32.Build.0 = Release|Win32 {75B4E5D6-E008-4EE6-84A7-23A9F0C6F365}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {75B4E5D6-E008-4EE6-84A7-23A9F0C6F365}.VSDebug|Win32.Build.0 = VSDebug|Win32 {897B0517-4405-4BE7-960B-8FD8CFC1F632}.Release|Win32.ActiveCfg = Release|Win32 {897B0517-4405-4BE7-960B-8FD8CFC1F632}.Release|Win32.Build.0 = Release|Win32 {897B0517-4405-4BE7-960B-8FD8CFC1F632}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {897B0517-4405-4BE7-960B-8FD8CFC1F632}.VSDebug|Win32.Build.0 = VSDebug|Win32 {366722BE-D632-4011-A62D-21DA660F5266}.Release|Win32.ActiveCfg = Release|Win32 {366722BE-D632-4011-A62D-21DA660F5266}.Release|Win32.Build.0 = Release|Win32 {366722BE-D632-4011-A62D-21DA660F5266}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {366722BE-D632-4011-A62D-21DA660F5266}.VSDebug|Win32.Build.0 = VSDebug|Win32 {5336D7B9-8E2D-4309-A78B-B82C5A9535B0}.Release|Win32.ActiveCfg = Release|Win32 {5336D7B9-8E2D-4309-A78B-B82C5A9535B0}.Release|Win32.Build.0 = Release|Win32 {5336D7B9-8E2D-4309-A78B-B82C5A9535B0}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {5336D7B9-8E2D-4309-A78B-B82C5A9535B0}.VSDebug|Win32.Build.0 = VSDebug|Win32 {872A52AC-56B8-4A03-998A-E991ABBB16CD}.Release|Win32.ActiveCfg = Release|Win32 {872A52AC-56B8-4A03-998A-E991ABBB16CD}.Release|Win32.Build.0 = Release|Win32 {872A52AC-56B8-4A03-998A-E991ABBB16CD}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {872A52AC-56B8-4A03-998A-E991ABBB16CD}.VSDebug|Win32.Build.0 = VSDebug|Win32 {E70D7EBE-951C-4C94-845E-44766CED4367}.Release|Win32.ActiveCfg = Release|Win32 {E70D7EBE-951C-4C94-845E-44766CED4367}.Release|Win32.Build.0 = Release|Win32 {E70D7EBE-951C-4C94-845E-44766CED4367}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {E70D7EBE-951C-4C94-845E-44766CED4367}.VSDebug|Win32.Build.0 = VSDebug|Win32 {CEDB7153-D51D-4A20-B268-816AC7F79D85}.Release|Win32.ActiveCfg = Release|Win32 {CEDB7153-D51D-4A20-B268-816AC7F79D85}.Release|Win32.Build.0 = Release|Win32 {CEDB7153-D51D-4A20-B268-816AC7F79D85}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {CEDB7153-D51D-4A20-B268-816AC7F79D85}.VSDebug|Win32.Build.0 = VSDebug|Win32 {2DD0CA8E-CB50-4F0C-BAD1-67041D6912CC}.Release|Win32.ActiveCfg = Release|Win32 {2DD0CA8E-CB50-4F0C-BAD1-67041D6912CC}.Release|Win32.Build.0 = Release|Win32 {2DD0CA8E-CB50-4F0C-BAD1-67041D6912CC}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {2DD0CA8E-CB50-4F0C-BAD1-67041D6912CC}.VSDebug|Win32.Build.0 = VSDebug|Win32 {2BB976E5-C6A6-4EFA-9112-C11FB1088136}.Release|Win32.ActiveCfg = Release|Win32 {2BB976E5-C6A6-4EFA-9112-C11FB1088136}.Release|Win32.Build.0 = Release|Win32 {2BB976E5-C6A6-4EFA-9112-C11FB1088136}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {2BB976E5-C6A6-4EFA-9112-C11FB1088136}.VSDebug|Win32.Build.0 = VSDebug|Win32 {4E267E4B-4F7C-4031-B8A3-D023803D6822}.Release|Win32.ActiveCfg = Release|Win32 {4E267E4B-4F7C-4031-B8A3-D023803D6822}.Release|Win32.Build.0 = Release|Win32 {4E267E4B-4F7C-4031-B8A3-D023803D6822}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {4E267E4B-4F7C-4031-B8A3-D023803D6822}.VSDebug|Win32.Build.0 = VSDebug|Win32 {F09A00EE-2E4A-4E6A-90F4-9501DAAC5262}.Release|Win32.ActiveCfg = Release|Win32 {F09A00EE-2E4A-4E6A-90F4-9501DAAC5262}.Release|Win32.Build.0 = Release|Win32 {F09A00EE-2E4A-4E6A-90F4-9501DAAC5262}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {F09A00EE-2E4A-4E6A-90F4-9501DAAC5262}.VSDebug|Win32.Build.0 = VSDebug|Win32 {8D5F07FD-41A4-4755-8BEF-E56AAD7AFD64}.Release|Win32.ActiveCfg = Release|Win32 {8D5F07FD-41A4-4755-8BEF-E56AAD7AFD64}.Release|Win32.Build.0 = Release|Win32 {8D5F07FD-41A4-4755-8BEF-E56AAD7AFD64}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {8D5F07FD-41A4-4755-8BEF-E56AAD7AFD64}.VSDebug|Win32.Build.0 = VSDebug|Win32 {BA6DC222-C14D-40D2-B2EF-A99EE46CF530}.Release|Win32.ActiveCfg = Release|Win32 {BA6DC222-C14D-40D2-B2EF-A99EE46CF530}.Release|Win32.Build.0 = Release|Win32 {BA6DC222-C14D-40D2-B2EF-A99EE46CF530}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {BA6DC222-C14D-40D2-B2EF-A99EE46CF530}.VSDebug|Win32.Build.0 = VSDebug|Win32 {5F5EFDC4-BB68-493C-B4CB-44C82892090C}.Release|Win32.ActiveCfg = Release|Win32 {5F5EFDC4-BB68-493C-B4CB-44C82892090C}.Release|Win32.Build.0 = Release|Win32 {5F5EFDC4-BB68-493C-B4CB-44C82892090C}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {5F5EFDC4-BB68-493C-B4CB-44C82892090C}.VSDebug|Win32.Build.0 = VSDebug|Win32 {D5B437A3-9C0B-433C-9BD6-0D3B1FA4EDDB}.Release|Win32.ActiveCfg = Release|Win32 {D5B437A3-9C0B-433C-9BD6-0D3B1FA4EDDB}.Release|Win32.Build.0 = Release|Win32 {D5B437A3-9C0B-433C-9BD6-0D3B1FA4EDDB}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {D5B437A3-9C0B-433C-9BD6-0D3B1FA4EDDB}.VSDebug|Win32.Build.0 = VSDebug|Win32 {60828C47-8A89-42DA-98CB-6775272A2FDC}.Release|Win32.ActiveCfg = Release|Win32 {60828C47-8A89-42DA-98CB-6775272A2FDC}.Release|Win32.Build.0 = Release|Win32 {60828C47-8A89-42DA-98CB-6775272A2FDC}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {60828C47-8A89-42DA-98CB-6775272A2FDC}.VSDebug|Win32.Build.0 = VSDebug|Win32 {85D3991B-8695-4DC7-A7BB-E88EB1E150D1}.Release|Win32.ActiveCfg = Release|Win32 {85D3991B-8695-4DC7-A7BB-E88EB1E150D1}.Release|Win32.Build.0 = Release|Win32 {85D3991B-8695-4DC7-A7BB-E88EB1E150D1}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {85D3991B-8695-4DC7-A7BB-E88EB1E150D1}.VSDebug|Win32.Build.0 = VSDebug|Win32 {83A76DAD-2982-4A72-84B8-A355112A4A23}.Release|Win32.ActiveCfg = Release|Win32 {83A76DAD-2982-4A72-84B8-A355112A4A23}.Release|Win32.Build.0 = Release|Win32 {83A76DAD-2982-4A72-84B8-A355112A4A23}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {83A76DAD-2982-4A72-84B8-A355112A4A23}.VSDebug|Win32.Build.0 = VSDebug|Win32 {E6F1AE28-F1A0-423C-8810-0B5051E27384}.Release|Win32.ActiveCfg = Release|Win32 {E6F1AE28-F1A0-423C-8810-0B5051E27384}.Release|Win32.Build.0 = Release|Win32 {E6F1AE28-F1A0-423C-8810-0B5051E27384}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {E6F1AE28-F1A0-423C-8810-0B5051E27384}.VSDebug|Win32.Build.0 = VSDebug|Win32 {A62A34CD-C110-49D8-A4D6-9047A82856CE}.Release|Win32.ActiveCfg = Release|Win32 {A62A34CD-C110-49D8-A4D6-9047A82856CE}.Release|Win32.Build.0 = Release|Win32 {A62A34CD-C110-49D8-A4D6-9047A82856CE}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {A62A34CD-C110-49D8-A4D6-9047A82856CE}.VSDebug|Win32.Build.0 = VSDebug|Win32 {B2142A8D-EB4B-40A7-9C59-472E5F4DF792}.Release|Win32.ActiveCfg = Release|Win32 {B2142A8D-EB4B-40A7-9C59-472E5F4DF792}.Release|Win32.Build.0 = Release|Win32 {B2142A8D-EB4B-40A7-9C59-472E5F4DF792}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {B2142A8D-EB4B-40A7-9C59-472E5F4DF792}.VSDebug|Win32.Build.0 = VSDebug|Win32 {8C4AE295-DF4B-48D6-9297-C86AB0C80DE9}.Release|Win32.ActiveCfg = Release|Win32 {8C4AE295-DF4B-48D6-9297-C86AB0C80DE9}.Release|Win32.Build.0 = Release|Win32 {8C4AE295-DF4B-48D6-9297-C86AB0C80DE9}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {8C4AE295-DF4B-48D6-9297-C86AB0C80DE9}.VSDebug|Win32.Build.0 = VSDebug|Win32 {A3F12C14-08FF-412C-806B-8258A444B134}.Release|Win32.ActiveCfg = Release|Win32 {A3F12C14-08FF-412C-806B-8258A444B134}.Release|Win32.Build.0 = Release|Win32 {A3F12C14-08FF-412C-806B-8258A444B134}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {A3F12C14-08FF-412C-806B-8258A444B134}.VSDebug|Win32.Build.0 = VSDebug|Win32 {33B72873-D87D-480A-8371-3334AEE49B6C}.Release|Win32.ActiveCfg = Release|Win32 {33B72873-D87D-480A-8371-3334AEE49B6C}.Release|Win32.Build.0 = Release|Win32 {33B72873-D87D-480A-8371-3334AEE49B6C}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {33B72873-D87D-480A-8371-3334AEE49B6C}.VSDebug|Win32.Build.0 = VSDebug|Win32 {160C2657-FEEE-45BC-959F-D68E6B07F619}.Release|Win32.ActiveCfg = Release|Win32 {160C2657-FEEE-45BC-959F-D68E6B07F619}.Release|Win32.Build.0 = Release|Win32 {160C2657-FEEE-45BC-959F-D68E6B07F619}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {160C2657-FEEE-45BC-959F-D68E6B07F619}.VSDebug|Win32.Build.0 = VSDebug|Win32 {4D7E70CE-57AD-430F-8387-BB518D767BD2}.Release|Win32.ActiveCfg = Release|Win32 {4D7E70CE-57AD-430F-8387-BB518D767BD2}.Release|Win32.Build.0 = Release|Win32 {4D7E70CE-57AD-430F-8387-BB518D767BD2}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {4D7E70CE-57AD-430F-8387-BB518D767BD2}.VSDebug|Win32.Build.0 = VSDebug|Win32 {59700D23-BA81-4639-8F02-3F609FAB22EF}.Release|Win32.ActiveCfg = Release|Win32 {59700D23-BA81-4639-8F02-3F609FAB22EF}.Release|Win32.Build.0 = Release|Win32 {59700D23-BA81-4639-8F02-3F609FAB22EF}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {59700D23-BA81-4639-8F02-3F609FAB22EF}.VSDebug|Win32.Build.0 = VSDebug|Win32 {66977E3C-C885-454C-B1D7-67A232096535}.Release|Win32.ActiveCfg = Release|Win32 {66977E3C-C885-454C-B1D7-67A232096535}.Release|Win32.Build.0 = Release|Win32 {66977E3C-C885-454C-B1D7-67A232096535}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {66977E3C-C885-454C-B1D7-67A232096535}.VSDebug|Win32.Build.0 = VSDebug|Win32 {69500ADF-371A-43DE-B73E-8A4CA34CB16C}.Release|Win32.ActiveCfg = Release|Win32 {69500ADF-371A-43DE-B73E-8A4CA34CB16C}.Release|Win32.Build.0 = Release|Win32 {69500ADF-371A-43DE-B73E-8A4CA34CB16C}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {69500ADF-371A-43DE-B73E-8A4CA34CB16C}.VSDebug|Win32.Build.0 = VSDebug|Win32 {A6FA8C02-6C70-455E-9B1B-0A3315BCEEBE}.Release|Win32.ActiveCfg = Release|Win32 {A6FA8C02-6C70-455E-9B1B-0A3315BCEEBE}.Release|Win32.Build.0 = Release|Win32 {A6FA8C02-6C70-455E-9B1B-0A3315BCEEBE}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {A6FA8C02-6C70-455E-9B1B-0A3315BCEEBE}.VSDebug|Win32.Build.0 = VSDebug|Win32 {3C380B85-EC36-457F-A07A-05C9B56AD5F6}.Release|Win32.ActiveCfg = Release|Win32 {3C380B85-EC36-457F-A07A-05C9B56AD5F6}.Release|Win32.Build.0 = Release|Win32 {3C380B85-EC36-457F-A07A-05C9B56AD5F6}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {3C380B85-EC36-457F-A07A-05C9B56AD5F6}.VSDebug|Win32.Build.0 = VSDebug|Win32 {38C14533-3620-463E-9476-CCB8D224DCF6}.Release|Win32.ActiveCfg = Release|Win32 {38C14533-3620-463E-9476-CCB8D224DCF6}.Release|Win32.Build.0 = Release|Win32 {38C14533-3620-463E-9476-CCB8D224DCF6}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {38C14533-3620-463E-9476-CCB8D224DCF6}.VSDebug|Win32.Build.0 = VSDebug|Win32 {DD6F6ABC-6000-41DA-AD17-15297A2A3E35}.Release|Win32.ActiveCfg = Release|Win32 {DD6F6ABC-6000-41DA-AD17-15297A2A3E35}.Release|Win32.Build.0 = Release|Win32 {DD6F6ABC-6000-41DA-AD17-15297A2A3E35}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {DD6F6ABC-6000-41DA-AD17-15297A2A3E35}.VSDebug|Win32.Build.0 = VSDebug|Win32 {BEB36450-DEDD-4262-AC86-ACBE007581F6}.Release|Win32.ActiveCfg = Release|Win32 {BEB36450-DEDD-4262-AC86-ACBE007581F6}.Release|Win32.Build.0 = Release|Win32 {BEB36450-DEDD-4262-AC86-ACBE007581F6}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {BEB36450-DEDD-4262-AC86-ACBE007581F6}.VSDebug|Win32.Build.0 = VSDebug|Win32 {3B175834-2D21-4F9A-AB77-2BB94DAB3BEC}.Release|Win32.ActiveCfg = Release|Win32 {3B175834-2D21-4F9A-AB77-2BB94DAB3BEC}.Release|Win32.Build.0 = Release|Win32 {3B175834-2D21-4F9A-AB77-2BB94DAB3BEC}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {3B175834-2D21-4F9A-AB77-2BB94DAB3BEC}.VSDebug|Win32.Build.0 = VSDebug|Win32 {D47D7B9A-C9B6-4F52-8B13-14E7FE90200E}.Release|Win32.ActiveCfg = Release|Win32 {D47D7B9A-C9B6-4F52-8B13-14E7FE90200E}.Release|Win32.Build.0 = Release|Win32 {D47D7B9A-C9B6-4F52-8B13-14E7FE90200E}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {D47D7B9A-C9B6-4F52-8B13-14E7FE90200E}.VSDebug|Win32.Build.0 = VSDebug|Win32 {0C5B426F-5F01-4A7F-8FE3-A372CE67F02A}.Release|Win32.ActiveCfg = Release|Win32 {0C5B426F-5F01-4A7F-8FE3-A372CE67F02A}.Release|Win32.Build.0 = Release|Win32 {0C5B426F-5F01-4A7F-8FE3-A372CE67F02A}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {0C5B426F-5F01-4A7F-8FE3-A372CE67F02A}.VSDebug|Win32.Build.0 = VSDebug|Win32 {AF956C6B-4E27-487E-B795-7F8503A4B5AB}.Release|Win32.ActiveCfg = Release|Win32 {AF956C6B-4E27-487E-B795-7F8503A4B5AB}.Release|Win32.Build.0 = Release|Win32 {AF956C6B-4E27-487E-B795-7F8503A4B5AB}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {AF956C6B-4E27-487E-B795-7F8503A4B5AB}.VSDebug|Win32.Build.0 = VSDebug|Win32 {B6B3A52D-BD01-4831-8F40-080721E5F3B8}.Release|Win32.ActiveCfg = Release|Win32 {B6B3A52D-BD01-4831-8F40-080721E5F3B8}.Release|Win32.Build.0 = Release|Win32 {B6B3A52D-BD01-4831-8F40-080721E5F3B8}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {B6B3A52D-BD01-4831-8F40-080721E5F3B8}.VSDebug|Win32.Build.0 = VSDebug|Win32 {23AA7603-07B4-42EF-9535-8BA4C156504E}.Release|Win32.ActiveCfg = Release|Win32 {23AA7603-07B4-42EF-9535-8BA4C156504E}.Release|Win32.Build.0 = Release|Win32 {23AA7603-07B4-42EF-9535-8BA4C156504E}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {23AA7603-07B4-42EF-9535-8BA4C156504E}.VSDebug|Win32.Build.0 = VSDebug|Win32 {18FA643E-04FF-49E0-BAF4-EAFDA60A492E}.Release|Win32.ActiveCfg = Release|Win32 {18FA643E-04FF-49E0-BAF4-EAFDA60A492E}.Release|Win32.Build.0 = Release|Win32 {18FA643E-04FF-49E0-BAF4-EAFDA60A492E}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {18FA643E-04FF-49E0-BAF4-EAFDA60A492E}.VSDebug|Win32.Build.0 = VSDebug|Win32 {A3CAA91B-F202-4B5E-B11B-367E05C097DC}.Release|Win32.ActiveCfg = Release|Win32 {A3CAA91B-F202-4B5E-B11B-367E05C097DC}.Release|Win32.Build.0 = Release|Win32 {A3CAA91B-F202-4B5E-B11B-367E05C097DC}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {A3CAA91B-F202-4B5E-B11B-367E05C097DC}.VSDebug|Win32.Build.0 = VSDebug|Win32 {92D81AA9-3090-4B66-966F-EE4CAA062A18}.Release|Win32.ActiveCfg = Release|Win32 {92D81AA9-3090-4B66-966F-EE4CAA062A18}.Release|Win32.Build.0 = Release|Win32 {92D81AA9-3090-4B66-966F-EE4CAA062A18}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {92D81AA9-3090-4B66-966F-EE4CAA062A18}.VSDebug|Win32.Build.0 = VSDebug|Win32 {9BA6CBAE-1B19-41BE-9E46-0824CCD932E3}.Release|Win32.ActiveCfg = Release|Win32 {9BA6CBAE-1B19-41BE-9E46-0824CCD932E3}.Release|Win32.Build.0 = Release|Win32 {9BA6CBAE-1B19-41BE-9E46-0824CCD932E3}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {9BA6CBAE-1B19-41BE-9E46-0824CCD932E3}.VSDebug|Win32.Build.0 = VSDebug|Win32 {60D0DC49-FB23-4356-B93B-3083D6C7870F}.Release|Win32.ActiveCfg = Release|Win32 {60D0DC49-FB23-4356-B93B-3083D6C7870F}.Release|Win32.Build.0 = Release|Win32 {60D0DC49-FB23-4356-B93B-3083D6C7870F}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {60D0DC49-FB23-4356-B93B-3083D6C7870F}.VSDebug|Win32.Build.0 = VSDebug|Win32 {3F48737B-A8D7-418A-A448-40AFBAEA1733}.Release|Win32.ActiveCfg = Release|Win32 {3F48737B-A8D7-418A-A448-40AFBAEA1733}.Release|Win32.Build.0 = Release|Win32 {3F48737B-A8D7-418A-A448-40AFBAEA1733}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {3F48737B-A8D7-418A-A448-40AFBAEA1733}.VSDebug|Win32.Build.0 = VSDebug|Win32 {71D59C5D-6E61-4132-B33D-F52524422CB1}.Release|Win32.ActiveCfg = Release|Win32 {71D59C5D-6E61-4132-B33D-F52524422CB1}.Release|Win32.Build.0 = Release|Win32 {71D59C5D-6E61-4132-B33D-F52524422CB1}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {71D59C5D-6E61-4132-B33D-F52524422CB1}.VSDebug|Win32.Build.0 = VSDebug|Win32 {DCDE74CC-6ABD-4F0B-9289-C4B19ADA76E4}.Release|Win32.ActiveCfg = Release|Win32 {DCDE74CC-6ABD-4F0B-9289-C4B19ADA76E4}.Release|Win32.Build.0 = Release|Win32 {DCDE74CC-6ABD-4F0B-9289-C4B19ADA76E4}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {DCDE74CC-6ABD-4F0B-9289-C4B19ADA76E4}.VSDebug|Win32.Build.0 = VSDebug|Win32 {DC6AD8F6-542A-48AC-8960-E62927C907FB}.Release|Win32.ActiveCfg = Release|Win32 {DC6AD8F6-542A-48AC-8960-E62927C907FB}.Release|Win32.Build.0 = Release|Win32 {DC6AD8F6-542A-48AC-8960-E62927C907FB}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {DC6AD8F6-542A-48AC-8960-E62927C907FB}.VSDebug|Win32.Build.0 = VSDebug|Win32 {1AFF43D1-88C8-44B6-A391-3CAA10B9E9CC}.Release|Win32.ActiveCfg = Release|Win32 {1AFF43D1-88C8-44B6-A391-3CAA10B9E9CC}.Release|Win32.Build.0 = Release|Win32 {1AFF43D1-88C8-44B6-A391-3CAA10B9E9CC}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {1AFF43D1-88C8-44B6-A391-3CAA10B9E9CC}.VSDebug|Win32.Build.0 = VSDebug|Win32 {F2BB99F7-6BAB-4DC2-AF69-FCA14F085A9F}.Release|Win32.ActiveCfg = Release|Win32 {F2BB99F7-6BAB-4DC2-AF69-FCA14F085A9F}.Release|Win32.Build.0 = Release|Win32 {F2BB99F7-6BAB-4DC2-AF69-FCA14F085A9F}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {F2BB99F7-6BAB-4DC2-AF69-FCA14F085A9F}.VSDebug|Win32.Build.0 = VSDebug|Win32 {B15D7487-46E8-4134-B095-DC601DD7F6C5}.Release|Win32.ActiveCfg = Release|Win32 {B15D7487-46E8-4134-B095-DC601DD7F6C5}.Release|Win32.Build.0 = Release|Win32 {B15D7487-46E8-4134-B095-DC601DD7F6C5}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {B15D7487-46E8-4134-B095-DC601DD7F6C5}.VSDebug|Win32.Build.0 = VSDebug|Win32 {568C781B-991A-4713-B035-C15BA84C13D1}.Release|Win32.ActiveCfg = Release|Win32 {568C781B-991A-4713-B035-C15BA84C13D1}.Release|Win32.Build.0 = Release|Win32 {568C781B-991A-4713-B035-C15BA84C13D1}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {568C781B-991A-4713-B035-C15BA84C13D1}.VSDebug|Win32.Build.0 = VSDebug|Win32 {6F12D839-A7B1-4BEB-B249-B48BD7D374C7}.Release|Win32.ActiveCfg = Release|Win32 {6F12D839-A7B1-4BEB-B249-B48BD7D374C7}.Release|Win32.Build.0 = Release|Win32 {6F12D839-A7B1-4BEB-B249-B48BD7D374C7}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {6F12D839-A7B1-4BEB-B249-B48BD7D374C7}.VSDebug|Win32.Build.0 = VSDebug|Win32 {04F1B6AF-0358-4FD2-88F9-E609356E7097}.Release|Win32.ActiveCfg = Release|Win32 {04F1B6AF-0358-4FD2-88F9-E609356E7097}.Release|Win32.Build.0 = Release|Win32 {04F1B6AF-0358-4FD2-88F9-E609356E7097}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {04F1B6AF-0358-4FD2-88F9-E609356E7097}.VSDebug|Win32.Build.0 = VSDebug|Win32 {C5627F45-9745-4015-9E82-4CC28EE7278B}.Release|Win32.ActiveCfg = Release|Win32 {C5627F45-9745-4015-9E82-4CC28EE7278B}.Release|Win32.Build.0 = Release|Win32 {C5627F45-9745-4015-9E82-4CC28EE7278B}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {C5627F45-9745-4015-9E82-4CC28EE7278B}.VSDebug|Win32.Build.0 = VSDebug|Win32 {3992C7C8-F4C6-4BAD-96FA-ED93C00BE24A}.Release|Win32.ActiveCfg = Release|Win32 {3992C7C8-F4C6-4BAD-96FA-ED93C00BE24A}.Release|Win32.Build.0 = Release|Win32 {3992C7C8-F4C6-4BAD-96FA-ED93C00BE24A}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {3992C7C8-F4C6-4BAD-96FA-ED93C00BE24A}.VSDebug|Win32.Build.0 = VSDebug|Win32 {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395}.Release|Win32.ActiveCfg = Release|Win32 {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395}.Release|Win32.Build.0 = Release|Win32 {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {F0DFA3BB-B24D-4B3C-B3C2-9FB961D96395}.VSDebug|Win32.Build.0 = VSDebug|Win32 {B3CAA0DA-B778-4B69-8537-3AF7F9984F51}.Release|Win32.ActiveCfg = Release|Win32 {B3CAA0DA-B778-4B69-8537-3AF7F9984F51}.Release|Win32.Build.0 = Release|Win32 {B3CAA0DA-B778-4B69-8537-3AF7F9984F51}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {B3CAA0DA-B778-4B69-8537-3AF7F9984F51}.VSDebug|Win32.Build.0 = VSDebug|Win32 {856D95C9-F063-4613-B8E2-ECB6FC9AB6D3}.Release|Win32.ActiveCfg = Release|Win32 {856D95C9-F063-4613-B8E2-ECB6FC9AB6D3}.Release|Win32.Build.0 = Release|Win32 {856D95C9-F063-4613-B8E2-ECB6FC9AB6D3}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {856D95C9-F063-4613-B8E2-ECB6FC9AB6D3}.VSDebug|Win32.Build.0 = VSDebug|Win32 {48BE6463-9726-40DA-AF2A-7F9E590C4B20}.Release|Win32.ActiveCfg = Release|Win32 {48BE6463-9726-40DA-AF2A-7F9E590C4B20}.Release|Win32.Build.0 = Release|Win32 {48BE6463-9726-40DA-AF2A-7F9E590C4B20}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {48BE6463-9726-40DA-AF2A-7F9E590C4B20}.VSDebug|Win32.Build.0 = VSDebug|Win32 {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D}.Release|Win32.ActiveCfg = Release|Win32 {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D}.Release|Win32.Build.0 = Release|Win32 {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {D1CA56F0-00C0-4E8C-BD6F-8A15619A954D}.VSDebug|Win32.Build.0 = VSDebug|Win32 {A95C47C2-8CFA-4BBB-BD66-3B198323B409}.Release|Win32.ActiveCfg = Release|Win32 {A95C47C2-8CFA-4BBB-BD66-3B198323B409}.Release|Win32.Build.0 = Release|Win32 {A95C47C2-8CFA-4BBB-BD66-3B198323B409}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {A95C47C2-8CFA-4BBB-BD66-3B198323B409}.VSDebug|Win32.Build.0 = VSDebug|Win32 {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2}.Release|Win32.ActiveCfg = Release|Win32 {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2}.Release|Win32.Build.0 = Release|Win32 {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {9DEDE9E5-79D9-41BF-B0E7-92F61D394BE2}.VSDebug|Win32.Build.0 = VSDebug|Win32 {1860A9F0-4E82-4808-B6F0-59625D118021}.Release|Win32.ActiveCfg = Release|Win32 {1860A9F0-4E82-4808-B6F0-59625D118021}.Release|Win32.Build.0 = Release|Win32 {1860A9F0-4E82-4808-B6F0-59625D118021}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {1860A9F0-4E82-4808-B6F0-59625D118021}.VSDebug|Win32.Build.0 = VSDebug|Win32 {1EF7B932-7B1D-49DA-8D58-E9CF0101C1F7}.Release|Win32.ActiveCfg = Release|Win32 {1EF7B932-7B1D-49DA-8D58-E9CF0101C1F7}.Release|Win32.Build.0 = Release|Win32 {1EF7B932-7B1D-49DA-8D58-E9CF0101C1F7}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {1EF7B932-7B1D-49DA-8D58-E9CF0101C1F7}.VSDebug|Win32.Build.0 = VSDebug|Win32 {7EC7E241-8C9E-40DC-8BF5-78FC90CEA990}.Release|Win32.ActiveCfg = Release|Win32 {7EC7E241-8C9E-40DC-8BF5-78FC90CEA990}.Release|Win32.Build.0 = Release|Win32 {7EC7E241-8C9E-40DC-8BF5-78FC90CEA990}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {7EC7E241-8C9E-40DC-8BF5-78FC90CEA990}.VSDebug|Win32.Build.0 = VSDebug|Win32 {5C1834B6-0BA9-4541-8770-D65A78F33958}.Release|Win32.ActiveCfg = Release|Win32 {5C1834B6-0BA9-4541-8770-D65A78F33958}.Release|Win32.Build.0 = Release|Win32 {5C1834B6-0BA9-4541-8770-D65A78F33958}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {5C1834B6-0BA9-4541-8770-D65A78F33958}.VSDebug|Win32.Build.0 = VSDebug|Win32 {CEE2C1FC-7AB1-4833-8AFC-8E0AD60CDCC9}.Release|Win32.ActiveCfg = Release|Win32 {CEE2C1FC-7AB1-4833-8AFC-8E0AD60CDCC9}.Release|Win32.Build.0 = Release|Win32 {CEE2C1FC-7AB1-4833-8AFC-8E0AD60CDCC9}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {CEE2C1FC-7AB1-4833-8AFC-8E0AD60CDCC9}.VSDebug|Win32.Build.0 = VSDebug|Win32 {6BA13A4B-8361-474A-8055-3A9F2437C3AC}.Release|Win32.ActiveCfg = Release|Win32 {6BA13A4B-8361-474A-8055-3A9F2437C3AC}.Release|Win32.Build.0 = Release|Win32 {6BA13A4B-8361-474A-8055-3A9F2437C3AC}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {6BA13A4B-8361-474A-8055-3A9F2437C3AC}.VSDebug|Win32.Build.0 = VSDebug|Win32 {8447CA5B-9D12-4DF0-B225-A25F4B288D2D}.Release|Win32.ActiveCfg = Release|Win32 {8447CA5B-9D12-4DF0-B225-A25F4B288D2D}.Release|Win32.Build.0 = Release|Win32 {8447CA5B-9D12-4DF0-B225-A25F4B288D2D}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {8447CA5B-9D12-4DF0-B225-A25F4B288D2D}.VSDebug|Win32.Build.0 = VSDebug|Win32 {4C79D798-FB54-4CD5-9067-9BDC8678478A}.Release|Win32.ActiveCfg = Release|Win32 {4C79D798-FB54-4CD5-9067-9BDC8678478A}.Release|Win32.Build.0 = Release|Win32 {4C79D798-FB54-4CD5-9067-9BDC8678478A}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {4C79D798-FB54-4CD5-9067-9BDC8678478A}.VSDebug|Win32.Build.0 = VSDebug|Win32 {5641B37B-7AE7-450A-A433-7B83C73BC878}.Release|Win32.ActiveCfg = Release|Win32 {5641B37B-7AE7-450A-A433-7B83C73BC878}.Release|Win32.Build.0 = Release|Win32 {5641B37B-7AE7-450A-A433-7B83C73BC878}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {5641B37B-7AE7-450A-A433-7B83C73BC878}.VSDebug|Win32.Build.0 = VSDebug|Win32 {D9725AED-6124-4225-AC2B-306A97F90607}.Release|Win32.ActiveCfg = Release|Win32 {D9725AED-6124-4225-AC2B-306A97F90607}.Release|Win32.Build.0 = Release|Win32 {D9725AED-6124-4225-AC2B-306A97F90607}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {D9725AED-6124-4225-AC2B-306A97F90607}.VSDebug|Win32.Build.0 = VSDebug|Win32 {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5}.Release|Win32.ActiveCfg = Release|Win32 {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5}.Release|Win32.Build.0 = Release|Win32 {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {F42C141B-BECB-4F9C-828B-8BA0DB2BF7E5}.VSDebug|Win32.Build.0 = VSDebug|Win32 {9D9A7FB3-B049-4E4C-835A-D2516DC2F076}.Release|Win32.ActiveCfg = Release|Win32 {9D9A7FB3-B049-4E4C-835A-D2516DC2F076}.Release|Win32.Build.0 = Release|Win32 {9D9A7FB3-B049-4E4C-835A-D2516DC2F076}.VSDebug|Win32.ActiveCfg = VSDebug|Win32 {9D9A7FB3-B049-4E4C-835A-D2516DC2F076}.VSDebug|Win32.Build.0 = VSDebug|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: msvscpp/libfusn/libfusn.vcproj ================================================ ================================================ FILE: msvscpp/libfwnt/libfwnt.vcproj ================================================ ================================================ FILE: msvscpp/libhmac/libhmac.vcproj ================================================ ================================================ FILE: msvscpp/libuna/libuna.vcproj ================================================ ================================================ FILE: msvscpp/pyfsntfs/pyfsntfs.vcproj ================================================ ================================================ FILE: ossfuzz/Makefile.am ================================================ if HAVE_LIB_FUZZING_ENGINE AM_CPPFLAGS = \ -I../include -I$(top_srcdir)/include \ -I../common -I$(top_srcdir)/common \ @LIBCERROR_CPPFLAGS@ \ @LIBCDATA_CPPFLAGS@ \ @LIBCLOCALE_CPPFLAGS@ \ @LIBCNOTIFY_CPPFLAGS@ \ @LIBUNA_CPPFLAGS@ \ @LIBCFILE_CPPFLAGS@ \ @LIBCPATH_CPPFLAGS@ \ @LIBBFIO_CPPFLAGS@ bin_PROGRAMS = \ file_entry_fuzzer \ mft_metadata_file_fuzzer \ volume_fuzzer file_entry_fuzzer_SOURCES = \ ossfuzz_libbfio.h \ ossfuzz_libfsntfs.h \ file_entry_fuzzer.cc file_entry_fuzzer_LDADD = \ @LIB_FUZZING_ENGINE@ \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCERROR_LIBADD@ \ @LIBINTL@ mft_metadata_file_fuzzer_SOURCES = \ mft_metadata_file_fuzzer.cc \ ossfuzz_libbfio.h \ ossfuzz_libfsntfs.h mft_metadata_file_fuzzer_LDADD = \ @LIB_FUZZING_ENGINE@ \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCERROR_LIBADD@ \ @LIBINTL@ volume_fuzzer_SOURCES = \ ossfuzz_libbfio.h \ ossfuzz_libfsntfs.h \ volume_fuzzer.cc volume_fuzzer_LDADD = \ @LIB_FUZZING_ENGINE@ \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCERROR_LIBADD@ \ @LIBINTL@ endif DISTCLEANFILES = \ Makefile \ Makefile.in splint-local: @echo "Running splint on file_entry_fuzzer ..." -splint -preproc -redef $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(file_entry_fuzzer_SOURCES) @echo "Running splint on mft_metadata_file_fuzzer ..." -splint -preproc -redef $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(mft_metadata_file_fuzzer_SOURCES) @echo "Running splint on volume_fuzzer ..." -splint -preproc -redef $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(volume_fuzzer_SOURCES) ================================================ FILE: ossfuzz/file_entry_fuzzer.cc ================================================ /* * OSS-Fuzz target for libfsntfs file_entry type * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include /* Note that some of the OSS-Fuzz engines use C++ */ extern "C" { #include "ossfuzz_libbfio.h" #include "ossfuzz_libfsntfs.h" #if !defined( LIBFSNTFS_HAVE_BFIO ) /* Opens a volume using a Basic File IO (bfio) handle * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_open_file_io_handle( libfsntfs_volume_t *volume, libbfio_handle_t *file_io_handle, int access_flags, libfsntfs_error_t **error ); #endif /* !defined( LIBFSNTFS_HAVE_BFIO ) */ int LLVMFuzzerTestOneInput( const uint8_t *data, size_t size ) { libbfio_handle_t *file_io_handle = NULL; libfsntfs_file_entry_t *root_directory = NULL; libfsntfs_file_entry_t *sub_file_entry = NULL; libfsntfs_volume_t *volume = NULL; int number_of_sub_file_entries = 0; if( libbfio_memory_range_initialize( &file_io_handle, NULL ) != 1 ) { return( 0 ); } if( libbfio_memory_range_set( file_io_handle, (uint8_t *) data, size, NULL ) != 1 ) { goto on_error_libbfio; } if( libfsntfs_volume_initialize( &volume, NULL ) != 1 ) { goto on_error_libbfio; } if( libfsntfs_volume_open_file_io_handle( volume, file_io_handle, LIBFSNTFS_OPEN_READ, NULL ) != 1 ) { goto on_error_libfsntfs_volume; } if( libfsntfs_volume_get_root_directory( volume, &root_directory, NULL ) == 1 ) { if( libfsntfs_file_entry_get_number_of_sub_file_entries( root_directory, &number_of_sub_file_entries, NULL ) != 1 ) { goto on_error_libfsntfs_root_directory; } if( number_of_sub_file_entries > 0 ) { if( libfsntfs_file_entry_get_sub_file_entry_by_index( root_directory, 0, &sub_file_entry, NULL ) != 1 ) { goto on_error_libfsntfs_root_directory; } libfsntfs_file_entry_free( &sub_file_entry, NULL ); } on_error_libfsntfs_root_directory: libfsntfs_file_entry_free( &root_directory, NULL ); } libfsntfs_volume_close( volume, NULL ); on_error_libfsntfs_volume: libfsntfs_volume_free( &volume, NULL ); on_error_libbfio: libbfio_handle_free( &file_io_handle, NULL ); return( 0 ); } } /* extern "C" */ ================================================ FILE: ossfuzz/mft_metadata_file_fuzzer.cc ================================================ /* * OSS-Fuzz target for libfsntfs MFT metadata file type * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include /* Note that some of the OSS-Fuzz engines use C++ */ extern "C" { #include "ossfuzz_libbfio.h" #include "ossfuzz_libfsntfs.h" #if !defined( LIBFSNTFS_HAVE_BFIO ) /* Opens a MFT metadata file using a Basic File IO (bfio) handle * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_open_file_io_handle( libfsntfs_mft_metadata_file_t *mft_metadata_file, libbfio_handle_t *file_io_handle, int access_flags, libfsntfs_error_t **error ); #endif /* !defined( LIBFSNTFS_HAVE_BFIO ) */ int LLVMFuzzerTestOneInput( const uint8_t *data, size_t size ) { libbfio_handle_t *file_io_handle = NULL; libfsntfs_mft_metadata_file_t *mft_metadata_file = NULL; if( libbfio_memory_range_initialize( &file_io_handle, NULL ) != 1 ) { return( 0 ); } if( libbfio_memory_range_set( file_io_handle, (uint8_t *) data, size, NULL ) != 1 ) { goto on_error_libbfio; } if( libfsntfs_mft_metadata_file_initialize( &mft_metadata_file, NULL ) != 1 ) { goto on_error_libbfio; } if( libfsntfs_mft_metadata_file_open_file_io_handle( mft_metadata_file, file_io_handle, LIBFSNTFS_OPEN_READ, NULL ) != 1 ) { goto on_error_libfsntfs; } libfsntfs_mft_metadata_file_close( mft_metadata_file, NULL ); on_error_libfsntfs: libfsntfs_mft_metadata_file_free( &mft_metadata_file, NULL ); on_error_libbfio: libbfio_handle_free( &file_io_handle, NULL ); return( 0 ); } } /* extern "C" */ ================================================ FILE: ossfuzz/ossfuzz_libbfio.h ================================================ /* * The libbfio header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _OSSFUZZ_LIBBFIO_H ) #define _OSSFUZZ_LIBBFIO_H #include /* Define HAVE_LOCAL_LIBBFIO for local use of libbfio */ #if defined( HAVE_LOCAL_LIBBFIO ) #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBBFIO_DLL_IMPORT * before including libbfio.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) && !defined( HAVE_STATIC_EXECUTABLES ) #define LIBBFIO_DLL_IMPORT #endif #include #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( LIBBFIO_HAVE_MULTI_THREAD_SUPPORT ) #error Multi-threading support requires libbfio with multi-threading support #endif #endif /* defined( HAVE_LOCAL_LIBBFIO ) */ #endif /* !defined( _OSSFUZZ_LIBBFIO_H ) */ ================================================ FILE: ossfuzz/ossfuzz_libfsntfs.h ================================================ /* * The libfsntfs header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _OSSFUZZ_LIBFSNTFS_H ) #define _OSSFUZZ_LIBFSNTFS_H #include #include #endif /* !defined( _OSSFUZZ_LIBFSNTFS_H ) */ ================================================ FILE: ossfuzz/volume_fuzzer.cc ================================================ /* * OSS-Fuzz target for libfsntfs volume type * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include /* Note that some of the OSS-Fuzz engines use C++ */ extern "C" { #include "ossfuzz_libbfio.h" #include "ossfuzz_libfsntfs.h" #if !defined( LIBFSNTFS_HAVE_BFIO ) /* Opens a volume using a Basic File IO (bfio) handle * Returns 1 if successful or -1 on error */ LIBFSNTFS_EXTERN \ int libfsntfs_volume_open_file_io_handle( libfsntfs_volume_t *volume, libbfio_handle_t *file_io_handle, int access_flags, libfsntfs_error_t **error ); #endif /* !defined( LIBFSNTFS_HAVE_BFIO ) */ int LLVMFuzzerTestOneInput( const uint8_t *data, size_t size ) { libbfio_handle_t *file_io_handle = NULL; libfsntfs_volume_t *volume = NULL; if( libbfio_memory_range_initialize( &file_io_handle, NULL ) != 1 ) { return( 0 ); } if( libbfio_memory_range_set( file_io_handle, (uint8_t *) data, size, NULL ) != 1 ) { goto on_error_libbfio; } if( libfsntfs_volume_initialize( &volume, NULL ) != 1 ) { goto on_error_libbfio; } if( libfsntfs_volume_open_file_io_handle( volume, file_io_handle, LIBFSNTFS_OPEN_READ, NULL ) != 1 ) { goto on_error_libfsntfs; } libfsntfs_volume_close( volume, NULL ); on_error_libfsntfs: libfsntfs_volume_free( &volume, NULL ); on_error_libbfio: libbfio_handle_free( &file_io_handle, NULL ); return( 0 ); } } /* extern "C" */ ================================================ FILE: po/ChangeLog ================================================ 2016-11-09 gettextize ================================================ FILE: po/Makevars.in ================================================ # Makefile variables for PO directory in any package using GNU gettext. # Usually the message domain is the same as the package name. DOMAIN = @PACKAGE@ # These two variables depend on the location of this directory. subdir = po top_builddir = .. # These options get passed to xgettext. XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ # This is the copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding # package. (Note that the msgstr strings, extracted from the package's # sources, belong to the copyright holder of the package.) Translators are # expected to transfer the copyright for their translations to this person # or entity, or to disclaim their copyright. The empty string stands for # the public domain; in this case the translators are expected to disclaim # their copyright. COPYRIGHT_HOLDER = Joachim Metz # This is the email address or URL to which the translators shall report # bugs in the untranslated strings: # - Strings which are not entire sentences, see the maintainer guidelines # in the GNU gettext documentation, section 'Preparing Strings'. # - Strings which use unclear terms or require additional context to be # understood. # - Strings which make invalid assumptions about notation of date, time or # money. # - Pluralisation problems. # - Incorrect English spelling. # - Incorrect formatting. # It can be your email address, or a mailing list address where translators # can write to without being subscribed, or the URL of a web page through # which the translators can contact you. MSGID_BUGS_ADDRESS = @PACKAGE_BUGREPORT@ # This is the list of locale categories, beyond LC_MESSAGES, for which the # message catalogs shall be used. It is usually empty. EXTRA_LOCALE_CATEGORIES = # Additional make targets. sources splint: ================================================ FILE: po/POTFILES.in ================================================ # List of source files which contain translatable strings. ================================================ FILE: pyfsntfs/Makefile.am ================================================ if HAVE_PYTHON AM_CFLAGS = \ -I../include -I$(top_srcdir)/include \ -I../common -I$(top_srcdir)/common \ @LIBCERROR_CPPFLAGS@ \ @LIBCDATA_CPPFLAGS@ \ @LIBCLOCALE_CPPFLAGS@ \ @LIBCSPLIT_CPPFLAGS@ \ @LIBUNA_CPPFLAGS@ \ @LIBCFILE_CPPFLAGS@ \ @LIBCPATH_CPPFLAGS@ \ @LIBBFIO_CPPFLAGS@ \ @LIBFGUID_CPPFLAGS@ \ @LIBFSNTFS_DLL_IMPORT@ pyexec_LTLIBRARIES = pyfsntfs.la pyfsntfs_la_SOURCES = \ pyfsntfs.c pyfsntfs.h \ pyfsntfs_attribute.c pyfsntfs_attribute.h \ pyfsntfs_attribute_types.c pyfsntfs_attribute_types.h \ pyfsntfs_attributes.c pyfsntfs_attributes.h \ pyfsntfs_data_stream.c pyfsntfs_data_stream.h \ pyfsntfs_data_streams.c pyfsntfs_data_streams.h \ pyfsntfs_datetime.c pyfsntfs_datetime.h \ pyfsntfs_error.c pyfsntfs_error.h \ pyfsntfs_file_attribute_flags.c pyfsntfs_file_attribute_flags.h \ pyfsntfs_file_entries.c pyfsntfs_file_entries.h \ pyfsntfs_file_entry.c pyfsntfs_file_entry.h \ pyfsntfs_file_name_attribute.c pyfsntfs_file_name_attribute.h \ pyfsntfs_file_object_io_handle.c pyfsntfs_file_object_io_handle.h \ pyfsntfs_guid.c pyfsntfs_guid.h \ pyfsntfs_integer.c pyfsntfs_integer.h \ pyfsntfs_libbfio.h \ pyfsntfs_libcerror.h \ pyfsntfs_libclocale.h \ pyfsntfs_libfguid.h \ pyfsntfs_libfsntfs.h \ pyfsntfs_libuna.h \ pyfsntfs_mft_metadata_file.c pyfsntfs_mft_metadata_file.h \ pyfsntfs_mft_metadata_file_entries.c pyfsntfs_mft_metadata_file_entries.h \ pyfsntfs_object_identifier_attribute.c pyfsntfs_object_identifier_attribute.h \ pyfsntfs_python.h \ pyfsntfs_reparse_point_attribute.c pyfsntfs_reparse_point_attribute.h \ pyfsntfs_security_descriptor_attribute.c pyfsntfs_security_descriptor_attribute.h \ pyfsntfs_standard_information_attribute.c pyfsntfs_standard_information_attribute.h \ pyfsntfs_string.c pyfsntfs_string.h \ pyfsntfs_usn_change_journal.c pyfsntfs_usn_change_journal.h \ pyfsntfs_unused.h \ pyfsntfs_volume.c pyfsntfs_volume.h \ pyfsntfs_volume_file_entries.c pyfsntfs_volume_file_entries.h \ pyfsntfs_volume_information_attribute.c pyfsntfs_volume_information_attribute.h \ pyfsntfs_volume_name_attribute.c pyfsntfs_volume_name_attribute.h pyfsntfs_la_LIBADD = \ @LIBCERROR_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCDATA_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBBFIO_LIBADD@ \ @LIBFGUID_LIBADD@ pyfsntfs_la_CPPFLAGS = $(PYTHON_CPPFLAGS) pyfsntfs_la_LDFLAGS = -module -avoid-version $(PYTHON_LDFLAGS) endif DISTCLEANFILES = \ Makefile \ Makefile.in ================================================ FILE: pyfsntfs/pyfsntfs.c ================================================ /* * Python bindings module for libfsntfs (pyfsntfs) * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs.h" #include "pyfsntfs_attribute.h" #include "pyfsntfs_attribute_types.h" #include "pyfsntfs_attributes.h" #include "pyfsntfs_data_stream.h" #include "pyfsntfs_data_streams.h" #include "pyfsntfs_error.h" #include "pyfsntfs_file_attribute_flags.h" #include "pyfsntfs_file_entries.h" #include "pyfsntfs_file_entry.h" #include "pyfsntfs_file_name_attribute.h" #include "pyfsntfs_file_object_io_handle.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_mft_metadata_file.h" #include "pyfsntfs_mft_metadata_file_entries.h" #include "pyfsntfs_object_identifier_attribute.h" #include "pyfsntfs_python.h" #include "pyfsntfs_reparse_point_attribute.h" #include "pyfsntfs_security_descriptor_attribute.h" #include "pyfsntfs_standard_information_attribute.h" #include "pyfsntfs_unused.h" #include "pyfsntfs_usn_change_journal.h" #include "pyfsntfs_volume.h" #include "pyfsntfs_volume_file_entries.h" #include "pyfsntfs_volume_information_attribute.h" #include "pyfsntfs_volume_name_attribute.h" #if !defined( LIBFSNTFS_HAVE_BFIO ) LIBFSNTFS_EXTERN \ int libfsntfs_check_volume_signature_file_io_handle( libbfio_handle_t *file_io_handle, libfsntfs_error_t **error ); #endif /* !defined( LIBFSNTFS_HAVE_BFIO ) */ /* The pyfsntfs module methods */ PyMethodDef pyfsntfs_module_methods[] = { { "get_version", (PyCFunction) pyfsntfs_get_version, METH_NOARGS, "get_version() -> String\n" "\n" "Retrieves the version." }, { "check_volume_signature", (PyCFunction) pyfsntfs_check_volume_signature, METH_VARARGS | METH_KEYWORDS, "check_volume_signature(filename) -> Boolean\n" "\n" "Checks if a volume has a Windows New Technology File System (NTFS) volume signature." }, { "check_volume_signature_file_object", (PyCFunction) pyfsntfs_check_volume_signature_file_object, METH_VARARGS | METH_KEYWORDS, "check_volume_signature_file_object(file_object) -> Boolean\n" "\n" "Checks if a volume has a Windows New Technology File System (NTFS) volume signature using a file-like object." }, { "open", (PyCFunction) pyfsntfs_open_new_volume, METH_VARARGS | METH_KEYWORDS, "open(filename, mode='r') -> Object\n" "\n" "Opens a volume." }, { "open_file_object", (PyCFunction) pyfsntfs_open_new_volume_with_file_object, METH_VARARGS | METH_KEYWORDS, "open_file_object(file_object, mode='r') -> Object\n" "\n" "Opens a volume using a file-like object." }, /* Sentinel */ { NULL, NULL, 0, NULL } }; /* Retrieves the pyfsntfs/libfsntfs version * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_get_version( PyObject *self PYFSNTFS_ATTRIBUTE_UNUSED, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { const char *version_string = NULL; size_t version_string_length = 0; PYFSNTFS_UNREFERENCED_PARAMETER( self ) PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) Py_BEGIN_ALLOW_THREADS version_string = libfsntfs_get_version(); Py_END_ALLOW_THREADS version_string_length = narrow_string_length( version_string ); /* Pass the string length to PyUnicode_DecodeUTF8 * otherwise it makes the end of string character is part * of the string */ return( PyUnicode_DecodeUTF8( version_string, (Py_ssize_t) version_string_length, NULL ) ); } /* Checks if a volume has a Windows New Technology File System (NTFS) volume signature * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_check_volume_signature( PyObject *self PYFSNTFS_ATTRIBUTE_UNUSED, PyObject *arguments, PyObject *keywords ) { PyObject *string_object = NULL; libcerror_error_t *error = NULL; const char *filename_narrow = NULL; static char *function = "pyfsntfs_check_volume_signature"; static char *keyword_list[] = { "filename", NULL }; int result = 0; #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) const wchar_t *filename_wide = NULL; #else PyObject *utf8_string_object = NULL; #endif PYFSNTFS_UNREFERENCED_PARAMETER( self ) /* Note that PyArg_ParseTupleAndKeywords with "s" will force Unicode strings to be converted to narrow character string. * On Windows the narrow character strings contains an extended ASCII string with a codepage. Hence we get a conversion * exception. This will also fail if the default encoding is not set correctly. We cannot use "u" here either since that * does not allow us to pass non Unicode string objects and Python (at least 2.7) does not seems to automatically upcast them. */ if( PyArg_ParseTupleAndKeywords( arguments, keywords, "O|", keyword_list, &string_object ) == 0 ) { return( NULL ); } PyErr_Clear(); result = PyObject_IsInstance( string_object, (PyObject *) &PyUnicode_Type ); if( result == -1 ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to determine if string object is of type Unicode.", function ); return( NULL ); } else if( result != 0 ) { PyErr_Clear(); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 filename_wide = (wchar_t *) PyUnicode_AsWideCharString( string_object, NULL ); #else filename_wide = (wchar_t *) PyUnicode_AsUnicode( string_object ); #endif Py_BEGIN_ALLOW_THREADS result = libfsntfs_check_volume_signature_wide( filename_wide, &error ); Py_END_ALLOW_THREADS #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 PyMem_Free( filename_wide ); #endif #else utf8_string_object = PyUnicode_AsUTF8String( string_object ); if( utf8_string_object == NULL ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to convert Unicode string to UTF-8.", function ); return( NULL ); } #if PY_MAJOR_VERSION >= 3 filename_narrow = PyBytes_AsString( utf8_string_object ); #else filename_narrow = PyString_AsString( utf8_string_object ); #endif Py_BEGIN_ALLOW_THREADS result = libfsntfs_check_volume_signature( filename_narrow, &error ); Py_END_ALLOW_THREADS Py_DecRef( utf8_string_object ); #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */ if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to check volume signature.", function ); libcerror_error_free( &error ); return( NULL ); } if( result != 0 ) { Py_IncRef( (PyObject *) Py_True ); return( Py_True ); } Py_IncRef( (PyObject *) Py_False ); return( Py_False ); } PyErr_Clear(); #if PY_MAJOR_VERSION >= 3 result = PyObject_IsInstance( string_object, (PyObject *) &PyBytes_Type ); #else result = PyObject_IsInstance( string_object, (PyObject *) &PyString_Type ); #endif if( result == -1 ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to determine if string object is of type string.", function ); return( NULL ); } else if( result != 0 ) { PyErr_Clear(); #if PY_MAJOR_VERSION >= 3 filename_narrow = PyBytes_AsString( string_object ); #else filename_narrow = PyString_AsString( string_object ); #endif Py_BEGIN_ALLOW_THREADS result = libfsntfs_check_volume_signature( filename_narrow, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to check volume signature.", function ); libcerror_error_free( &error ); return( NULL ); } if( result != 0 ) { Py_IncRef( (PyObject *) Py_True ); return( Py_True ); } Py_IncRef( (PyObject *) Py_False ); return( Py_False ); } PyErr_Format( PyExc_TypeError, "%s: unsupported string object type.", function ); return( NULL ); } /* Checks if a volume has a Windows New Technology File System (NTFS) volume signature using a file-like object * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_check_volume_signature_file_object( PyObject *self PYFSNTFS_ATTRIBUTE_UNUSED, PyObject *arguments, PyObject *keywords ) { PyObject *file_object = NULL; libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; static char *function = "pyfsntfs_check_volume_signature_file_object"; static char *keyword_list[] = { "file_object", NULL }; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( self ) if( PyArg_ParseTupleAndKeywords( arguments, keywords, "|O", keyword_list, &file_object ) == 0 ) { return( NULL ); } if( pyfsntfs_file_object_initialize( &file_io_handle, file_object, &error ) != 1 ) { pyfsntfs_error_raise( error, PyExc_MemoryError, "%s: unable to initialize file IO handle.", function ); libcerror_error_free( &error ); goto on_error; } Py_BEGIN_ALLOW_THREADS result = libfsntfs_check_volume_signature_file_io_handle( file_io_handle, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to check volume signature.", function ); libcerror_error_free( &error ); goto on_error; } if( libbfio_handle_free( &file_io_handle, &error ) != 1 ) { pyfsntfs_error_raise( error, PyExc_MemoryError, "%s: unable to free file IO handle.", function ); libcerror_error_free( &error ); goto on_error; } if( result != 0 ) { Py_IncRef( (PyObject *) Py_True ); return( Py_True ); } Py_IncRef( (PyObject *) Py_False ); return( Py_False ); on_error: if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } return( NULL ); } /* Creates a new volume object and opens it * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_open_new_volume( PyObject *self PYFSNTFS_ATTRIBUTE_UNUSED, PyObject *arguments, PyObject *keywords ) { pyfsntfs_volume_t *pyfsntfs_volume = NULL; static char *function = "pyfsntfs_open_new_volume"; PYFSNTFS_UNREFERENCED_PARAMETER( self ) /* PyObject_New does not invoke tp_init */ pyfsntfs_volume = PyObject_New( struct pyfsntfs_volume, &pyfsntfs_volume_type_object ); if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create volume.", function ); goto on_error; } if( pyfsntfs_volume_init( pyfsntfs_volume ) != 0 ) { goto on_error; } if( pyfsntfs_volume_open( pyfsntfs_volume, arguments, keywords ) == NULL ) { goto on_error; } return( (PyObject *) pyfsntfs_volume ); on_error: if( pyfsntfs_volume != NULL ) { Py_DecRef( (PyObject *) pyfsntfs_volume ); } return( NULL ); } /* Creates a new volume object and opens it using a file-like object * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_open_new_volume_with_file_object( PyObject *self PYFSNTFS_ATTRIBUTE_UNUSED, PyObject *arguments, PyObject *keywords ) { pyfsntfs_volume_t *pyfsntfs_volume = NULL; static char *function = "pyfsntfs_open_new_volume_with_file_object"; PYFSNTFS_UNREFERENCED_PARAMETER( self ) /* PyObject_New does not invoke tp_init */ pyfsntfs_volume = PyObject_New( struct pyfsntfs_volume, &pyfsntfs_volume_type_object ); if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create volume.", function ); goto on_error; } if( pyfsntfs_volume_init( pyfsntfs_volume ) != 0 ) { goto on_error; } if( pyfsntfs_volume_open_file_object( pyfsntfs_volume, arguments, keywords ) == NULL ) { goto on_error; } return( (PyObject *) pyfsntfs_volume ); on_error: if( pyfsntfs_volume != NULL ) { Py_DecRef( (PyObject *) pyfsntfs_volume ); } return( NULL ); } #if PY_MAJOR_VERSION >= 3 /* The pyfsntfs module definition */ PyModuleDef pyfsntfs_module_definition = { PyModuleDef_HEAD_INIT, /* m_name */ "pyfsntfs", /* m_doc */ "Python libfsntfs module (pyfsntfs).", /* m_size */ -1, /* m_methods */ pyfsntfs_module_methods, /* m_reload */ NULL, /* m_traverse */ NULL, /* m_clear */ NULL, /* m_free */ NULL, }; #endif /* PY_MAJOR_VERSION >= 3 */ /* Initializes the pyfsntfs module */ #if PY_MAJOR_VERSION >= 3 PyMODINIT_FUNC PyInit_pyfsntfs( void ) #else PyMODINIT_FUNC initpyfsntfs( void ) #endif { PyObject *module = NULL; PyGILState_STATE gil_state = 0; #if defined( HAVE_DEBUG_OUTPUT ) libfsntfs_notify_set_stream( stderr, NULL ); libfsntfs_notify_set_verbose( 1 ); #endif /* Create the module * This function must be called before grabbing the GIL * otherwise the module will segfault on a version mismatch */ #if PY_MAJOR_VERSION >= 3 module = PyModule_Create( &pyfsntfs_module_definition ); #else module = Py_InitModule3( "pyfsntfs", pyfsntfs_module_methods, "Python libfsntfs module (pyfsntfs)." ); #endif if( module == NULL ) { #if PY_MAJOR_VERSION >= 3 return( NULL ); #else return; #endif } #if PY_VERSION_HEX < 0x03070000 PyEval_InitThreads(); #endif gil_state = PyGILState_Ensure(); /* Setup the attribute type object */ pyfsntfs_attribute_type_object.tp_new = PyType_GenericNew; if( PyType_Ready( &pyfsntfs_attribute_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_attribute_type_object ); PyModule_AddObject( module, "attribute", (PyObject *) &pyfsntfs_attribute_type_object ); /* Setup the attribute types type object */ pyfsntfs_attribute_types_type_object.tp_new = PyType_GenericNew; if( pyfsntfs_attribute_types_init_type( &pyfsntfs_attribute_types_type_object ) != 1 ) { goto on_error; } if( PyType_Ready( &pyfsntfs_attribute_types_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_attribute_types_type_object ); PyModule_AddObject( module, "attribute_types", (PyObject *) &pyfsntfs_attribute_types_type_object ); /* Setup the attributes type object */ pyfsntfs_attributes_type_object.tp_new = PyType_GenericNew; if( PyType_Ready( &pyfsntfs_attributes_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_attributes_type_object ); PyModule_AddObject( module, "attributes", (PyObject *) &pyfsntfs_attributes_type_object ); /* Setup the data stream type object */ pyfsntfs_data_stream_type_object.tp_new = PyType_GenericNew; if( PyType_Ready( &pyfsntfs_data_stream_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_data_stream_type_object ); PyModule_AddObject( module, "data_stream", (PyObject *) &pyfsntfs_data_stream_type_object ); /* Setup the data streams type object */ pyfsntfs_data_streams_type_object.tp_new = PyType_GenericNew; if( PyType_Ready( &pyfsntfs_data_streams_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_data_streams_type_object ); PyModule_AddObject( module, "data_streams", (PyObject *) &pyfsntfs_data_streams_type_object ); /* Setup the file attribute flags type object */ pyfsntfs_file_attribute_flags_type_object.tp_new = PyType_GenericNew; if( pyfsntfs_file_attribute_flags_init_type( &pyfsntfs_file_attribute_flags_type_object ) != 1 ) { goto on_error; } if( PyType_Ready( &pyfsntfs_file_attribute_flags_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_file_attribute_flags_type_object ); PyModule_AddObject( module, "file_attribute_flags", (PyObject *) &pyfsntfs_file_attribute_flags_type_object ); /* Setup the file entry type object */ pyfsntfs_file_entry_type_object.tp_new = PyType_GenericNew; if( PyType_Ready( &pyfsntfs_file_entry_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_file_entry_type_object ); PyModule_AddObject( module, "file_entry", (PyObject *) &pyfsntfs_file_entry_type_object ); /* Setup the file entries type object */ pyfsntfs_file_entries_type_object.tp_new = PyType_GenericNew; if( PyType_Ready( &pyfsntfs_file_entries_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_file_entries_type_object ); PyModule_AddObject( module, "file_entries", (PyObject *) &pyfsntfs_file_entries_type_object ); /* Setup the $FILE_NAME attribute type object */ pyfsntfs_file_name_attribute_type_object.tp_new = PyType_GenericNew; if( PyType_Ready( &pyfsntfs_file_name_attribute_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_file_name_attribute_type_object ); PyModule_AddObject( module, "file_name_attribute", (PyObject *) &pyfsntfs_attribute_type_object ); /* Setup the MFT metadata file type object */ pyfsntfs_mft_metadata_file_type_object.tp_new = PyType_GenericNew; if( PyType_Ready( &pyfsntfs_mft_metadata_file_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_mft_metadata_file_type_object ); PyModule_AddObject( module, "mft_metadata_file", (PyObject *) &pyfsntfs_mft_metadata_file_type_object ); /* Setup the MFT metadata file entries type object */ pyfsntfs_mft_metadata_file_entries_type_object.tp_new = PyType_GenericNew; if( PyType_Ready( &pyfsntfs_mft_metadata_file_entries_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_mft_metadata_file_entries_type_object ); PyModule_AddObject( module, "mft_metadata_file_entries", (PyObject *) &pyfsntfs_mft_metadata_file_entries_type_object ); /* Setup the $OBJECT_IDENTIFIER attribute type object */ pyfsntfs_object_identifier_attribute_type_object.tp_new = PyType_GenericNew; if( PyType_Ready( &pyfsntfs_object_identifier_attribute_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_object_identifier_attribute_type_object ); PyModule_AddObject( module, "object_identifier_attribute", (PyObject *) &pyfsntfs_attribute_type_object ); /* Setup the $REPARSE_POINT attribute type object */ pyfsntfs_reparse_point_attribute_type_object.tp_new = PyType_GenericNew; if( PyType_Ready( &pyfsntfs_reparse_point_attribute_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_reparse_point_attribute_type_object ); PyModule_AddObject( module, "reparse_point_attribute", (PyObject *) &pyfsntfs_attribute_type_object ); /* Setup the $SECURITY_DESCRIPTOR attribute type object */ pyfsntfs_security_descriptor_attribute_type_object.tp_new = PyType_GenericNew; if( PyType_Ready( &pyfsntfs_security_descriptor_attribute_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_security_descriptor_attribute_type_object ); PyModule_AddObject( module, "security_descriptor_attribute", (PyObject *) &pyfsntfs_attribute_type_object ); /* Setup the $STANDARD_INFORMATION attribute type object */ pyfsntfs_standard_information_attribute_type_object.tp_new = PyType_GenericNew; if( PyType_Ready( &pyfsntfs_standard_information_attribute_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_standard_information_attribute_type_object ); PyModule_AddObject( module, "standard_information_attribute", (PyObject *) &pyfsntfs_attribute_type_object ); /* Setup the USN change journal type object */ pyfsntfs_usn_change_journal_type_object.tp_new = PyType_GenericNew; if( PyType_Ready( &pyfsntfs_usn_change_journal_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_usn_change_journal_type_object ); PyModule_AddObject( module, "usn_change_journal", (PyObject *) &pyfsntfs_usn_change_journal_type_object ); /* Setup the volume type object */ pyfsntfs_volume_type_object.tp_new = PyType_GenericNew; if( PyType_Ready( &pyfsntfs_volume_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_volume_type_object ); PyModule_AddObject( module, "volume", (PyObject *) &pyfsntfs_volume_type_object ); /* Setup the volume file entries type object */ pyfsntfs_volume_file_entries_type_object.tp_new = PyType_GenericNew; if( PyType_Ready( &pyfsntfs_volume_file_entries_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_volume_file_entries_type_object ); PyModule_AddObject( module, "volume_file_entries", (PyObject *) &pyfsntfs_volume_file_entries_type_object ); /* Setup the $VOLUME_INFORMATION attribute type object */ pyfsntfs_volume_information_attribute_type_object.tp_new = PyType_GenericNew; if( PyType_Ready( &pyfsntfs_volume_information_attribute_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_volume_information_attribute_type_object ); PyModule_AddObject( module, "volume_information_attribute", (PyObject *) &pyfsntfs_attribute_type_object ); /* Setup the $VOLUME_NAME attribute type object */ pyfsntfs_volume_name_attribute_type_object.tp_new = PyType_GenericNew; if( PyType_Ready( &pyfsntfs_volume_name_attribute_type_object ) < 0 ) { goto on_error; } Py_IncRef( (PyObject *) &pyfsntfs_volume_name_attribute_type_object ); PyModule_AddObject( module, "volume_name_attribute", (PyObject *) &pyfsntfs_attribute_type_object ); PyGILState_Release( gil_state ); #if PY_MAJOR_VERSION >= 3 return( module ); #else return; #endif on_error: PyGILState_Release( gil_state ); #if PY_MAJOR_VERSION >= 3 return( NULL ); #else return; #endif } ================================================ FILE: pyfsntfs/pyfsntfs.h ================================================ /* * Python bindings module for libfsntfs (pyfsntfs) * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_H ) #define _PYFSNTFS_H #include #include #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif PyObject *pyfsntfs_get_version( PyObject *self, PyObject *arguments ); PyObject *pyfsntfs_check_volume_signature( PyObject *self, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_check_volume_signature_file_object( PyObject *self, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_open_new_volume( PyObject *self, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_open_new_volume_with_file_object( PyObject *self, PyObject *arguments, PyObject *keywords ); #if PY_MAJOR_VERSION >= 3 PyMODINIT_FUNC PyInit_pyfsntfs( void ); #else PyMODINIT_FUNC initpyfsntfs( void ); #endif #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_attribute.c ================================================ /* * Python object wrapper of libfsntfs_attribute_t * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_attribute.h" #include "pyfsntfs_error.h" #include "pyfsntfs_integer.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #include "pyfsntfs_unused.h" PyMethodDef pyfsntfs_attribute_object_methods[] = { /* Functions to access the attribute values */ { "get_attribute_type", (PyCFunction) pyfsntfs_attribute_get_type, METH_NOARGS, "get_attribute_type() -> Integer\n" "\n" "Retrieves the attribute type." }, { "get_attribute_name", (PyCFunction) pyfsntfs_attribute_get_name, METH_NOARGS, "get_attribute_name() -> Unicode string or None\n" "\n" "Returns the name of the attribute." }, { "get_data_size", (PyCFunction) pyfsntfs_attribute_get_data_size, METH_NOARGS, "get_data_size() -> Integer\n" "\n" "Returns the size of the attribute data." }, { "get_valid_data_size", (PyCFunction) pyfsntfs_attribute_get_valid_data_size, METH_NOARGS, "get_valid_data_size() -> Integer\n" "\n" "Returns the size of the attribute data that is used (considered valid)." }, /* Sentinel */ { NULL, NULL, 0, NULL } }; PyGetSetDef pyfsntfs_attribute_object_get_set_definitions[] = { { "attribute_type", (getter) pyfsntfs_attribute_get_type, (setter) 0, "The attribute type.", NULL }, { "attribute_name", (getter) pyfsntfs_attribute_get_name, (setter) 0, "The name of the attribute.", NULL }, { "data_size", (getter) pyfsntfs_attribute_get_data_size, (setter) 0, "The size of the attribute data.", NULL }, { "valid_data_size", (getter) pyfsntfs_attribute_get_valid_data_size, (setter) 0, "The size of the attribute data that is used (considered valid).", NULL }, /* Sentinel */ { NULL, NULL, NULL, NULL, NULL } }; PyTypeObject pyfsntfs_attribute_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs.attribute", /* tp_basicsize */ sizeof( pyfsntfs_attribute_t ), /* tp_itemsize */ 0, /* tp_dealloc */ (destructor) pyfsntfs_attribute_free, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_doc */ "pyfsntfs attribute object (wraps libfsntfs_attribute_t)", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ pyfsntfs_attribute_object_methods, /* tp_members */ 0, /* tp_getset */ pyfsntfs_attribute_object_get_set_definitions, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ (initproc) pyfsntfs_attribute_init, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Creates a new attribute object * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_attribute_new( PyTypeObject *type_object, libfsntfs_attribute_t *attribute, PyObject *parent_object ) { pyfsntfs_attribute_t *pyfsntfs_attribute = NULL; static char *function = "pyfsntfs_attribute_new"; if( attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } /* PyObject_New does not invoke tp_init */ pyfsntfs_attribute = PyObject_New( struct pyfsntfs_attribute, type_object ); if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to initialize attribute.", function ); goto on_error; } pyfsntfs_attribute->attribute = attribute; pyfsntfs_attribute->parent_object = parent_object; if( pyfsntfs_attribute->parent_object != NULL ) { Py_IncRef( pyfsntfs_attribute->parent_object ); } return( (PyObject *) pyfsntfs_attribute ); on_error: if( pyfsntfs_attribute != NULL ) { Py_DecRef( (PyObject *) pyfsntfs_attribute ); } return( NULL ); } /* Initializes an attribute object * Returns 0 if successful or -1 on error */ int pyfsntfs_attribute_init( pyfsntfs_attribute_t *pyfsntfs_attribute ) { static char *function = "pyfsntfs_attribute_init"; if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( -1 ); } /* Make sure libfsntfs attribute is set to NULL */ pyfsntfs_attribute->attribute = NULL; PyErr_Format( PyExc_NotImplementedError, "%s: initialize of attribute not supported.", function ); return( -1 ); } /* Frees an attribute object */ void pyfsntfs_attribute_free( pyfsntfs_attribute_t *pyfsntfs_attribute ) { struct _typeobject *ob_type = NULL; libcerror_error_t *error = NULL; static char *function = "pyfsntfs_attribute_free"; int result = 0; if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return; } ob_type = Py_TYPE( pyfsntfs_attribute ); if( ob_type == NULL ) { PyErr_Format( PyExc_ValueError, "%s: missing ob_type.", function ); return; } if( ob_type->tp_free == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid ob_type - missing tp_free.", function ); return; } if( pyfsntfs_attribute->attribute != NULL ) { Py_BEGIN_ALLOW_THREADS result = libfsntfs_attribute_free( &( pyfsntfs_attribute->attribute ), &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_MemoryError, "%s: unable to free libfsntfs attribute.", function ); libcerror_error_free( &error ); } } if( pyfsntfs_attribute->parent_object != NULL ) { Py_DecRef( pyfsntfs_attribute->parent_object ); } ob_type->tp_free( (PyObject*) pyfsntfs_attribute ); } /* Retrieves the type * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_attribute_get_type( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_attribute_get_type"; uint32_t value_32bit = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_attribute_get_type( pyfsntfs_attribute->attribute, &value_32bit, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve type.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = PyLong_FromUnsignedLong( (unsigned long) value_32bit ); return( integer_object ); } /* Retrieves the name * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_attribute_get_name( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *string_object = NULL; uint8_t *name = NULL; static char *function = "pyfsntfs_attribute_get_name"; size_t name_size = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_attribute_get_utf8_name_size( pyfsntfs_attribute->attribute, &name_size, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve name size.", function ); libcerror_error_free( &error ); goto on_error; } else if( ( result == 0 ) || ( name_size == 0 ) ) { Py_IncRef( Py_None ); return( Py_None ); } name = (uint8_t *) PyMem_Malloc( sizeof( uint8_t ) * name_size ); if( name == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create name.", function ); goto on_error; } Py_BEGIN_ALLOW_THREADS result = libfsntfs_attribute_get_utf8_name( pyfsntfs_attribute->attribute, name, name_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve name.", function ); libcerror_error_free( &error ); goto on_error; } /* Pass the string length to PyUnicode_DecodeUTF8 * otherwise it makes the end of string character is part * of the string */ string_object = PyUnicode_DecodeUTF8( (char *) name, (Py_ssize_t) name_size - 1, NULL ); PyMem_Free( name ); return( string_object ); on_error: if( name != NULL ) { PyMem_Free( name ); } return( NULL ); } /* Retrieves the data size * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_attribute_get_data_size( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_attribute_get_data_size"; size64_t data_size = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_attribute_get_data_size( pyfsntfs_attribute->attribute, &data_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve data size.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( (uint64_t) data_size ); return( integer_object ); } /* Retrieves the valid data size * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_attribute_get_valid_data_size( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_attribute_get_valid_data_size"; size64_t valid_data_size = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_attribute_get_valid_data_size( pyfsntfs_attribute->attribute, &valid_data_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve valid data size.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( (uint64_t) valid_data_size ); return( integer_object ); } ================================================ FILE: pyfsntfs/pyfsntfs_attribute.h ================================================ /* * Python object wrapper of libfsntfs_attribute_t * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_ATTRIBUTE_H ) #define _PYFSNTFS_ATTRIBUTE_H #include #include #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct pyfsntfs_attribute pyfsntfs_attribute_t; struct pyfsntfs_attribute { /* Python object initialization */ PyObject_HEAD /* The libfsntfs attribute */ libfsntfs_attribute_t *attribute; /* The parent object */ PyObject *parent_object; }; extern PyMethodDef pyfsntfs_attribute_object_methods[]; extern PyTypeObject pyfsntfs_attribute_type_object; PyObject *pyfsntfs_attribute_new( PyTypeObject *type_object, libfsntfs_attribute_t *attribute, PyObject *parent_object ); int pyfsntfs_attribute_init( pyfsntfs_attribute_t *pyfsntfs_attribute ); void pyfsntfs_attribute_free( pyfsntfs_attribute_t *pyfsntfs_attribute ); PyObject *pyfsntfs_attribute_get_type( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_attribute_get_name( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_attribute_get_data_size( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_attribute_get_valid_data_size( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_ATTRIBUTE_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_attribute_types.c ================================================ /* * Python object definition of the libfsntfs attribute types * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_attribute_types.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #include "pyfsntfs_unused.h" PyTypeObject pyfsntfs_attribute_types_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs.attribute_types", /* tp_basicsize */ sizeof( pyfsntfs_attribute_types_t ), /* tp_itemsize */ 0, /* tp_dealloc */ (destructor) pyfsntfs_attribute_types_free, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_doc */ "pyfsntfs attribute types object (wraps LIBFSNTFS_ATTRIBUTE_TYPES)", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ (initproc) pyfsntfs_attribute_types_init, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Initializes the type object * Returns 1 if successful or -1 on error */ int pyfsntfs_attribute_types_init_type( PyTypeObject *type_object ) { PyObject *value_object = NULL; if( type_object == NULL ) { return( -1 ); } type_object->tp_dict = PyDict_New(); if( type_object->tp_dict == NULL ) { return( -1 ); } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION ); #else value_object = PyInt_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION ); #endif if( PyDict_SetItemString( type_object->tp_dict, "$STANDARD_INFORMATION", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_ATTRIBUTE_LIST ); #else value_object = PyInt_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_ATTRIBUTE_LIST ); #endif if( PyDict_SetItemString( type_object->tp_dict, "$ATTRIBUTE_LIST", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ); #else value_object = PyInt_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ); #endif if( PyDict_SetItemString( type_object->tp_dict, "$FILE_NAME", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_OBJECT_IDENTIFIER ); #else value_object = PyInt_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_OBJECT_IDENTIFIER ); #endif if( PyDict_SetItemString( type_object->tp_dict, "$OBJECT_ID", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_SECURITY_DESCRIPTOR ); #else value_object = PyInt_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_SECURITY_DESCRIPTOR ); #endif if( PyDict_SetItemString( type_object->tp_dict, "$SECURITY_DESCRIPTOR", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME ); #else value_object = PyInt_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME ); #endif if( PyDict_SetItemString( type_object->tp_dict, "$VOLUME_NAME", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_INFORMATION ); #else value_object = PyInt_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_INFORMATION ); #endif if( PyDict_SetItemString( type_object->tp_dict, "$VOLUME_INFORMATION", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_DATA ); #else value_object = PyInt_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_DATA ); #endif if( PyDict_SetItemString( type_object->tp_dict, "$DATA", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ROOT ); #else value_object = PyInt_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ROOT ); #endif if( PyDict_SetItemString( type_object->tp_dict, "$INDEX_ROOT", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ALLOCATION ); #else value_object = PyInt_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ALLOCATION ); #endif if( PyDict_SetItemString( type_object->tp_dict, "$INDEX_ALLOCATION", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_BITMAP ); #else value_object = PyInt_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_BITMAP ); #endif if( PyDict_SetItemString( type_object->tp_dict, "$BITMAP", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT ); #else value_object = PyInt_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT ); #endif if( PyDict_SetItemString( type_object->tp_dict, "$REPARSE_POINT", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_EXTENDED_INFORMATION ); #else value_object = PyInt_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_EXTENDED_INFORMATION ); #endif if( PyDict_SetItemString( type_object->tp_dict, "$EA_INFORMATION", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_EXTENDED ); #else value_object = PyInt_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_EXTENDED ); #endif if( PyDict_SetItemString( type_object->tp_dict, "$EA", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_PROPERTY_SET ); #else value_object = PyInt_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_PROPERTY_SET ); #endif if( PyDict_SetItemString( type_object->tp_dict, "$PROPERTY_SET", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_LOGGED_UTILITY_STREAM ); #else value_object = PyInt_FromLong( LIBFSNTFS_ATTRIBUTE_TYPE_LOGGED_UTILITY_STREAM ); #endif if( PyDict_SetItemString( type_object->tp_dict, "$LOGGED_UTILITY_STREAM", value_object ) != 0 ) { goto on_error; } return( 1 ); on_error: if( type_object->tp_dict != NULL ) { Py_DecRef( type_object->tp_dict ); type_object->tp_dict = NULL; } return( -1 ); } /* Creates a new attribute types object * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_attribute_types_new( void ) { pyfsntfs_attribute_types_t *definitions_object = NULL; static char *function = "pyfsntfs_attribute_types_new"; definitions_object = PyObject_New( struct pyfsntfs_attribute_types, &pyfsntfs_attribute_types_type_object ); if( definitions_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create definitions object.", function ); goto on_error; } if( pyfsntfs_attribute_types_init( definitions_object ) != 0 ) { PyErr_Format( PyExc_MemoryError, "%s: unable to initialize definitions object.", function ); goto on_error; } return( (PyObject *) definitions_object ); on_error: if( definitions_object != NULL ) { Py_DecRef( (PyObject *) definitions_object ); } return( NULL ); } /* Initializes an attribute types object * Returns 0 if successful or -1 on error */ int pyfsntfs_attribute_types_init( pyfsntfs_attribute_types_t *definitions_object ) { static char *function = "pyfsntfs_attribute_types_init"; if( definitions_object == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid definitions object.", function ); return( -1 ); } return( 0 ); } /* Frees an attribute types object */ void pyfsntfs_attribute_types_free( pyfsntfs_attribute_types_t *definitions_object ) { struct _typeobject *ob_type = NULL; static char *function = "pyfsntfs_attribute_types_free"; if( definitions_object == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid definitions object.", function ); return; } ob_type = Py_TYPE( definitions_object ); if( ob_type == NULL ) { PyErr_Format( PyExc_ValueError, "%s: missing ob_type.", function ); return; } if( ob_type->tp_free == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid ob_type - missing tp_free.", function ); return; } ob_type->tp_free( (PyObject*) definitions_object ); } ================================================ FILE: pyfsntfs/pyfsntfs_attribute_types.h ================================================ /* * Python object definition of the libfsntfs attribute types * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_ATTRIBUTE_TYPES_H ) #define _PYFSNTFS_ATTRIBUTE_TYPES_H #include #include #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct pyfsntfs_attribute_types pyfsntfs_attribute_types_t; struct pyfsntfs_attribute_types { /* Python object initialization */ PyObject_HEAD }; extern PyTypeObject pyfsntfs_attribute_types_type_object; int pyfsntfs_attribute_types_init_type( PyTypeObject *type_object ); PyObject *pyfsntfs_attribute_types_new( void ); int pyfsntfs_attribute_types_init( pyfsntfs_attribute_types_t *definitions_object ); void pyfsntfs_attribute_types_free( pyfsntfs_attribute_types_t *definitions_object ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_ATTRIBUTE_TYPES_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_attributes.c ================================================ /* * Python object definition of the sequence and iterator object of attributes * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_attributes.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" PySequenceMethods pyfsntfs_attributes_sequence_methods = { /* sq_length */ (lenfunc) pyfsntfs_attributes_len, /* sq_concat */ 0, /* sq_repeat */ 0, /* sq_item */ (ssizeargfunc) pyfsntfs_attributes_getitem, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ 0, /* sq_contains */ 0, /* sq_inplace_concat */ 0, /* sq_inplace_repeat */ 0 }; PyTypeObject pyfsntfs_attributes_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs.attributes", /* tp_basicsize */ sizeof( pyfsntfs_attributes_t ), /* tp_itemsize */ 0, /* tp_dealloc */ (destructor) pyfsntfs_attributes_free, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ &pyfsntfs_attributes_sequence_methods, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /* tp_doc */ "pyfsntfs sequence and iterator object of attributes", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ (getiterfunc) pyfsntfs_attributes_iter, /* tp_iternext */ (iternextfunc) pyfsntfs_attributes_iternext, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ (initproc) pyfsntfs_attributes_init, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Creates a new attributes sequence and iterator object * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_attributes_new( PyObject *parent_object, PyObject* (*get_item_by_index)( PyObject *parent_object, int index ), int number_of_items ) { pyfsntfs_attributes_t *sequence_object = NULL; static char *function = "pyfsntfs_attributes_new"; if( parent_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid parent object.", function ); return( NULL ); } if( get_item_by_index == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid get item by index function.", function ); return( NULL ); } /* Make sure the attributes values are initialized */ sequence_object = PyObject_New( struct pyfsntfs_attributes, &pyfsntfs_attributes_type_object ); if( sequence_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create sequence object.", function ); goto on_error; } sequence_object->parent_object = parent_object; sequence_object->get_item_by_index = get_item_by_index; sequence_object->current_index = 0; sequence_object->number_of_items = number_of_items; Py_IncRef( (PyObject *) sequence_object->parent_object ); return( (PyObject *) sequence_object ); on_error: if( sequence_object != NULL ) { Py_DecRef( (PyObject *) sequence_object ); } return( NULL ); } /* Initializes an attributes sequence and iterator object * Returns 0 if successful or -1 on error */ int pyfsntfs_attributes_init( pyfsntfs_attributes_t *sequence_object ) { static char *function = "pyfsntfs_attributes_init"; if( sequence_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object.", function ); return( -1 ); } /* Make sure the attributes values are initialized */ sequence_object->parent_object = NULL; sequence_object->get_item_by_index = NULL; sequence_object->current_index = 0; sequence_object->number_of_items = 0; PyErr_Format( PyExc_NotImplementedError, "%s: initialize of attributes not supported.", function ); return( -1 ); } /* Frees an attributes sequence object */ void pyfsntfs_attributes_free( pyfsntfs_attributes_t *sequence_object ) { struct _typeobject *ob_type = NULL; static char *function = "pyfsntfs_attributes_free"; if( sequence_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object.", function ); return; } ob_type = Py_TYPE( sequence_object ); if( ob_type == NULL ) { PyErr_Format( PyExc_ValueError, "%s: missing ob_type.", function ); return; } if( ob_type->tp_free == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid ob_type - missing tp_free.", function ); return; } if( sequence_object->parent_object != NULL ) { Py_DecRef( (PyObject *) sequence_object->parent_object ); } ob_type->tp_free( (PyObject*) sequence_object ); } /* The attributes len() function */ Py_ssize_t pyfsntfs_attributes_len( pyfsntfs_attributes_t *sequence_object ) { static char *function = "pyfsntfs_attributes_len"; if( sequence_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object.", function ); return( -1 ); } return( (Py_ssize_t) sequence_object->number_of_items ); } /* The attributes getitem() function */ PyObject *pyfsntfs_attributes_getitem( pyfsntfs_attributes_t *sequence_object, Py_ssize_t item_index ) { PyObject *attribute_object = NULL; static char *function = "pyfsntfs_attributes_getitem"; if( sequence_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object.", function ); return( NULL ); } if( sequence_object->get_item_by_index == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object - missing get item by index function.", function ); return( NULL ); } if( sequence_object->number_of_items < 0 ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object - invalid number of items.", function ); return( NULL ); } if( ( item_index < 0 ) || ( item_index >= (Py_ssize_t) sequence_object->number_of_items ) ) { PyErr_Format( PyExc_ValueError, "%s: invalid invalid item index value out of bounds.", function ); return( NULL ); } attribute_object = sequence_object->get_item_by_index( sequence_object->parent_object, (int) item_index ); return( attribute_object ); } /* The attributes iter() function */ PyObject *pyfsntfs_attributes_iter( pyfsntfs_attributes_t *sequence_object ) { static char *function = "pyfsntfs_attributes_iter"; if( sequence_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object.", function ); return( NULL ); } Py_IncRef( (PyObject *) sequence_object ); return( (PyObject *) sequence_object ); } /* The attributes iternext() function */ PyObject *pyfsntfs_attributes_iternext( pyfsntfs_attributes_t *sequence_object ) { PyObject *attribute_object = NULL; static char *function = "pyfsntfs_attributes_iternext"; if( sequence_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object.", function ); return( NULL ); } if( sequence_object->get_item_by_index == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object - missing get item by index function.", function ); return( NULL ); } if( sequence_object->current_index < 0 ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object - invalid current index.", function ); return( NULL ); } if( sequence_object->number_of_items < 0 ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object - invalid number of items.", function ); return( NULL ); } if( sequence_object->current_index >= sequence_object->number_of_items ) { PyErr_SetNone( PyExc_StopIteration ); return( NULL ); } attribute_object = sequence_object->get_item_by_index( sequence_object->parent_object, sequence_object->current_index ); if( attribute_object != NULL ) { sequence_object->current_index++; } return( attribute_object ); } ================================================ FILE: pyfsntfs/pyfsntfs_attributes.h ================================================ /* * Python object definition of the sequence and iterator object of attributes * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_ATTRIBUTES_H ) #define _PYFSNTFS_ATTRIBUTES_H #include #include #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct pyfsntfs_attributes pyfsntfs_attributes_t; struct pyfsntfs_attributes { /* Python object initialization */ PyObject_HEAD /* The parent object */ PyObject *parent_object; /* The get item by index callback function */ PyObject* (*get_item_by_index)( PyObject *parent_object, int index ); /* The current index */ int current_index; /* The number of items */ int number_of_items; }; extern PyTypeObject pyfsntfs_attributes_type_object; PyObject *pyfsntfs_attributes_new( PyObject *parent_object, PyObject* (*get_item_by_index)( PyObject *parent_object, int index ), int number_of_items ); int pyfsntfs_attributes_init( pyfsntfs_attributes_t *sequence_object ); void pyfsntfs_attributes_free( pyfsntfs_attributes_t *sequence_object ); Py_ssize_t pyfsntfs_attributes_len( pyfsntfs_attributes_t *sequence_object ); PyObject *pyfsntfs_attributes_getitem( pyfsntfs_attributes_t *sequence_object, Py_ssize_t item_index ); PyObject *pyfsntfs_attributes_iter( pyfsntfs_attributes_t *sequence_object ); PyObject *pyfsntfs_attributes_iternext( pyfsntfs_attributes_t *sequence_object ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_ATTRIBUTES_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_data_stream.c ================================================ /* * Python object wrapper of libfsntfs_data_stream_t * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_data_stream.h" #include "pyfsntfs_error.h" #include "pyfsntfs_integer.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #include "pyfsntfs_unused.h" PyMethodDef pyfsntfs_data_stream_object_methods[] = { /* Functions to access the data stream data */ { "read_buffer", (PyCFunction) pyfsntfs_data_stream_read_buffer, METH_VARARGS | METH_KEYWORDS, "read_buffer(size) -> String\n" "\n" "Reads a buffer of data stream data." }, { "read_buffer_at_offset", (PyCFunction) pyfsntfs_data_stream_read_buffer_at_offset, METH_VARARGS | METH_KEYWORDS, "read_buffer_at_offset(size, offset) -> String\n" "\n" "Reads a buffer of data stream data at a specific offset." }, { "seek_offset", (PyCFunction) pyfsntfs_data_stream_seek_offset, METH_VARARGS | METH_KEYWORDS, "seek_offset(offset, whence) -> None\n" "\n" "Seeks an offset within the data stream data." }, { "get_offset", (PyCFunction) pyfsntfs_data_stream_get_offset, METH_NOARGS, "get_offset() -> Integer\n" "\n" "Returns the current offset within the data stream data." }, /* Some Pythonesque aliases */ { "read", (PyCFunction) pyfsntfs_data_stream_read_buffer, METH_VARARGS | METH_KEYWORDS, "read(size) -> String\n" "\n" "Reads a buffer of data stream data." }, { "seek", (PyCFunction) pyfsntfs_data_stream_seek_offset, METH_VARARGS | METH_KEYWORDS, "seek(offset, whence) -> None\n" "\n" "Seeks an offset within the data stream data." }, { "tell", (PyCFunction) pyfsntfs_data_stream_get_offset, METH_NOARGS, "tell() -> Integer\n" "\n" "Returns the current offset within the data stream data." }, /* Functions to access the metadata */ { "get_size", (PyCFunction) pyfsntfs_data_stream_get_size, METH_NOARGS, "get_size() -> Integer\n" "\n" "Returns the size data." }, { "get_name", (PyCFunction) pyfsntfs_data_stream_get_name, METH_NOARGS, "get_name() -> Unicode string or None\n" "\n" "Returns the name." }, /* Functions to access the extents */ { "get_number_of_extents", (PyCFunction) pyfsntfs_data_stream_get_number_of_extents, METH_NOARGS, "get_number_of_extents() -> Integer\n" "\n" "Retrieves the number of extents." }, { "get_extent", (PyCFunction) pyfsntfs_data_stream_get_extent, METH_VARARGS | METH_KEYWORDS, "get_extent(extent_index) -> Tuple( Integer, Integer, Integer )\n" "\n" "Retrieves a specific extent.\t" "The extent is a tuple of offset, size and flags." }, /* Sentinel */ { NULL, NULL, 0, NULL } }; PyGetSetDef pyfsntfs_data_stream_object_get_set_definitions[] = { { "size", (getter) pyfsntfs_data_stream_get_size, (setter) 0, "The size of the data.", NULL }, { "name", (getter) pyfsntfs_data_stream_get_name, (setter) 0, "The name.", NULL }, { "number_of_extents", (getter) pyfsntfs_data_stream_get_number_of_extents, (setter) 0, "The number of extents.", NULL }, /* Sentinel */ { NULL, NULL, NULL, NULL, NULL } }; PyTypeObject pyfsntfs_data_stream_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs.data_stream", /* tp_basicsize */ sizeof( pyfsntfs_data_stream_t ), /* tp_itemsize */ 0, /* tp_dealloc */ (destructor) pyfsntfs_data_stream_free, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_doc */ "pyfsntfs data stream object (wraps libfsntfs_data_stream_t)", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ pyfsntfs_data_stream_object_methods, /* tp_members */ 0, /* tp_getset */ pyfsntfs_data_stream_object_get_set_definitions, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ (initproc) pyfsntfs_data_stream_init, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Creates a new data stream object * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_data_stream_new( libfsntfs_data_stream_t *data_stream, PyObject *parent_object ) { pyfsntfs_data_stream_t *pyfsntfs_data_stream = NULL; static char *function = "pyfsntfs_data_stream_new"; if( data_stream == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid data stream.", function ); return( NULL ); } /* PyObject_New does not invoke tp_init */ pyfsntfs_data_stream = PyObject_New( struct pyfsntfs_data_stream, &pyfsntfs_data_stream_type_object ); if( pyfsntfs_data_stream == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to initialize data stream.", function ); goto on_error; } pyfsntfs_data_stream->data_stream = data_stream; pyfsntfs_data_stream->parent_object = parent_object; if( pyfsntfs_data_stream->parent_object != NULL ) { Py_IncRef( pyfsntfs_data_stream->parent_object ); } return( (PyObject *) pyfsntfs_data_stream ); on_error: if( pyfsntfs_data_stream != NULL ) { Py_DecRef( (PyObject *) pyfsntfs_data_stream ); } return( NULL ); } /* Initializes a data stream object * Returns 0 if successful or -1 on error */ int pyfsntfs_data_stream_init( pyfsntfs_data_stream_t *pyfsntfs_data_stream ) { static char *function = "pyfsntfs_data_stream_init"; if( pyfsntfs_data_stream == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid data stream.", function ); return( -1 ); } /* Make sure libfsntfs data stream is set to NULL */ pyfsntfs_data_stream->data_stream = NULL; PyErr_Format( PyExc_NotImplementedError, "%s: initialize of data stream not supported.", function ); return( -1 ); } /* Frees a data stream object */ void pyfsntfs_data_stream_free( pyfsntfs_data_stream_t *pyfsntfs_data_stream ) { struct _typeobject *ob_type = NULL; libcerror_error_t *error = NULL; static char *function = "pyfsntfs_data_stream_free"; int result = 0; if( pyfsntfs_data_stream == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid data stream.", function ); return; } ob_type = Py_TYPE( pyfsntfs_data_stream ); if( ob_type == NULL ) { PyErr_Format( PyExc_ValueError, "%s: missing ob_type.", function ); return; } if( ob_type->tp_free == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid ob_type - missing tp_free.", function ); return; } if( pyfsntfs_data_stream->data_stream != NULL ) { Py_BEGIN_ALLOW_THREADS result = libfsntfs_data_stream_free( &( pyfsntfs_data_stream->data_stream ), &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_MemoryError, "%s: unable to free libfsntfs data stream.", function ); libcerror_error_free( &error ); } } if( pyfsntfs_data_stream->parent_object != NULL ) { Py_DecRef( pyfsntfs_data_stream->parent_object ); } ob_type->tp_free( (PyObject*) pyfsntfs_data_stream ); } /* Reads a buffer of data from the data stream * Returns a Python object holding the data if successful or NULL on error */ PyObject *pyfsntfs_data_stream_read_buffer( pyfsntfs_data_stream_t *pyfsntfs_data_stream, PyObject *arguments, PyObject *keywords ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; PyObject *string_object = NULL; static char *function = "pyfsntfs_data_stream_read_buffer"; static char *keyword_list[] = { "size", NULL }; char *buffer = NULL; size64_t read_size = 0; ssize_t read_count = 0; int result = 0; if( pyfsntfs_data_stream == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid pyfsntfs data stream.", function ); return( NULL ); } if( pyfsntfs_data_stream->data_stream == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid pyfsntfs data stream - missing libfsntfs data stream.", function ); return( NULL ); } if( PyArg_ParseTupleAndKeywords( arguments, keywords, "|O", keyword_list, &integer_object ) == 0 ) { return( NULL ); } if( integer_object != NULL ) { PyErr_Clear(); result = PyObject_IsInstance( integer_object, (PyObject *) &PyLong_Type ); if( result == -1 ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to determine if integer object is of type long.", function ); return( NULL ); } #if PY_MAJOR_VERSION < 3 else if( result == 0 ) { PyErr_Clear(); result = PyObject_IsInstance( integer_object, (PyObject *) &PyInt_Type ); if( result == -1 ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to determine if integer object is of type int.", function ); return( NULL ); } } #endif } if( result != 0 ) { if( pyfsntfs_integer_unsigned_copy_to_64bit( integer_object, (uint64_t *) &read_size, &error ) != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to convert integer object into read size.", function ); libcerror_error_free( &error ); return( NULL ); } } else if( ( integer_object == NULL ) || ( integer_object == Py_None ) ) { Py_BEGIN_ALLOW_THREADS result = libfsntfs_data_stream_get_size( pyfsntfs_data_stream->data_stream, &read_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve size.", function ); libcerror_error_free( &error ); return( NULL ); } } else { PyErr_Format( PyExc_ValueError, "%s: unsupported integer object type.", function ); return( NULL ); } if( read_size == 0 ) { #if PY_MAJOR_VERSION >= 3 string_object = PyBytes_FromString( "" ); #else string_object = PyString_FromString( "" ); #endif return( string_object ); } /* Make sure the data fits into a memory buffer */ if( ( read_size > (size64_t) INT_MAX ) || ( read_size > (size64_t) SSIZE_MAX ) ) { PyErr_Format( PyExc_ValueError, "%s: invalid argument read size value exceeds maximum.", function ); return( NULL ); } #if PY_MAJOR_VERSION >= 3 string_object = PyBytes_FromStringAndSize( NULL, read_size ); buffer = PyBytes_AsString( string_object ); #else /* Note that a size of 0 is not supported */ string_object = PyString_FromStringAndSize( NULL, read_size ); buffer = PyString_AsString( string_object ); #endif Py_BEGIN_ALLOW_THREADS read_count = libfsntfs_data_stream_read_buffer( pyfsntfs_data_stream->data_stream, (uint8_t *) buffer, (size_t) read_size, &error ); Py_END_ALLOW_THREADS if( read_count <= -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to read data.", function ); libcerror_error_free( &error ); Py_DecRef( (PyObject *) string_object ); return( NULL ); } /* Need to resize the string here in case read_size was not fully read. */ #if PY_MAJOR_VERSION >= 3 if( _PyBytes_Resize( &string_object, (Py_ssize_t) read_count ) != 0 ) #else if( _PyString_Resize( &string_object, (Py_ssize_t) read_count ) != 0 ) #endif { Py_DecRef( (PyObject *) string_object ); return( NULL ); } return( string_object ); } /* Reads a buffer of data at a specific offset from the data stream * Returns a Python object holding the data if successful or NULL on error */ PyObject *pyfsntfs_data_stream_read_buffer_at_offset( pyfsntfs_data_stream_t *pyfsntfs_data_stream, PyObject *arguments, PyObject *keywords ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; PyObject *string_object = NULL; static char *function = "pyfsntfs_data_stream_read_buffer_at_offset"; static char *keyword_list[] = { "size", "offset", NULL }; char *buffer = NULL; off64_t read_offset = 0; size64_t read_size = 0; ssize_t read_count = 0; int result = 0; if( pyfsntfs_data_stream == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid pyfsntfs data stream.", function ); return( NULL ); } if( pyfsntfs_data_stream->data_stream == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid pyfsntfs data stream - missing libfsntfs data stream.", function ); return( NULL ); } if( PyArg_ParseTupleAndKeywords( arguments, keywords, "OL", keyword_list, &integer_object, &read_offset ) == 0 ) { return( NULL ); } result = PyObject_IsInstance( integer_object, (PyObject *) &PyLong_Type ); if( result == -1 ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to determine if integer object is of type long.", function ); return( NULL ); } #if PY_MAJOR_VERSION < 3 else if( result == 0 ) { PyErr_Clear(); result = PyObject_IsInstance( integer_object, (PyObject *) &PyInt_Type ); if( result == -1 ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to determine if integer object is of type int.", function ); return( NULL ); } } #endif if( result != 0 ) { if( pyfsntfs_integer_unsigned_copy_to_64bit( integer_object, (uint64_t *) &read_size, &error ) != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to convert integer object into read size.", function ); libcerror_error_free( &error ); return( NULL ); } } else if( integer_object == Py_None ) { Py_BEGIN_ALLOW_THREADS result = libfsntfs_data_stream_get_size( pyfsntfs_data_stream->data_stream, &read_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve size.", function ); libcerror_error_free( &error ); return( NULL ); } } else { PyErr_Format( PyExc_TypeError, "%s: unsupported integer object type.", function ); return( NULL ); } if( read_size == 0 ) { #if PY_MAJOR_VERSION >= 3 string_object = PyBytes_FromString( "" ); #else string_object = PyString_FromString( "" ); #endif return( string_object ); } /* Make sure the data fits into a memory buffer */ if( ( read_size > (size64_t) INT_MAX ) || ( read_size > (size64_t) SSIZE_MAX ) ) { PyErr_Format( PyExc_ValueError, "%s: invalid argument read size value exceeds maximum.", function ); return( NULL ); } #if PY_MAJOR_VERSION >= 3 string_object = PyBytes_FromStringAndSize( NULL, read_size ); buffer = PyBytes_AsString( string_object ); #else /* Note that a size of 0 is not supported */ string_object = PyString_FromStringAndSize( NULL, read_size ); buffer = PyString_AsString( string_object ); #endif Py_BEGIN_ALLOW_THREADS read_count = libfsntfs_data_stream_read_buffer_at_offset( pyfsntfs_data_stream->data_stream, (uint8_t *) buffer, (size_t) read_size, (off64_t) read_offset, &error ); Py_END_ALLOW_THREADS if( read_count <= -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to read data.", function ); libcerror_error_free( &error ); Py_DecRef( (PyObject *) string_object ); return( NULL ); } /* Need to resize the string here in case read_size was not fully read. */ #if PY_MAJOR_VERSION >= 3 if( _PyBytes_Resize( &string_object, (Py_ssize_t) read_count ) != 0 ) #else if( _PyString_Resize( &string_object, (Py_ssize_t) read_count ) != 0 ) #endif { Py_DecRef( (PyObject *) string_object ); return( NULL ); } return( string_object ); } /* Seeks a certain offset in the data stream data * Returns a Python object holding the offset if successful or NULL on error */ PyObject *pyfsntfs_data_stream_seek_offset( pyfsntfs_data_stream_t *pyfsntfs_data_stream, PyObject *arguments, PyObject *keywords ) { libcerror_error_t *error = NULL; static char *function = "pyfsntfs_data_stream_seek_offset"; static char *keyword_list[] = { "offset", "whence", NULL }; off64_t offset = 0; int whence = 0; if( pyfsntfs_data_stream == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid pyfsntfs data stream.", function ); return( NULL ); } if( pyfsntfs_data_stream->data_stream == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid pyfsntfs data stream - missing libfsntfs data stream.", function ); return( NULL ); } if( PyArg_ParseTupleAndKeywords( arguments, keywords, "L|i", keyword_list, &offset, &whence ) == 0 ) { return( NULL ); } Py_BEGIN_ALLOW_THREADS offset = libfsntfs_data_stream_seek_offset( pyfsntfs_data_stream->data_stream, offset, whence, &error ); Py_END_ALLOW_THREADS if( offset == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to seek offset.", function ); libcerror_error_free( &error ); return( NULL ); } Py_IncRef( Py_None ); return( Py_None ); } /* Retrieves the offset * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_data_stream_get_offset( pyfsntfs_data_stream_t *pyfsntfs_data_stream, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_data_stream_get_offset"; off64_t offset = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_data_stream == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid data stream.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_data_stream_get_offset( pyfsntfs_data_stream->data_stream, &offset, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve offset.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_signed_new_from_64bit( (int64_t) offset ); return( integer_object ); } /* Retrieves the size * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_data_stream_get_size( pyfsntfs_data_stream_t *pyfsntfs_data_stream, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_data_stream_get_size"; size64_t size = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_data_stream == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid data stream.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_data_stream_get_size( pyfsntfs_data_stream->data_stream, &size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve size.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( (uint64_t) size ); return( integer_object ); } /* Retrieves the name * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_data_stream_get_name( pyfsntfs_data_stream_t *pyfsntfs_data_stream, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *string_object = NULL; uint8_t *name = NULL; static char *function = "pyfsntfs_data_stream_get_name"; size_t name_size = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_data_stream == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid data stream.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_data_stream_get_utf8_name_size( pyfsntfs_data_stream->data_stream, &name_size, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve name size.", function ); libcerror_error_free( &error ); goto on_error; } else if( ( result == 0 ) || ( name_size == 0 ) ) { Py_IncRef( Py_None ); return( Py_None ); } name = (uint8_t *) PyMem_Malloc( sizeof( uint8_t ) * name_size ); if( name == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create name.", function ); goto on_error; } Py_BEGIN_ALLOW_THREADS result = libfsntfs_data_stream_get_utf8_name( pyfsntfs_data_stream->data_stream, name, name_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve name.", function ); libcerror_error_free( &error ); goto on_error; } /* Pass the string length to PyUnicode_DecodeUTF8 * otherwise it makes the end of string character is part * of the string */ string_object = PyUnicode_DecodeUTF8( (char *) name, (Py_ssize_t) name_size - 1, NULL ); PyMem_Free( name ); return( string_object ); on_error: if( name != NULL ) { PyMem_Free( name ); } return( NULL ); } /* Retrieves the number of extents * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_data_stream_get_number_of_extents( pyfsntfs_data_stream_t *pyfsntfs_data_stream, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_data_stream_get_number_of_extents"; int number_of_extents = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_data_stream == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid data stream.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_data_stream_get_number_of_extents( pyfsntfs_data_stream->data_stream, &number_of_extents, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve number of extents.", function ); libcerror_error_free( &error ); return( NULL ); } #if PY_MAJOR_VERSION >= 3 integer_object = PyLong_FromLong( (long) number_of_extents ); #else integer_object = PyInt_FromLong( (long) number_of_extents ); #endif return( integer_object ); } /* Retrieves a specific extent by index * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_data_stream_get_extent_by_index( pyfsntfs_data_stream_t *pyfsntfs_data_stream, int extent_index ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; PyObject *tuple_object = NULL; static char *function = "pyfsntfs_data_stream_get_extent_by_index"; off64_t extent_offset = 0; size64_t extent_size = 0; uint32_t extent_flags = 0; int result = 0; if( pyfsntfs_data_stream == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid data stream.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_data_stream_get_extent_by_index( pyfsntfs_data_stream->data_stream, extent_index, &extent_offset, &extent_size, &extent_flags, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve extent: %d.", function, extent_index ); libcerror_error_free( &error ); goto on_error; } tuple_object = PyTuple_New( 3 ); integer_object = pyfsntfs_integer_signed_new_from_64bit( (int64_t) extent_offset ); /* Tuple set item does not increment the reference count of the integer object */ if( PyTuple_SetItem( tuple_object, 0, integer_object ) != 0 ) { goto on_error; } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( (uint64_t) extent_size ); /* Tuple set item does not increment the reference count of the integer object */ if( PyTuple_SetItem( tuple_object, 1, integer_object ) != 0 ) { goto on_error; } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( (uint64_t) extent_flags ); /* Tuple set item does not increment the reference count of the integer object */ if( PyTuple_SetItem( tuple_object, 2, integer_object ) != 0 ) { goto on_error; } return( tuple_object ); on_error: if( integer_object != NULL ) { Py_DecRef( (PyObject *) integer_object ); } if( tuple_object != NULL ) { Py_DecRef( (PyObject *) tuple_object ); } return( NULL ); } /* Retrieves a specific extent * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_data_stream_get_extent( pyfsntfs_data_stream_t *pyfsntfs_data_stream, PyObject *arguments, PyObject *keywords ) { PyObject *sequence_object = NULL; static char *keyword_list[] = { "extent_index", NULL }; int extent_index = 0; if( PyArg_ParseTupleAndKeywords( arguments, keywords, "i", keyword_list, &extent_index ) == 0 ) { return( NULL ); } sequence_object = pyfsntfs_data_stream_get_extent_by_index( pyfsntfs_data_stream, extent_index ); return( sequence_object ); } ================================================ FILE: pyfsntfs/pyfsntfs_data_stream.h ================================================ /* * Python object wrapper of libfsntfs_data_stream_t * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_DATA_STREAM_H ) #define _PYFSNTFS_DATA_STREAM_H #include #include #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct pyfsntfs_data_stream pyfsntfs_data_stream_t; struct pyfsntfs_data_stream { /* Python object initialization */ PyObject_HEAD /* The libfsntfs data stream */ libfsntfs_data_stream_t *data_stream; /* The parent object */ PyObject *parent_object; }; extern PyMethodDef pyfsntfs_data_stream_object_methods[]; extern PyTypeObject pyfsntfs_data_stream_type_object; PyObject *pyfsntfs_data_stream_new( libfsntfs_data_stream_t *data_stream, PyObject *parent_object ); int pyfsntfs_data_stream_init( pyfsntfs_data_stream_t *pyfsntfs_data_stream ); void pyfsntfs_data_stream_free( pyfsntfs_data_stream_t *pyfsntfs_data_stream ); PyObject *pyfsntfs_data_stream_read_buffer( pyfsntfs_data_stream_t *pyfsntfs_data_stream, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_data_stream_read_buffer_at_offset( pyfsntfs_data_stream_t *pyfsntfs_data_stream, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_data_stream_seek_offset( pyfsntfs_data_stream_t *pyfsntfs_data_stream, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_data_stream_get_offset( pyfsntfs_data_stream_t *pyfsntfs_data_stream, PyObject *arguments ); PyObject *pyfsntfs_data_stream_get_size( pyfsntfs_data_stream_t *pyfsntfs_data_stream, PyObject *arguments ); PyObject *pyfsntfs_data_stream_get_name( pyfsntfs_data_stream_t *pyfsntfs_data_stream, PyObject *arguments ); PyObject *pyfsntfs_data_stream_get_number_of_extents( pyfsntfs_data_stream_t *pyfsntfs_data_stream, PyObject *arguments ); PyObject *pyfsntfs_data_stream_get_extent_by_index( pyfsntfs_data_stream_t *pyfsntfs_data_stream, int extent_index ); PyObject *pyfsntfs_data_stream_get_extent( pyfsntfs_data_stream_t *pyfsntfs_data_stream, PyObject *arguments, PyObject *keywords ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_DATA_STREAM_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_data_streams.c ================================================ /* * Python object definition of the sequence and iterator object of data streams * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_data_stream.h" #include "pyfsntfs_data_streams.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" PySequenceMethods pyfsntfs_data_streams_sequence_methods = { /* sq_length */ (lenfunc) pyfsntfs_data_streams_len, /* sq_concat */ 0, /* sq_repeat */ 0, /* sq_item */ (ssizeargfunc) pyfsntfs_data_streams_getitem, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ 0, /* sq_contains */ 0, /* sq_inplace_concat */ 0, /* sq_inplace_repeat */ 0 }; PyTypeObject pyfsntfs_data_streams_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs.data_streams", /* tp_basicsize */ sizeof( pyfsntfs_data_streams_t ), /* tp_itemsize */ 0, /* tp_dealloc */ (destructor) pyfsntfs_data_streams_free, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ &pyfsntfs_data_streams_sequence_methods, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /* tp_doc */ "pyfsntfs sequence and iterator object of data streams", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ (getiterfunc) pyfsntfs_data_streams_iter, /* tp_iternext */ (iternextfunc) pyfsntfs_data_streams_iternext, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ (initproc) pyfsntfs_data_streams_init, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Creates a new data streams sequence and iterator object * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_data_streams_new( PyObject *parent_object, PyObject* (*get_item_by_index)( PyObject *parent_object, int index ), int number_of_items ) { pyfsntfs_data_streams_t *sequence_object = NULL; static char *function = "pyfsntfs_data_streams_new"; if( parent_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid parent object.", function ); return( NULL ); } if( get_item_by_index == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid get item by index function.", function ); return( NULL ); } /* Make sure the data streams values are initialized */ sequence_object = PyObject_New( struct pyfsntfs_data_streams, &pyfsntfs_data_streams_type_object ); if( sequence_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create sequence object.", function ); goto on_error; } sequence_object->parent_object = parent_object; sequence_object->get_item_by_index = get_item_by_index; sequence_object->current_index = 0; sequence_object->number_of_items = number_of_items; Py_IncRef( (PyObject *) sequence_object->parent_object ); return( (PyObject *) sequence_object ); on_error: if( sequence_object != NULL ) { Py_DecRef( (PyObject *) sequence_object ); } return( NULL ); } /* Initializes a data streams sequence and iterator object * Returns 0 if successful or -1 on error */ int pyfsntfs_data_streams_init( pyfsntfs_data_streams_t *sequence_object ) { static char *function = "pyfsntfs_data_streams_init"; if( sequence_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object.", function ); return( -1 ); } /* Make sure the data streams values are initialized */ sequence_object->parent_object = NULL; sequence_object->get_item_by_index = NULL; sequence_object->current_index = 0; sequence_object->number_of_items = 0; PyErr_Format( PyExc_NotImplementedError, "%s: initialize of data streams not supported.", function ); return( -1 ); } /* Frees a data streams sequence object */ void pyfsntfs_data_streams_free( pyfsntfs_data_streams_t *sequence_object ) { struct _typeobject *ob_type = NULL; static char *function = "pyfsntfs_data_streams_free"; if( sequence_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object.", function ); return; } ob_type = Py_TYPE( sequence_object ); if( ob_type == NULL ) { PyErr_Format( PyExc_ValueError, "%s: missing ob_type.", function ); return; } if( ob_type->tp_free == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid ob_type - missing tp_free.", function ); return; } if( sequence_object->parent_object != NULL ) { Py_DecRef( (PyObject *) sequence_object->parent_object ); } ob_type->tp_free( (PyObject*) sequence_object ); } /* The data streams len() function */ Py_ssize_t pyfsntfs_data_streams_len( pyfsntfs_data_streams_t *sequence_object ) { static char *function = "pyfsntfs_data_streams_len"; if( sequence_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object.", function ); return( -1 ); } return( (Py_ssize_t) sequence_object->number_of_items ); } /* The data streams getitem() function */ PyObject *pyfsntfs_data_streams_getitem( pyfsntfs_data_streams_t *sequence_object, Py_ssize_t item_index ) { PyObject *data_stream_object = NULL; static char *function = "pyfsntfs_data_streams_getitem"; if( sequence_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object.", function ); return( NULL ); } if( sequence_object->get_item_by_index == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object - missing get item by index function.", function ); return( NULL ); } if( sequence_object->number_of_items < 0 ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object - invalid number of items.", function ); return( NULL ); } if( ( item_index < 0 ) || ( item_index >= (Py_ssize_t) sequence_object->number_of_items ) ) { PyErr_Format( PyExc_ValueError, "%s: invalid invalid item index value out of bounds.", function ); return( NULL ); } data_stream_object = sequence_object->get_item_by_index( sequence_object->parent_object, (int) item_index ); return( data_stream_object ); } /* The data streams iter() function */ PyObject *pyfsntfs_data_streams_iter( pyfsntfs_data_streams_t *sequence_object ) { static char *function = "pyfsntfs_data_streams_iter"; if( sequence_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object.", function ); return( NULL ); } Py_IncRef( (PyObject *) sequence_object ); return( (PyObject *) sequence_object ); } /* The data streams iternext() function */ PyObject *pyfsntfs_data_streams_iternext( pyfsntfs_data_streams_t *sequence_object ) { PyObject *data_stream_object = NULL; static char *function = "pyfsntfs_data_streams_iternext"; if( sequence_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object.", function ); return( NULL ); } if( sequence_object->get_item_by_index == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object - missing get item by index function.", function ); return( NULL ); } if( sequence_object->current_index < 0 ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object - invalid current index.", function ); return( NULL ); } if( sequence_object->number_of_items < 0 ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object - invalid number of items.", function ); return( NULL ); } if( sequence_object->current_index >= sequence_object->number_of_items ) { PyErr_SetNone( PyExc_StopIteration ); return( NULL ); } data_stream_object = sequence_object->get_item_by_index( sequence_object->parent_object, sequence_object->current_index ); if( data_stream_object != NULL ) { sequence_object->current_index++; } return( data_stream_object ); } ================================================ FILE: pyfsntfs/pyfsntfs_data_streams.h ================================================ /* * Python object definition of the sequence and iterator object of data streams * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_DATA_STREAMS_H ) #define _PYFSNTFS_DATA_STREAMS_H #include #include #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct pyfsntfs_data_streams pyfsntfs_data_streams_t; struct pyfsntfs_data_streams { /* Python object initialization */ PyObject_HEAD /* The parent object */ PyObject *parent_object; /* The get item by index callback function */ PyObject* (*get_item_by_index)( PyObject *parent_object, int index ); /* The current index */ int current_index; /* The number of items */ int number_of_items; }; extern PyTypeObject pyfsntfs_data_streams_type_object; PyObject *pyfsntfs_data_streams_new( PyObject *parent_object, PyObject* (*get_item_by_index)( PyObject *parent_object, int index ), int number_of_items ); int pyfsntfs_data_streams_init( pyfsntfs_data_streams_t *sequence_object ); void pyfsntfs_data_streams_free( pyfsntfs_data_streams_t *sequence_object ); Py_ssize_t pyfsntfs_data_streams_len( pyfsntfs_data_streams_t *sequence_object ); PyObject *pyfsntfs_data_streams_getitem( pyfsntfs_data_streams_t *sequence_object, Py_ssize_t item_index ); PyObject *pyfsntfs_data_streams_iter( pyfsntfs_data_streams_t *sequence_object ); PyObject *pyfsntfs_data_streams_iternext( pyfsntfs_data_streams_t *sequence_object ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_DATA_STREAMS_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_datetime.c ================================================ /* * Date and time functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "pyfsntfs_datetime.h" #include "pyfsntfs_python.h" #include /* Creates a new datetime object from date and time elements * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_datetime_new_from_time_elements( uint16_t year, uint64_t number_of_days, uint8_t hours, uint8_t minutes, uint8_t seconds, uint32_t micro_seconds ) { PyObject *datetime_object = NULL; static char *function = "pyfsntfs_datetime_new_from_time_elements"; uint32_t days_in_century = 0; uint16_t days_in_year = 0; uint8_t day_of_month = 0; uint8_t days_in_month = 0; uint8_t month = 0; while( number_of_days > 0 ) { if( ( year % 400 ) == 0 ) { days_in_century = 36525; } else { days_in_century = 36524; } if( number_of_days <= days_in_century ) { break; } number_of_days -= days_in_century; year += 100; } while( number_of_days > 0 ) { /* Check for a leap year * The year is ( ( dividable by 4 ) and ( not dividable by 100 ) ) or ( dividable by 400 ) */ if( ( ( ( year % 4 ) == 0 ) && ( ( year % 100 ) != 0 ) ) || ( ( year % 400 ) == 0 ) ) { days_in_year = 366; } else { days_in_year = 365; } if( number_of_days <= days_in_year ) { break; } number_of_days -= days_in_year; year += 1; } /* Determine the month correct the value to days within the month */ month = 1; while( number_of_days > 0 ) { /* February (2) */ if( month == 2 ) { if( ( ( ( year % 4 ) == 0 ) && ( ( year % 100 ) != 0 ) ) || ( ( year % 400 ) == 0 ) ) { days_in_month = 29; } else { days_in_month = 28; } } /* April (4), June (6), September (9), November (11) */ else if( ( month == 4 ) || ( month == 6 ) || ( month == 9 ) || ( month == 11 ) ) { days_in_month = 30; } /* January (1), March (3), May (5), July (7), August (8), October (10), December (12) */ else if( ( month == 1 ) || ( month == 3 ) || ( month == 5 ) || ( month == 7 ) || ( month == 8 ) || ( month == 10 ) || ( month == 12 ) ) { days_in_month = 31; } /* This should never happen, but just in case */ else { PyErr_Format( PyExc_IOError, "%s: unsupported month: %" PRIu8 ".", function, month ); return( NULL ); } if( number_of_days <= days_in_month ) { break; } number_of_days -= days_in_month; month += 1; } /* Determine the day */ day_of_month = (uint8_t) number_of_days; PyDateTime_IMPORT; datetime_object = (PyObject *) PyDateTime_FromDateAndTime( (int) year, (int) month, (int) day_of_month, (int) hours, (int) minutes, (int) seconds, (int) micro_seconds ); return( datetime_object ); } /* Creates a new datetime object from a FAT date time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_datetime_new_from_fat_date_time( uint32_t fat_date_time ) { PyObject *datetime_object = NULL; static char *function = "pyfsntfs_datetime_new_from_fat_date_time"; uint16_t year = 0; uint8_t day_of_month = 0; uint8_t days_in_month = 0; uint8_t hours = 0; uint8_t minutes = 0; uint8_t month = 0; uint8_t seconds = 0; /* The day of month is stored in the next 5 bits */ day_of_month = fat_date_time & 0x1f; fat_date_time >>= 5; /* The month is stored in the next 4 bits */ month = fat_date_time & 0x0f; fat_date_time >>= 4; /* The year is stored in the next 7 bits starting at 1980 */ year = 1980 + ( fat_date_time & 0x7f ); fat_date_time >>= 7; /* The number of seconds are stored in the lower 5 bits * in intervals of 2 seconds */ seconds = ( fat_date_time & 0x1f ) * 2; fat_date_time >>= 5; /* The number of minutes are stored in the next 6 bits */ minutes = fat_date_time & 0x3f; fat_date_time >>= 6; /* The number of hours are stored in the next 5 bits */ hours = fat_date_time & 0x1f; /* February (2) */ if( month == 2 ) { if( ( ( ( year % 4 ) == 0 ) && ( ( year % 100 ) != 0 ) ) || ( ( year % 400 ) == 0 ) ) { days_in_month = 29; } else { days_in_month = 28; } } /* April (4), June (6), September (9), November (11) */ else if( ( month == 4 ) || ( month == 6 ) || ( month == 9 ) || ( month == 11 ) ) { days_in_month = 30; } /* January (1), March (3), May (5), July (7), August (8), October (10), December (12) */ else if( ( month == 1 ) || ( month == 3 ) || ( month == 5 ) || ( month == 7 ) || ( month == 8 ) || ( month == 10 ) || ( month == 12 ) ) { days_in_month = 31; } else { PyErr_Format( PyExc_IOError, "%s: unsupported month: %" PRIu8 ".", function, month ); return( NULL ); } if( ( day_of_month == 0 ) || ( day_of_month > days_in_month ) ) { PyErr_Format( PyExc_IOError, "%s: unsupported day of month: %" PRIu8 ".", function, day_of_month ); return( NULL ); } PyDateTime_IMPORT; datetime_object = (PyObject *) PyDateTime_FromDateAndTime( (int) year, (int) month, (int) day_of_month, (int) hours, (int) minutes, (int) seconds, 0 ); return( datetime_object ); } /* Creates a new datetime object from a FILETIME * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_datetime_new_from_filetime( uint64_t filetime ) { PyObject *datetime_object = NULL; uint32_t micro_seconds = 0; uint16_t year = 0; uint8_t hours = 0; uint8_t minutes = 0; uint8_t seconds = 0; /* The timestamp is in units of 100 nano seconds correct the value to seconds */ micro_seconds = (uint32_t) ( filetime % 10000000 ) / 10; filetime /= 10000000; /* There are 60 seconds in a minute correct the value to minutes */ seconds = (uint8_t) ( filetime % 60 ); filetime /= 60; /* There are 60 minutes in an hour correct the value to hours */ minutes = (uint8_t) ( filetime % 60 ); filetime /= 60; /* There are 24 hours in a day correct the value to days */ hours = (uint8_t) ( filetime % 24 ); filetime /= 24; /* Add 1 day to compensate that Jan 1 1601 is represented as 0 */ filetime += 1; /* Determine the number of years starting at '1 Jan 1601 00:00:00' * correct the value to days within the year */ year = 1601; if( filetime >= 36159 ) { year = 1700; filetime -= 36159; } datetime_object = pyfsntfs_datetime_new_from_time_elements( year, filetime, hours, minutes, seconds, micro_seconds ); return( datetime_object ); } /* Creates a new datetime object from a floatingtime * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_datetime_new_from_floatingtime( uint64_t floatingtime ) { byte_stream_float64_t timestamp; PyObject *datetime_object = NULL; static char *function = "pyfsntfs_datetime_new_from_floatingtime"; uint32_t days_in_century = 0; uint32_t micro_seconds = 0; uint16_t days_in_year = 0; uint16_t year = 0; uint8_t day_of_month = 0; uint8_t days_in_month = 0; uint8_t hours = 0; uint8_t minutes = 0; uint8_t month = 0; uint8_t seconds = 0; timestamp.integer = floatingtime; /* Determine the number of years starting at '30 Dec 1899 00:00:00' * correct the value to days within the year */ year = 1899; if( timestamp.floating_point >= 2 ) { year = 1900; timestamp.floating_point -= 2; } while( timestamp.floating_point > 0 ) { if( ( year % 400 ) == 0 ) { days_in_century = 36525; } else { days_in_century = 36524; } if( timestamp.floating_point <= days_in_century ) { break; } timestamp.floating_point -= days_in_century; year += 100; } while( timestamp.floating_point > 0 ) { /* Check for a leap year * The year is ( ( dividable by 4 ) and ( not dividable by 100 ) ) or ( dividable by 400 ) */ if( ( ( ( year % 4 ) == 0 ) && ( ( year % 100 ) != 0 ) ) || ( ( year % 400 ) == 0 ) ) { days_in_year = 366; } else { days_in_year = 365; } if( timestamp.floating_point <= days_in_year ) { break; } timestamp.floating_point -= days_in_year; year += 1; } /* Determine the month correct the value to days within the month */ month = 1; while( timestamp.floating_point > 0 ) { /* February (2) */ if( month == 2 ) { if( ( ( ( year % 4 ) == 0 ) && ( ( year % 100 ) != 0 ) ) || ( ( year % 400 ) == 0 ) ) { days_in_month = 29; } else { days_in_month = 28; } } /* April (4), June (6), September (9), November (11) */ else if( ( month == 4 ) || ( month == 6 ) || ( month == 9 ) || ( month == 11 ) ) { days_in_month = 30; } /* January (1), March (3), May (5), July (7), August (8), October (10), December (12) */ else if( ( month == 1 ) || ( month == 3 ) || ( month == 5 ) || ( month == 7 ) || ( month == 8 ) || ( month == 10 ) || ( month == 12 ) ) { days_in_month = 31; } /* This should never happen, but just in case */ else { PyErr_Format( PyExc_IOError, "%s: unsupported month: %" PRIu8 ".", function, month ); return( NULL ); } if( timestamp.floating_point <= days_in_month ) { break; } timestamp.floating_point -= days_in_month; month += 1; } /* Determine the day */ day_of_month = (uint8_t) timestamp.floating_point; timestamp.floating_point -= day_of_month; /* There are 24 hours in a day correct the value to hours */ timestamp.floating_point *= 24; hours = (uint8_t) timestamp.floating_point; timestamp.floating_point -= hours; /* There are 60 minutes in an hour correct the value to minutes */ timestamp.floating_point *= 60; minutes = (uint8_t) timestamp.floating_point; timestamp.floating_point -= minutes; /* There are 60 seconds in a minute correct the value to seconds */ timestamp.floating_point *= 60; seconds = (uint8_t) timestamp.floating_point; timestamp.floating_point -= seconds; /* There are 1000 micro seconds in a seconds correct the value to micro seconds */ timestamp.floating_point *= 1000000; micro_seconds = (uint8_t) timestamp.floating_point; timestamp.floating_point -= micro_seconds; PyDateTime_IMPORT; datetime_object = (PyObject *) PyDateTime_FromDateAndTime( (int) year, (int) month, (int) day_of_month, (int) hours, (int) minutes, (int) seconds, (int) micro_seconds ); return( datetime_object ); } /* Creates a new datetime object from a HFS time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_datetime_new_from_hfs_time( uint32_t hfs_time ) { PyObject *datetime_object = NULL; uint16_t year = 0; uint8_t hours = 0; uint8_t minutes = 0; uint8_t seconds = 0; /* There are 60 seconds in a minute correct the value to minutes */ seconds = (uint8_t) ( hfs_time % 60 ); hfs_time /= 60; /* There are 60 minutes in an hour correct the value to hours */ minutes = (uint8_t) ( hfs_time % 60 ); hfs_time /= 60; /* There are 24 hours in a day correct the value to days */ hours = (uint8_t) ( hfs_time % 24 ); hfs_time /= 24; /* Add 1 day to compensate that Jan 1 1904 is represented as 0 */ hfs_time += 1; /* Determine the number of years starting at '1 Jan 1904 00:00:00' * correct the value to days within the year */ year = 1904; if( hfs_time >= 35064 ) { year = 2000; hfs_time -= 35064; } datetime_object = pyfsntfs_datetime_new_from_time_elements( year, (uint64_t) hfs_time, hours, minutes, seconds, 0 ); return( datetime_object ); } /* Creates a new datetime object from a POSIX time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_datetime_new_from_posix_time( int64_t posix_time ) { PyObject *datetime_object = NULL; uint16_t year = 0; uint8_t hours = 0; uint8_t minutes = 0; uint8_t seconds = 0; /* There are 60 seconds in a minute correct the value to minutes */ seconds = posix_time % 60; posix_time /= 60; /* There are 60 minutes in an hour correct the value to hours */ minutes = posix_time % 60; posix_time /= 60; /* There are 24 hours in a day correct the value to days */ hours = posix_time % 24; posix_time /= 24; /* Add 1 day to compensate that Jan 1 1601 is represented as 0 */ posix_time += 1; /* Determine the number of years starting at '1 Jan 1970 00:00:00' * correct the value to days within the year */ year = 1970; if( posix_time >= 10957 ) { year = 2000; posix_time -= 10957; } datetime_object = pyfsntfs_datetime_new_from_time_elements( year, (uint64_t) posix_time, hours, minutes, seconds, 0 ); return( datetime_object ); } /* Creates a new datetime object from a POSIX time in micro seconds * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_datetime_new_from_posix_time_in_micro_seconds( int64_t posix_time ) { PyObject *datetime_object = NULL; uint32_t micro_seconds = 0; uint16_t year = 0; uint8_t hours = 0; uint8_t minutes = 0; uint8_t seconds = 0; /* There are 1000000 micro seconds in a second correct the value to seconds */ micro_seconds = (uint32_t) ( posix_time % 1000000 ); posix_time /= 1000000; /* There are 60 seconds in a minute correct the value to minutes */ seconds = posix_time % 60; posix_time /= 60; /* There are 60 minutes in an hour correct the value to hours */ minutes = posix_time % 60; posix_time /= 60; /* There are 24 hours in a day correct the value to days */ hours = posix_time % 24; posix_time /= 24; /* Add 1 day to compensate that Jan 1 1970 is represented as 0 */ posix_time += 1; /* Determine the number of years starting at '1 Jan 1970 00:00:00' * correct the value to days within the year */ year = 1970; if( posix_time >= 10957 ) { year = 2000; posix_time -= 10957; } datetime_object = pyfsntfs_datetime_new_from_time_elements( year, (uint64_t) posix_time, hours, minutes, seconds, micro_seconds ); return( datetime_object ); } ================================================ FILE: pyfsntfs/pyfsntfs_datetime.h ================================================ /* * Date and time functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_DATETIME_H ) #define _PYFSNTFS_DATETIME_H #include #include #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif PyObject *pyfsntfs_datetime_new_from_time_elements( uint16_t year, uint64_t number_of_days, uint8_t hours, uint8_t minutes, uint8_t seconds, uint32_t micro_seconds ); PyObject *pyfsntfs_datetime_new_from_fat_date_time( uint32_t fat_date_time ); PyObject *pyfsntfs_datetime_new_from_filetime( uint64_t filetime ); PyObject *pyfsntfs_datetime_new_from_floatingtime( uint64_t floatingtime ); PyObject *pyfsntfs_datetime_new_from_hfs_time( uint32_t hfs_time ); PyObject *pyfsntfs_datetime_new_from_posix_time( int64_t posix_time ); PyObject *pyfsntfs_datetime_new_from_posix_time_in_micro_seconds( int64_t posix_time ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_DATETIME_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_error.c ================================================ /* * Error functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDARG_H ) || defined( WINAPI ) #include #elif defined( HAVE_VARARGS_H ) #include #else #error Missing headers stdarg.h and varargs.h #endif #include "pyfsntfs_error.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_python.h" #if defined( HAVE_STDARG_H ) || defined( WINAPI ) #define VARARGS( function, error, error_domain, error_code, type, argument ) \ function( error, error_domain, error_code, type argument, ... ) #define VASTART( argument_list, type, name ) \ va_start( argument_list, name ) #define VAEND( argument_list ) \ va_end( argument_list ) #elif defined( HAVE_VARARGS_H ) #define VARARGS( function, error, error_domain, error_code, type, argument ) \ function( error, error_domain, error_code, va_alist ) va_dcl #define VASTART( argument_list, type, name ) \ { type name; va_start( argument_list ); name = va_arg( argument_list, type ) #define VAEND( argument_list ) \ va_end( argument_list ); } #endif /* Fetches an error */ void VARARGS( pyfsntfs_error_fetch, libcerror_error_t **error, int error_domain, int error_code, const char *, format_string ) { va_list argument_list; char error_string[ PYFSNTFS_ERROR_STRING_SIZE ]; PyObject *exception_traceback = NULL; PyObject *exception_type = NULL; PyObject *exception_value = NULL; PyObject *string_object = NULL; static char *function = "pyfsntfs_error_fetch"; char *exception_string = NULL; size_t error_string_length = 0; int print_count = 0; #if PY_MAJOR_VERSION >= 3 PyObject *utf8_string_object = NULL; #endif if( format_string == NULL ) { PyErr_Format( PyExc_ValueError, "%s: missing format string.", function ); return; } VASTART( argument_list, const char *, format_string ); print_count = PyOS_vsnprintf( error_string, PYFSNTFS_ERROR_STRING_SIZE, format_string, argument_list ); VAEND( argument_list ); if( print_count < 0 ) { PyErr_Format( PyExc_ValueError, "%s: unable to format error string.", function ); return; } error_string_length = narrow_string_length( error_string ); if( ( error_string_length >= 1 ) && ( error_string[ error_string_length - 1 ] == '.' ) ) { error_string[ error_string_length - 1 ] = 0; } PyErr_Fetch( &exception_type, &exception_value, &exception_traceback ); string_object = PyObject_Repr( exception_value ); #if PY_MAJOR_VERSION >= 3 utf8_string_object = PyUnicode_AsUTF8String( string_object ); if( utf8_string_object != NULL ) { exception_string = PyBytes_AsString( utf8_string_object ); } #else exception_string = PyString_AsString( string_object ); #endif if( exception_string != NULL ) { libcerror_error_set( error, error_domain, error_code, "%s with error: %s.", error_string, exception_string ); } else { libcerror_error_set( error, error_domain, error_code, "%s.", error_string ); } #if PY_MAJOR_VERSION >= 3 if( utf8_string_object != NULL ) { Py_DecRef( utf8_string_object ); } #endif Py_DecRef( string_object ); return; } #undef VARARGS #undef VASTART #undef VAEND #if defined( HAVE_STDARG_H ) || defined( WINAPI ) #define VARARGS( function, exception_object, type, argument ) \ function( exception_object, type argument, ... ) #define VASTART( argument_list, type, name ) \ va_start( argument_list, name ) #define VAEND( argument_list ) \ va_end( argument_list ) #elif defined( HAVE_VARARGS_H ) #define VARARGS( function, exception_object, type, argument ) \ function( exception_object, va_alist ) va_dcl #define VASTART( argument_list, type, name ) \ { type name; va_start( argument_list ); name = va_arg( argument_list, type ) #define VAEND( argument_list ) \ va_end( argument_list ); } #endif /* Fetches and raises an error */ void VARARGS( pyfsntfs_error_fetch_and_raise, PyObject *exception_object, const char *, format_string ) { va_list argument_list; char error_string[ PYFSNTFS_ERROR_STRING_SIZE ]; PyObject *exception_traceback = NULL; PyObject *exception_type = NULL; PyObject *exception_value = NULL; PyObject *string_object = NULL; static char *function = "pyfsntfs_error_fetch_and_raise"; char *exception_string = NULL; size_t error_string_length = 0; int print_count = 0; #if PY_MAJOR_VERSION >= 3 PyObject *utf8_string_object = NULL; #endif if( format_string == NULL ) { PyErr_Format( PyExc_ValueError, "%s: missing format string.", function ); return; } VASTART( argument_list, const char *, format_string ); print_count = PyOS_vsnprintf( error_string, PYFSNTFS_ERROR_STRING_SIZE, format_string, argument_list ); VAEND( argument_list ); if( print_count < 0 ) { PyErr_Format( PyExc_ValueError, "%s: unable to format exception string.", function ); return; } error_string_length = narrow_string_length( error_string ); if( ( error_string_length >= 1 ) && ( error_string[ error_string_length - 1 ] == '.' ) ) { error_string[ error_string_length - 1 ] = 0; } PyErr_Fetch( &exception_type, &exception_value, &exception_traceback ); string_object = PyObject_Repr( exception_value ); #if PY_MAJOR_VERSION >= 3 utf8_string_object = PyUnicode_AsUTF8String( string_object ); if( utf8_string_object != NULL ) { exception_string = PyBytes_AsString( utf8_string_object ); } #else exception_string = PyString_AsString( string_object ); #endif if( exception_string != NULL ) { PyErr_Format( exception_object, "%s with error: %s.", error_string, exception_string ); } else { PyErr_Format( exception_object, "%s.", error_string ); } Py_DecRef( string_object ); return; } #undef VARARGS #undef VASTART #undef VAEND #if defined( HAVE_STDARG_H ) || defined( WINAPI ) #define VARARGS( function, error, exception_object, type, argument ) \ function( error, exception_object, type argument, ... ) #define VASTART( argument_list, type, name ) \ va_start( argument_list, name ) #define VAEND( argument_list ) \ va_end( argument_list ) #elif defined( HAVE_VARARGS_H ) #define VARARGS( function, error, exception_object, type, argument ) \ function( error, exception_object, va_alist ) va_dcl #define VASTART( argument_list, type, name ) \ { type name; va_start( argument_list ); name = va_arg( argument_list, type ) #define VAEND( argument_list ) \ va_end( argument_list ); } #endif /* Raises an error */ void VARARGS( pyfsntfs_error_raise, libcerror_error_t *error, PyObject *exception_object, const char *, format_string ) { va_list argument_list; char error_string[ PYFSNTFS_ERROR_STRING_SIZE ]; char exception_string[ PYFSNTFS_ERROR_STRING_SIZE ]; static char *function = "pyfsntfs_error_raise"; size_t error_string_index = 0; int print_count = 0; if( format_string == NULL ) { PyErr_Format( PyExc_ValueError, "%s: missing format string.", function ); return; } VASTART( argument_list, const char *, format_string ); print_count = PyOS_vsnprintf( exception_string, PYFSNTFS_ERROR_STRING_SIZE, format_string, argument_list ); VAEND( argument_list ); if( print_count < 0 ) { PyErr_Format( PyExc_ValueError, "%s: unable to format exception string.", function ); return; } if( error != NULL ) { if( libcerror_error_backtrace_sprint( error, error_string, PYFSNTFS_ERROR_STRING_SIZE ) != -1 ) { while( error_string_index < PYFSNTFS_ERROR_STRING_SIZE ) { if( error_string[ error_string_index ] == 0 ) { break; } if( ( error_string[ error_string_index ] == '\n' ) || ( error_string[ error_string_index ] == '\r' ) ) { error_string[ error_string_index ] = ' '; } error_string_index++; } if( error_string_index >= PYFSNTFS_ERROR_STRING_SIZE ) { error_string[ PYFSNTFS_ERROR_STRING_SIZE - 1 ] = 0; } PyErr_Format( exception_object, "%s %s", exception_string, error_string ); return; } } PyErr_Format( exception_object, "%s", exception_string ); return; } #undef VARARGS #undef VASTART #undef VAEND ================================================ FILE: pyfsntfs/pyfsntfs_error.h ================================================ /* * Error functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_ERROR_H ) #define _PYFSNTFS_ERROR_H #include #include #include "pyfsntfs_libcerror.h" #include "pyfsntfs_python.h" #define PYFSNTFS_ERROR_STRING_SIZE 2048 #if defined( __cplusplus ) extern "C" { #endif void pyfsntfs_error_fetch( libcerror_error_t **error, int error_domain, int error_code, const char *format_string, ... ); void pyfsntfs_error_fetch_and_raise( PyObject *exception_object, const char *format_string, ... ); void pyfsntfs_error_raise( libcerror_error_t *error, PyObject *exception_object, const char *format_string, ... ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_ERROR_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_file_attribute_flags.c ================================================ /* * Python object definition of the libfsntfs file attribute flags * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_file_attribute_flags.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #include "pyfsntfs_unused.h" PyTypeObject pyfsntfs_file_attribute_flags_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs.file_attribute_flags", /* tp_basicsize */ sizeof( pyfsntfs_file_attribute_flags_t ), /* tp_itemsize */ 0, /* tp_dealloc */ (destructor) pyfsntfs_file_attribute_flags_free, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_doc */ "pyfsntfs file attribute flags object (wraps LIBFSNTFS_FILE_ATTRIBUTE_FLAGS)", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ (initproc) pyfsntfs_file_attribute_flags_init, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Initializes the type object * Returns 1 if successful or -1 on error */ int pyfsntfs_file_attribute_flags_init_type( PyTypeObject *type_object ) { PyObject *value_object = NULL; if( type_object == NULL ) { return( -1 ); } type_object->tp_dict = PyDict_New(); if( type_object->tp_dict == NULL ) { return( -1 ); } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_READ_ONLY ); #else value_object = PyInt_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_READ_ONLY ); #endif if( PyDict_SetItemString( type_object->tp_dict, "READ_ONLY", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_HIDDEN ); #else value_object = PyInt_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_HIDDEN ); #endif if( PyDict_SetItemString( type_object->tp_dict, "HIDDEN", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_SYSTEM ); #else value_object = PyInt_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_SYSTEM ); #endif if( PyDict_SetItemString( type_object->tp_dict, "SYSTEM", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_DIRECTORY ); #else value_object = PyInt_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_DIRECTORY ); #endif if( PyDict_SetItemString( type_object->tp_dict, "DIRECTORY", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_ARCHIVE ); #else value_object = PyInt_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_ARCHIVE ); #endif if( PyDict_SetItemString( type_object->tp_dict, "ARCHIVE", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_DEVICE ); #else value_object = PyInt_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_DEVICE ); #endif if( PyDict_SetItemString( type_object->tp_dict, "DEVICE", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_NORMAL ); #else value_object = PyInt_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_NORMAL ); #endif if( PyDict_SetItemString( type_object->tp_dict, "NORMAL", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_TEMPORARY ); #else value_object = PyInt_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_TEMPORARY ); #endif if( PyDict_SetItemString( type_object->tp_dict, "TEMPORARY", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_SPARSE_FILE ); #else value_object = PyInt_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_SPARSE_FILE ); #endif if( PyDict_SetItemString( type_object->tp_dict, "SPARSE_FILE", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_REPARSE_POINT ); #else value_object = PyInt_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_REPARSE_POINT ); #endif if( PyDict_SetItemString( type_object->tp_dict, "REPARSE_POINT", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_COMPRESSED ); #else value_object = PyInt_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_COMPRESSED ); #endif if( PyDict_SetItemString( type_object->tp_dict, "COMPRESSED", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_OFFLINE ); #else value_object = PyInt_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_OFFLINE ); #endif if( PyDict_SetItemString( type_object->tp_dict, "OFFLINE", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_NOT_CONTENT_INDEXED ); #else value_object = PyInt_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_NOT_CONTENT_INDEXED ); #endif if( PyDict_SetItemString( type_object->tp_dict, "NOT_CONTENT_INDEXED", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_ENCRYPTED ); #else value_object = PyInt_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_ENCRYPTED ); #endif if( PyDict_SetItemString( type_object->tp_dict, "ENCRYPTED", value_object ) != 0 ) { goto on_error; } #if PY_MAJOR_VERSION >= 3 value_object = PyLong_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_VIRTUAL ); #else value_object = PyInt_FromLong( LIBFSNTFS_FILE_ATTRIBUTE_FLAG_VIRTUAL ); #endif if( PyDict_SetItemString( type_object->tp_dict, "VIRTUAL", value_object ) != 0 ) { goto on_error; } return( 1 ); on_error: if( type_object->tp_dict != NULL ) { Py_DecRef( type_object->tp_dict ); type_object->tp_dict = NULL; } return( -1 ); } /* Creates a new file attribute flags object * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_attribute_flags_new( void ) { pyfsntfs_file_attribute_flags_t *definitions_object = NULL; static char *function = "pyfsntfs_file_attribute_flags_new"; definitions_object = PyObject_New( struct pyfsntfs_file_attribute_flags, &pyfsntfs_file_attribute_flags_type_object ); if( definitions_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create definitions object.", function ); goto on_error; } if( pyfsntfs_file_attribute_flags_init( definitions_object ) != 0 ) { PyErr_Format( PyExc_MemoryError, "%s: unable to initialize definitions object.", function ); goto on_error; } return( (PyObject *) definitions_object ); on_error: if( definitions_object != NULL ) { Py_DecRef( (PyObject *) definitions_object ); } return( NULL ); } /* Initializes a file attribute flags object * Returns 0 if successful or -1 on error */ int pyfsntfs_file_attribute_flags_init( pyfsntfs_file_attribute_flags_t *definitions_object ) { static char *function = "pyfsntfs_file_attribute_flags_init"; if( definitions_object == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid definitions object.", function ); return( -1 ); } return( 0 ); } /* Frees a file attribute flags object */ void pyfsntfs_file_attribute_flags_free( pyfsntfs_file_attribute_flags_t *definitions_object ) { struct _typeobject *ob_type = NULL; static char *function = "pyfsntfs_file_attribute_flags_free"; if( definitions_object == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid definitions object.", function ); return; } ob_type = Py_TYPE( definitions_object ); if( ob_type == NULL ) { PyErr_Format( PyExc_ValueError, "%s: missing ob_type.", function ); return; } if( ob_type->tp_free == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid ob_type - missing tp_free.", function ); return; } ob_type->tp_free( (PyObject*) definitions_object ); } ================================================ FILE: pyfsntfs/pyfsntfs_file_attribute_flags.h ================================================ /* * Python object definition of the libfsntfs file attribute flags * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_FILE_ATTRIBUTE_FLAGS_H ) #define _PYFSNTFS_FILE_ATTRIBUTE_FLAGS_H #include #include #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct pyfsntfs_file_attribute_flags pyfsntfs_file_attribute_flags_t; struct pyfsntfs_file_attribute_flags { /* Python object initialization */ PyObject_HEAD }; extern PyTypeObject pyfsntfs_file_attribute_flags_type_object; int pyfsntfs_file_attribute_flags_init_type( PyTypeObject *type_object ); PyObject *pyfsntfs_file_attribute_flags_new( void ); int pyfsntfs_file_attribute_flags_init( pyfsntfs_file_attribute_flags_t *definitions_object ); void pyfsntfs_file_attribute_flags_free( pyfsntfs_file_attribute_flags_t *definitions_object ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_FILE_ATTRIBUTE_FLAGS_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_file_entries.c ================================================ /* * Python object definition of the sequence and iterator object of file entries * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_file_entries.h" #include "pyfsntfs_file_entry.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" PySequenceMethods pyfsntfs_file_entries_sequence_methods = { /* sq_length */ (lenfunc) pyfsntfs_file_entries_len, /* sq_concat */ 0, /* sq_repeat */ 0, /* sq_item */ (ssizeargfunc) pyfsntfs_file_entries_getitem, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ 0, /* sq_contains */ 0, /* sq_inplace_concat */ 0, /* sq_inplace_repeat */ 0 }; PyTypeObject pyfsntfs_file_entries_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs.file_entries", /* tp_basicsize */ sizeof( pyfsntfs_file_entries_t ), /* tp_itemsize */ 0, /* tp_dealloc */ (destructor) pyfsntfs_file_entries_free, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ &pyfsntfs_file_entries_sequence_methods, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /* tp_doc */ "pyfsntfs sequence and iterator object of file entries", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ (getiterfunc) pyfsntfs_file_entries_iter, /* tp_iternext */ (iternextfunc) pyfsntfs_file_entries_iternext, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ (initproc) pyfsntfs_file_entries_init, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Creates a new file entries sequence and iterator object * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entries_new( PyObject *parent_object, PyObject* (*get_item_by_index)( PyObject *parent_object, int index ), int number_of_items ) { pyfsntfs_file_entries_t *sequence_object = NULL; static char *function = "pyfsntfs_file_entries_new"; if( parent_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid parent object.", function ); return( NULL ); } if( get_item_by_index == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid get item by index function.", function ); return( NULL ); } /* Make sure the file entries values are initialized */ sequence_object = PyObject_New( struct pyfsntfs_file_entries, &pyfsntfs_file_entries_type_object ); if( sequence_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create sequence object.", function ); goto on_error; } sequence_object->parent_object = parent_object; sequence_object->get_item_by_index = get_item_by_index; sequence_object->current_index = 0; sequence_object->number_of_items = number_of_items; Py_IncRef( (PyObject *) sequence_object->parent_object ); return( (PyObject *) sequence_object ); on_error: if( sequence_object != NULL ) { Py_DecRef( (PyObject *) sequence_object ); } return( NULL ); } /* Initializes a file entries sequence and iterator object * Returns 0 if successful or -1 on error */ int pyfsntfs_file_entries_init( pyfsntfs_file_entries_t *sequence_object ) { static char *function = "pyfsntfs_file_entries_init"; if( sequence_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object.", function ); return( -1 ); } /* Make sure the file entries values are initialized */ sequence_object->parent_object = NULL; sequence_object->get_item_by_index = NULL; sequence_object->current_index = 0; sequence_object->number_of_items = 0; PyErr_Format( PyExc_NotImplementedError, "%s: initialize of file entries not supported.", function ); return( -1 ); } /* Frees a file entries sequence object */ void pyfsntfs_file_entries_free( pyfsntfs_file_entries_t *sequence_object ) { struct _typeobject *ob_type = NULL; static char *function = "pyfsntfs_file_entries_free"; if( sequence_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object.", function ); return; } ob_type = Py_TYPE( sequence_object ); if( ob_type == NULL ) { PyErr_Format( PyExc_ValueError, "%s: missing ob_type.", function ); return; } if( ob_type->tp_free == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid ob_type - missing tp_free.", function ); return; } if( sequence_object->parent_object != NULL ) { Py_DecRef( (PyObject *) sequence_object->parent_object ); } ob_type->tp_free( (PyObject*) sequence_object ); } /* The file entries len() function */ Py_ssize_t pyfsntfs_file_entries_len( pyfsntfs_file_entries_t *sequence_object ) { static char *function = "pyfsntfs_file_entries_len"; if( sequence_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object.", function ); return( -1 ); } return( (Py_ssize_t) sequence_object->number_of_items ); } /* The file entries getitem() function */ PyObject *pyfsntfs_file_entries_getitem( pyfsntfs_file_entries_t *sequence_object, Py_ssize_t item_index ) { PyObject *file_entry_object = NULL; static char *function = "pyfsntfs_file_entries_getitem"; if( sequence_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object.", function ); return( NULL ); } if( sequence_object->get_item_by_index == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object - missing get item by index function.", function ); return( NULL ); } if( sequence_object->number_of_items < 0 ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object - invalid number of items.", function ); return( NULL ); } if( ( item_index < 0 ) || ( item_index >= (Py_ssize_t) sequence_object->number_of_items ) ) { PyErr_Format( PyExc_ValueError, "%s: invalid invalid item index value out of bounds.", function ); return( NULL ); } file_entry_object = sequence_object->get_item_by_index( sequence_object->parent_object, (int) item_index ); return( file_entry_object ); } /* The file entries iter() function */ PyObject *pyfsntfs_file_entries_iter( pyfsntfs_file_entries_t *sequence_object ) { static char *function = "pyfsntfs_file_entries_iter"; if( sequence_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object.", function ); return( NULL ); } Py_IncRef( (PyObject *) sequence_object ); return( (PyObject *) sequence_object ); } /* The file entries iternext() function */ PyObject *pyfsntfs_file_entries_iternext( pyfsntfs_file_entries_t *sequence_object ) { PyObject *file_entry_object = NULL; static char *function = "pyfsntfs_file_entries_iternext"; if( sequence_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object.", function ); return( NULL ); } if( sequence_object->get_item_by_index == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object - missing get item by index function.", function ); return( NULL ); } if( sequence_object->current_index < 0 ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object - invalid current index.", function ); return( NULL ); } if( sequence_object->number_of_items < 0 ) { PyErr_Format( PyExc_ValueError, "%s: invalid sequence object - invalid number of items.", function ); return( NULL ); } if( sequence_object->current_index >= sequence_object->number_of_items ) { PyErr_SetNone( PyExc_StopIteration ); return( NULL ); } file_entry_object = sequence_object->get_item_by_index( sequence_object->parent_object, sequence_object->current_index ); if( file_entry_object != NULL ) { sequence_object->current_index++; } return( file_entry_object ); } ================================================ FILE: pyfsntfs/pyfsntfs_file_entries.h ================================================ /* * Python object definition of the sequence and iterator object of file entries * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_FILE_ENTRIES_H ) #define _PYFSNTFS_FILE_ENTRIES_H #include #include #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct pyfsntfs_file_entries pyfsntfs_file_entries_t; struct pyfsntfs_file_entries { /* Python object initialization */ PyObject_HEAD /* The parent object */ PyObject *parent_object; /* The get item by index callback function */ PyObject* (*get_item_by_index)( PyObject *parent_object, int index ); /* The current index */ int current_index; /* The number of items */ int number_of_items; }; extern PyTypeObject pyfsntfs_file_entries_type_object; PyObject *pyfsntfs_file_entries_new( PyObject *parent_object, PyObject* (*get_item_by_index)( PyObject *parent_object, int index ), int number_of_items ); int pyfsntfs_file_entries_init( pyfsntfs_file_entries_t *sequence_object ); void pyfsntfs_file_entries_free( pyfsntfs_file_entries_t *sequence_object ); Py_ssize_t pyfsntfs_file_entries_len( pyfsntfs_file_entries_t *sequence_object ); PyObject *pyfsntfs_file_entries_getitem( pyfsntfs_file_entries_t *sequence_object, Py_ssize_t item_index ); PyObject *pyfsntfs_file_entries_iter( pyfsntfs_file_entries_t *sequence_object ); PyObject *pyfsntfs_file_entries_iternext( pyfsntfs_file_entries_t *sequence_object ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_FILE_ENTRIES_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_file_entry.c ================================================ /* * Python object wrapper of libfsntfs_file_entry_t * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_attribute.h" #include "pyfsntfs_attributes.h" #include "pyfsntfs_data_stream.h" #include "pyfsntfs_data_streams.h" #include "pyfsntfs_datetime.h" #include "pyfsntfs_error.h" #include "pyfsntfs_file_entries.h" #include "pyfsntfs_file_entry.h" #include "pyfsntfs_file_name_attribute.h" #include "pyfsntfs_integer.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_object_identifier_attribute.h" #include "pyfsntfs_python.h" #include "pyfsntfs_reparse_point_attribute.h" #include "pyfsntfs_security_descriptor_attribute.h" #include "pyfsntfs_standard_information_attribute.h" #include "pyfsntfs_string.h" #include "pyfsntfs_unused.h" #include "pyfsntfs_volume_information_attribute.h" #include "pyfsntfs_volume_name_attribute.h" PyMethodDef pyfsntfs_file_entry_object_methods[] = { /* Functions to access the file entry data */ { "read_buffer", (PyCFunction) pyfsntfs_file_entry_read_buffer, METH_VARARGS | METH_KEYWORDS, "read_buffer(size) -> String\n" "\n" "Reads a buffer of file entry data." }, { "read_buffer_at_offset", (PyCFunction) pyfsntfs_file_entry_read_buffer_at_offset, METH_VARARGS | METH_KEYWORDS, "read_buffer_at_offset(size, offset) -> String\n" "\n" "Reads a buffer of file entry data at a specific offset." }, { "seek_offset", (PyCFunction) pyfsntfs_file_entry_seek_offset, METH_VARARGS | METH_KEYWORDS, "seek_offset(offset, whence) -> None\n" "\n" "Seeks an offset within the file entry data." }, { "get_offset", (PyCFunction) pyfsntfs_file_entry_get_offset, METH_NOARGS, "get_offset() -> Integer\n" "\n" "Returns the current offset within the file entry data." }, /* Some Pythonesque aliases */ { "read", (PyCFunction) pyfsntfs_file_entry_read_buffer, METH_VARARGS | METH_KEYWORDS, "read(size) -> String\n" "\n" "Reads a buffer of file entry data." }, { "seek", (PyCFunction) pyfsntfs_file_entry_seek_offset, METH_VARARGS | METH_KEYWORDS, "seek(offset, whence) -> None\n" "\n" "Seeks an offset within the file entry data." }, { "tell", (PyCFunction) pyfsntfs_file_entry_get_offset, METH_NOARGS, "tell() -> Integer\n" "\n" "Returns the current offset within the file entry data." }, /* Functions to access the metadata */ { "get_size", (PyCFunction) pyfsntfs_file_entry_get_size, METH_NOARGS, "get_size() -> Integer\n" "\n" "Returns the size data." }, /* Functions to access the extents */ { "get_number_of_extents", (PyCFunction) pyfsntfs_file_entry_get_number_of_extents, METH_NOARGS, "get_number_of_extents() -> Integer\n" "\n" "Retrieves the number of extents." }, { "get_extent", (PyCFunction) pyfsntfs_file_entry_get_extent, METH_VARARGS | METH_KEYWORDS, "get_extent(extent_index) -> Tuple(Integer, Integer, Integer)\n" "\n" "Retrieves a specific extent.\t" "The extent is a tuple of offset, size and flags." }, /* Functions to access the file entry data */ { "is_empty", (PyCFunction) pyfsntfs_file_entry_is_empty, METH_NOARGS, "is_empty() -> Boolean\n" "\n" "Determines if the file entry is empty." }, { "is_allocated", (PyCFunction) pyfsntfs_file_entry_is_allocated, METH_NOARGS, "is_allocated() -> Boolean\n" "\n" "Determines if the file entry is allocated." }, { "has_directory_entries_index", (PyCFunction) pyfsntfs_file_entry_has_directory_entries_index, METH_NOARGS, "has_directory_entries_index() -> Boolean\n" "\n" "Determines if the file entry has a directory entries index." }, { "has_default_data_stream", (PyCFunction) pyfsntfs_file_entry_has_default_data_stream, METH_NOARGS, "has_default_data_stream() -> Boolean\n" "\n" "Determines if the file entry has a default data stream." }, { "has_i30_entry", (PyCFunction) pyfsntfs_file_entry_has_i30_entry, METH_NOARGS, "i30_entry() -> Boolean\n" "\n" "Determines if the file entry has a $I30 entry." }, { "get_file_reference", (PyCFunction) pyfsntfs_file_entry_get_file_reference, METH_NOARGS, "get_file_reference() -> Integer\n" "\n" "Returns the file reference, a combination of MFT entry index and sequence number." }, { "get_base_record_file_reference", (PyCFunction) pyfsntfs_file_entry_get_base_record_file_reference, METH_NOARGS, "get_base_record_file_reference() -> Integer\n" "\n" "Returns the base record file reference, a combination of MFT entry index and sequence number." }, { "get_parent_file_reference", (PyCFunction) pyfsntfs_file_entry_get_parent_file_reference, METH_NOARGS, "get_parent_file_reference() -> Integer or None\n" "\n" "Returns the parent file reference, a combination of MFT entry index and sequence number." }, { "get_parent_file_reference_by_attribute_index", (PyCFunction) pyfsntfs_file_entry_get_parent_file_reference_by_attribute_index, METH_VARARGS | METH_KEYWORDS, "get_parent_file_reference_by_attribute_index(attribute_index) -> Integer\n" "\n" "Returns the parent file reference, a combination of MFT entry index and sequence number." }, { "get_journal_sequence_number", (PyCFunction) pyfsntfs_file_entry_get_journal_sequence_number, METH_NOARGS, "get_journal_sequence_number() -> Integer\n" "\n" "Returns the journal sequence number." }, { "get_creation_time", (PyCFunction) pyfsntfs_file_entry_get_creation_time, METH_NOARGS, "get_creation_time() -> Datetime or None\n" "\n" "Returns the creation date and time." }, { "get_creation_time_as_integer", (PyCFunction) pyfsntfs_file_entry_get_creation_time_as_integer, METH_NOARGS, "get_creation_time_as_integer() -> Integer or None\n" "\n" "Returns the creation date and time as a 64-bit integer containing a FILETIME value." }, { "get_modification_time", (PyCFunction) pyfsntfs_file_entry_get_modification_time, METH_NOARGS, "get_modification_time() -> Datetime or None\n" "\n" "Returns the modification date and time." }, { "get_modification_time_as_integer", (PyCFunction) pyfsntfs_file_entry_get_modification_time_as_integer, METH_NOARGS, "get_modification_time_as_integer() -> Integer or None\n" "\n" "Returns the modification date and time as a 64-bit integer containing a FILETIME value." }, { "get_access_time", (PyCFunction) pyfsntfs_file_entry_get_access_time, METH_NOARGS, "get_access_time() -> Datetime or None\n" "\n" "Returns the access date and time." }, { "get_access_time_as_integer", (PyCFunction) pyfsntfs_file_entry_get_access_time_as_integer, METH_NOARGS, "get_access_time_as_integer() -> Integer or None\n" "\n" "Returns the access date and time as a 64-bit integer containing a FILETIME value." }, { "get_entry_modification_time", (PyCFunction) pyfsntfs_file_entry_get_entry_modification_time, METH_NOARGS, "get_entry_modification_time() -> Datetime or None\n" "\n" "Returns the entry modification date and time." }, { "get_entry_modification_time_as_integer", (PyCFunction) pyfsntfs_file_entry_get_entry_modification_time_as_integer, METH_NOARGS, "get_entry_modification_time_as_integer() -> Integer or None\n" "\n" "Returns the entry modification date and time as a 64-bit integer containing a FILETIME value." }, { "get_file_attribute_flags", (PyCFunction) pyfsntfs_file_entry_get_file_attribute_flags, METH_NOARGS, "get_file_attribute_flags() -> Integer or None\n" "\n" "Returns the file attribute flags." }, { "get_i30_file_reference", (PyCFunction) pyfsntfs_file_entry_get_i30_file_reference, METH_NOARGS, "get_i30_file_reference() -> Integer\n" "\n" "Returns the $I30 entry file reference, a combination of MFT entry index and sequence number." }, { "get_i30_creation_time", (PyCFunction) pyfsntfs_file_entry_get_i30_creation_time, METH_NOARGS, "get_i30_creation_time() -> Datetime or None\n" "\n" "Returns the $I30 entry creation date and time." }, { "get_i30_creation_time_as_integer", (PyCFunction) pyfsntfs_file_entry_get_i30_creation_time_as_integer, METH_NOARGS, "get_i30_creation_time_as_integer() -> Integer or None\n" "\n" "Returns the $I30 entry creation date and time as a 64-bit integer containing a FILETIME value." }, { "get_i30_modification_time", (PyCFunction) pyfsntfs_file_entry_get_i30_modification_time, METH_NOARGS, "get_i30_modification_time() -> Datetime or None\n" "\n" "Returns the $I30 entry modification date and time." }, { "get_i30_modification_time_as_integer", (PyCFunction) pyfsntfs_file_entry_get_i30_modification_time_as_integer, METH_NOARGS, "get_i30_modification_time_as_integer() -> Integer or None\n" "\n" "Returns the $I30 entry modification date and time as a 64-bit integer containing a FILETIME value." }, { "get_i30_access_time", (PyCFunction) pyfsntfs_file_entry_get_i30_access_time, METH_NOARGS, "get_i30_access_time() -> Datetime or None\n" "\n" "Returns the $I30 entry access date and time." }, { "get_i30_access_time_as_integer", (PyCFunction) pyfsntfs_file_entry_get_i30_access_time_as_integer, METH_NOARGS, "get_i30_access_time_as_integer() -> Integer or None\n" "\n" "Returns the $I30 entry access date and time as a 64-bit integer containing a FILETIME value." }, { "get_i30_entry_modification_time", (PyCFunction) pyfsntfs_file_entry_get_i30_entry_modification_time, METH_NOARGS, "get_i30_entry_modification_time() -> Datetime or None\n" "\n" "Returns the $I30 entry entry modification date and time." }, { "get_i30_entry_modification_time_as_integer", (PyCFunction) pyfsntfs_file_entry_get_i30_entry_modification_time_as_integer, METH_NOARGS, "get_i30_entry_modification_time_as_integer() -> Integer or None\n" "\n" "Returns the $I30 entry entry modification date and time as a 64-bit integer containing a FILETIME value." }, { "get_i30_file_attribute_flags", (PyCFunction) pyfsntfs_file_entry_get_i30_file_attribute_flags, METH_NOARGS, "get_i30_file_attribute_flags() -> Integer or None\n" "\n" "Returns the $I30 entry file attribute flags." }, { "get_name", (PyCFunction) pyfsntfs_file_entry_get_name, METH_NOARGS, "get_name() -> Unicode string or None\n" "\n" "Returns the name." }, { "get_name_attribute_index", (PyCFunction) pyfsntfs_file_entry_get_name_attribute_index, METH_NOARGS, "get_name_attribute_index() -> Integer or None\n" "\n" "Returns the attribute index corresponding to the name." }, { "get_name_by_attribute_index", (PyCFunction) pyfsntfs_file_entry_get_name_by_attribute_index, METH_VARARGS | METH_KEYWORDS, "get_name_by_attribute_index(attribute_index) -> Unicode string or None\n" "\n" "Returns the name." }, { "get_path_hint", (PyCFunction) pyfsntfs_file_entry_get_path_hint, METH_VARARGS | METH_KEYWORDS, "get_path_hint(attribute_index) -> Unicode string or None\n" "\n" "Returns the name." }, { "get_symbolic_link_target", (PyCFunction) pyfsntfs_file_entry_get_symbolic_link_target, METH_NOARGS, "get_symbolic_link_target() -> Unicode string or None\n" "\n" "Returns the symbolic link target." }, { "get_security_descriptor_data", (PyCFunction) pyfsntfs_file_entry_get_security_descriptor_data, METH_NOARGS, "get_security_descriptor_data() -> String or None\n" "\n" "Returns the security descriptor data." }, /* Functions to access the attributes */ { "get_number_of_attributes", (PyCFunction) pyfsntfs_file_entry_get_number_of_attributes, METH_NOARGS, "get_number_of_attributes() -> Integer\n" "\n" "Retrieves the number of attributes." }, { "get_attribute", (PyCFunction) pyfsntfs_file_entry_get_attribute, METH_VARARGS | METH_KEYWORDS, "get_attribute(attribute_index) -> Object\n" "\n" "Retrieves a specific attribute." }, /* Functions to access the alternate data streams */ { "get_number_of_alternate_data_streams", (PyCFunction) pyfsntfs_file_entry_get_number_of_alternate_data_streams, METH_NOARGS, "get_number_of_alternate_data_streams() -> Integer\n" "\n" "Retrieves the number of alternate data streams." }, { "get_alternate_data_stream", (PyCFunction) pyfsntfs_file_entry_get_alternate_data_stream, METH_VARARGS | METH_KEYWORDS, "get_alternate_data_stream(alternate_data_stream_index) -> Object\n" "\n" "Retrieves a specific alternate data stream." }, { "has_alternate_data_stream_by_name", (PyCFunction) pyfsntfs_file_entry_has_alternate_data_stream_by_name, METH_VARARGS | METH_KEYWORDS, "has_alternate_data_stream_by_name(name) -> Boolean\n" "\n" "Determines if there is an alternate data stream specified by the name." }, { "get_alternate_data_stream_by_name", (PyCFunction) pyfsntfs_file_entry_get_alternate_data_stream_by_name, METH_VARARGS | METH_KEYWORDS, "get_alternate_data_stream_by_name(name) -> Object or None\n" "\n" "Retrieves an alternate data stream specified by the name." }, /* Functions to access the sub file entries */ { "get_number_of_sub_file_entries", (PyCFunction) pyfsntfs_file_entry_get_number_of_sub_file_entries, METH_NOARGS, "get_number_of_sub_file_entries() -> Integer\n" "\n" "Retrieves the number of sub file entries." }, { "get_sub_file_entry", (PyCFunction) pyfsntfs_file_entry_get_sub_file_entry, METH_VARARGS | METH_KEYWORDS, "get_sub_file_entry(sub_file_entry_index) -> Object\n" "\n" "Retrieves a specific sub file entry." }, /* Sentinel */ { NULL, NULL, 0, NULL } }; PyGetSetDef pyfsntfs_file_entry_object_get_set_definitions[] = { { "size", (getter) pyfsntfs_file_entry_get_size, (setter) 0, "The size of the data.", NULL }, { "number_of_extents", (getter) pyfsntfs_file_entry_get_number_of_extents, (setter) 0, "The number of extents.", NULL }, { "file_reference", (getter) pyfsntfs_file_entry_get_file_reference, (setter) 0, "The file reference, a combination of MFT entry index and sequence number.", NULL }, { "base_record_file_reference", (getter) pyfsntfs_file_entry_get_base_record_file_reference, (setter) 0, "The base record file reference, a combination of MFT entry index and sequence number.", NULL }, { "parent_file_reference", (getter) pyfsntfs_file_entry_get_parent_file_reference, (setter) 0, "The parent file reference, a combination of MFT entry index and sequence number.", NULL }, { "journal_sequence_number", (getter) pyfsntfs_file_entry_get_journal_sequence_number, (setter) 0, "The journal sequence number.", NULL }, { "creation_time", (getter) pyfsntfs_file_entry_get_creation_time, (setter) 0, "The creation date and time.", NULL }, { "modification_time", (getter) pyfsntfs_file_entry_get_modification_time, (setter) 0, "The modification date and time.", NULL }, { "access_time", (getter) pyfsntfs_file_entry_get_access_time, (setter) 0, "The access date and time.", NULL }, { "entry_modification_time", (getter) pyfsntfs_file_entry_get_entry_modification_time, (setter) 0, "The entry modification date and time.", NULL }, { "file_attribute_flags", (getter) pyfsntfs_file_entry_get_file_attribute_flags, (setter) 0, "The file attribute flags.", NULL }, { "name", (getter) pyfsntfs_file_entry_get_name, (setter) 0, "The name.", NULL }, { "name_attribute_index", (getter) pyfsntfs_file_entry_get_name_attribute_index, (setter) 0, "The name.", NULL }, { "symbolic_link_target", (getter) pyfsntfs_file_entry_get_symbolic_link_target, (setter) 0, "The symbolic link target.", NULL }, { "security_descriptor_data", (getter) pyfsntfs_file_entry_get_security_descriptor_data, (setter) 0, "The security descriptor data.", NULL }, { "number_of_attributes", (getter) pyfsntfs_file_entry_get_number_of_attributes, (setter) 0, "The number of attributes.", NULL }, { "attributes", (getter) pyfsntfs_file_entry_get_attributes, (setter) 0, "The attributes", NULL }, { "number_of_alternate_data_streams", (getter) pyfsntfs_file_entry_get_number_of_alternate_data_streams, (setter) 0, "The number of alternate data streams.", NULL }, { "alternate_data_streams", (getter) pyfsntfs_file_entry_get_alternate_data_streams, (setter) 0, "The alternate data streams", NULL }, { "number_of_sub_file_entries", (getter) pyfsntfs_file_entry_get_number_of_sub_file_entries, (setter) 0, "The number of sub file entries.", NULL }, { "sub_file_entries", (getter) pyfsntfs_file_entry_get_sub_file_entries, (setter) 0, "The sub file entries", NULL }, /* Sentinel */ { NULL, NULL, NULL, NULL, NULL } }; PyTypeObject pyfsntfs_file_entry_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs.file_entry", /* tp_basicsize */ sizeof( pyfsntfs_file_entry_t ), /* tp_itemsize */ 0, /* tp_dealloc */ (destructor) pyfsntfs_file_entry_free, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_doc */ "pyfsntfs file entry object (wraps libfsntfs_file_entry_t)", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ pyfsntfs_file_entry_object_methods, /* tp_members */ 0, /* tp_getset */ pyfsntfs_file_entry_object_get_set_definitions, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ (initproc) pyfsntfs_file_entry_init, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Creates a new file entry object * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_new( libfsntfs_file_entry_t *file_entry, PyObject *parent_object ) { pyfsntfs_file_entry_t *pyfsntfs_file_entry = NULL; static char *function = "pyfsntfs_file_entry_new"; if( file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } /* PyObject_New does not invoke tp_init */ pyfsntfs_file_entry = PyObject_New( struct pyfsntfs_file_entry, &pyfsntfs_file_entry_type_object ); if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to initialize file entry.", function ); goto on_error; } pyfsntfs_file_entry->file_entry = file_entry; pyfsntfs_file_entry->parent_object = parent_object; if( pyfsntfs_file_entry->parent_object != NULL ) { Py_IncRef( pyfsntfs_file_entry->parent_object ); } return( (PyObject *) pyfsntfs_file_entry ); on_error: if( pyfsntfs_file_entry != NULL ) { Py_DecRef( (PyObject *) pyfsntfs_file_entry ); } return( NULL ); } /* Initializes a file entry object * Returns 0 if successful or -1 on error */ int pyfsntfs_file_entry_init( pyfsntfs_file_entry_t *pyfsntfs_file_entry ) { static char *function = "pyfsntfs_file_entry_init"; if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( -1 ); } /* Make sure libfsntfs file entry is set to NULL */ pyfsntfs_file_entry->file_entry = NULL; PyErr_Format( PyExc_NotImplementedError, "%s: initialize of file entry not supported.", function ); return( -1 ); } /* Frees a file entry object */ void pyfsntfs_file_entry_free( pyfsntfs_file_entry_t *pyfsntfs_file_entry ) { struct _typeobject *ob_type = NULL; libcerror_error_t *error = NULL; static char *function = "pyfsntfs_file_entry_free"; int result = 0; if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return; } ob_type = Py_TYPE( pyfsntfs_file_entry ); if( ob_type == NULL ) { PyErr_Format( PyExc_ValueError, "%s: missing ob_type.", function ); return; } if( ob_type->tp_free == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid ob_type - missing tp_free.", function ); return; } if( pyfsntfs_file_entry->file_entry != NULL ) { Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_free( &( pyfsntfs_file_entry->file_entry ), &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_MemoryError, "%s: unable to free libfsntfs file entry.", function ); libcerror_error_free( &error ); } } if( pyfsntfs_file_entry->parent_object != NULL ) { Py_DecRef( pyfsntfs_file_entry->parent_object ); } ob_type->tp_free( (PyObject*) pyfsntfs_file_entry ); } /* Reads a buffer of data from the file entry * Returns a Python object holding the data if successful or NULL on error */ PyObject *pyfsntfs_file_entry_read_buffer( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; PyObject *string_object = NULL; static char *function = "pyfsntfs_file_entry_read_buffer"; static char *keyword_list[] = { "size", NULL }; char *buffer = NULL; size64_t read_size = 0; ssize_t read_count = 0; int result = 0; if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid pyfsntfs file entry.", function ); return( NULL ); } if( pyfsntfs_file_entry->file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid pyfsntfs file entry - missing libfsntfs file entry.", function ); return( NULL ); } if( PyArg_ParseTupleAndKeywords( arguments, keywords, "|O", keyword_list, &integer_object ) == 0 ) { return( NULL ); } PyErr_Clear(); Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_has_default_data_stream( pyfsntfs_file_entry->file_entry, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to determine if file entry has default data stream.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { PyErr_Format( PyExc_IOError, "%s: missing default data stream.", function ); return( NULL ); } if( integer_object == NULL ) { result = 0; } else { result = PyObject_IsInstance( integer_object, (PyObject *) &PyLong_Type ); if( result == -1 ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to determine if integer object is of type long.", function ); return( NULL ); } #if PY_MAJOR_VERSION < 3 else if( result == 0 ) { PyErr_Clear(); result = PyObject_IsInstance( integer_object, (PyObject *) &PyInt_Type ); if( result == -1 ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to determine if integer object is of type int.", function ); return( NULL ); } } #endif } if( result != 0 ) { if( pyfsntfs_integer_unsigned_copy_to_64bit( integer_object, (uint64_t *) &read_size, &error ) != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to convert integer object into read size.", function ); libcerror_error_free( &error ); return( NULL ); } } else if( ( integer_object == NULL ) || ( integer_object == Py_None ) ) { Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_size( pyfsntfs_file_entry->file_entry, &read_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve size.", function ); libcerror_error_free( &error ); return( NULL ); } } else { PyErr_Format( PyExc_TypeError, "%s: unsupported integer object type.", function ); return( NULL ); } if( read_size == 0 ) { #if PY_MAJOR_VERSION >= 3 string_object = PyBytes_FromString( "" ); #else string_object = PyString_FromString( "" ); #endif return( string_object ); } /* Make sure the data fits into a memory buffer */ if( ( read_size > (size64_t) INT_MAX ) || ( read_size > (size64_t) SSIZE_MAX ) ) { PyErr_Format( PyExc_ValueError, "%s: invalid argument read size value exceeds maximum.", function ); return( NULL ); } #if PY_MAJOR_VERSION >= 3 string_object = PyBytes_FromStringAndSize( NULL, read_size ); buffer = PyBytes_AsString( string_object ); #else /* Note that a size of 0 is not supported */ string_object = PyString_FromStringAndSize( NULL, read_size ); buffer = PyString_AsString( string_object ); #endif Py_BEGIN_ALLOW_THREADS read_count = libfsntfs_file_entry_read_buffer( pyfsntfs_file_entry->file_entry, (uint8_t *) buffer, (size_t) read_size, &error ); Py_END_ALLOW_THREADS if( read_count <= -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to read data.", function ); libcerror_error_free( &error ); Py_DecRef( (PyObject *) string_object ); return( NULL ); } /* Need to resize the string here in case read_size was not fully read. */ #if PY_MAJOR_VERSION >= 3 if( _PyBytes_Resize( &string_object, (Py_ssize_t) read_count ) != 0 ) #else if( _PyString_Resize( &string_object, (Py_ssize_t) read_count ) != 0 ) #endif { Py_DecRef( (PyObject *) string_object ); return( NULL ); } return( string_object ); } /* Reads a buffer of data at a specific foffset from the file entry * Returns a Python object holding the data if successful or NULL on error */ PyObject *pyfsntfs_file_entry_read_buffer_at_offset( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; PyObject *string_object = NULL; static char *function = "pyfsntfs_file_entry_read_buffer_at_offset"; static char *keyword_list[] = { "size", "offset", NULL }; char *buffer = NULL; off64_t read_offset = 0; size64_t read_size = 0; ssize_t read_count = 0; int result = 0; if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid pyfsntfs file entry.", function ); return( NULL ); } if( pyfsntfs_file_entry->file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid pyfsntfs file entry - missing libfsntfs file entry.", function ); return( NULL ); } if( PyArg_ParseTupleAndKeywords( arguments, keywords, "OL", keyword_list, &integer_object, &read_offset ) == 0 ) { return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_has_default_data_stream( pyfsntfs_file_entry->file_entry, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to determine if file entry has default data stream.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { PyErr_Format( PyExc_IOError, "%s: missing default data stream.", function ); return( NULL ); } result = PyObject_IsInstance( integer_object, (PyObject *) &PyLong_Type ); if( result == -1 ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to determine if integer object is of type long.", function ); return( NULL ); } #if PY_MAJOR_VERSION < 3 else if( result == 0 ) { PyErr_Clear(); result = PyObject_IsInstance( integer_object, (PyObject *) &PyInt_Type ); if( result == -1 ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to determine if integer object is of type int.", function ); return( NULL ); } } #endif if( result != 0 ) { if( pyfsntfs_integer_unsigned_copy_to_64bit( integer_object, (uint64_t *) &read_size, &error ) != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to convert integer object into read size.", function ); libcerror_error_free( &error ); return( NULL ); } } else if( integer_object == Py_None ) { Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_size( pyfsntfs_file_entry->file_entry, &read_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve size.", function ); libcerror_error_free( &error ); return( NULL ); } } else { PyErr_Format( PyExc_TypeError, "%s: unsupported integer object type.", function ); return( NULL ); } if( read_size == 0 ) { #if PY_MAJOR_VERSION >= 3 string_object = PyBytes_FromString( "" ); #else string_object = PyString_FromString( "" ); #endif return( string_object ); } /* Make sure the data fits into a memory buffer */ if( ( read_size > (size64_t) INT_MAX ) || ( read_size > (size64_t) SSIZE_MAX ) ) { PyErr_Format( PyExc_ValueError, "%s: invalid argument read size value exceeds maximum.", function ); return( NULL ); } #if PY_MAJOR_VERSION >= 3 string_object = PyBytes_FromStringAndSize( NULL, read_size ); buffer = PyBytes_AsString( string_object ); #else /* Note that a size of 0 is not supported */ string_object = PyString_FromStringAndSize( NULL, read_size ); buffer = PyString_AsString( string_object ); #endif Py_BEGIN_ALLOW_THREADS read_count = libfsntfs_file_entry_read_buffer_at_offset( pyfsntfs_file_entry->file_entry, (uint8_t *) buffer, (size_t) read_size, (off64_t) read_offset, &error ); Py_END_ALLOW_THREADS if( read_count <= -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to read data.", function ); libcerror_error_free( &error ); Py_DecRef( (PyObject *) string_object ); return( NULL ); } /* Need to resize the string here in case read_size was not fully read. */ #if PY_MAJOR_VERSION >= 3 if( _PyBytes_Resize( &string_object, (Py_ssize_t) read_count ) != 0 ) #else if( _PyString_Resize( &string_object, (Py_ssize_t) read_count ) != 0 ) #endif { Py_DecRef( (PyObject *) string_object ); return( NULL ); } return( string_object ); } /* Seeks a certain offset in the file entry data * Returns a Python object holding the offset if successful or NULL on error */ PyObject *pyfsntfs_file_entry_seek_offset( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ) { libcerror_error_t *error = NULL; static char *function = "pyfsntfs_file_entry_seek_offset"; static char *keyword_list[] = { "offset", "whence", NULL }; off64_t offset = 0; int result = 0; int whence = 0; if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid pyfsntfs file entry.", function ); return( NULL ); } if( pyfsntfs_file_entry->file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid pyfsntfs file entry - missing libfsntfs file entry.", function ); return( NULL ); } if( PyArg_ParseTupleAndKeywords( arguments, keywords, "L|i", keyword_list, &offset, &whence ) == 0 ) { return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_has_default_data_stream( pyfsntfs_file_entry->file_entry, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to determine if file entry has default data stream.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { PyErr_Format( PyExc_IOError, "%s: missing default data stream.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS offset = libfsntfs_file_entry_seek_offset( pyfsntfs_file_entry->file_entry, offset, whence, &error ); Py_END_ALLOW_THREADS if( offset == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to seek offset.", function ); libcerror_error_free( &error ); return( NULL ); } Py_IncRef( Py_None ); return( Py_None ); } /* Retrieves the offset * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_offset( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_offset"; off64_t offset = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_has_default_data_stream( pyfsntfs_file_entry->file_entry, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to determine if file entry has default data stream.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { PyErr_Format( PyExc_IOError, "%s: missing default data stream.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_offset( pyfsntfs_file_entry->file_entry, &offset, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve offset.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_signed_new_from_64bit( (int64_t) offset ); return( integer_object ); } /* Retrieves the size * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_size( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_size"; size64_t size = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_size( pyfsntfs_file_entry->file_entry, &size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve size.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( (uint64_t) size ); return( integer_object ); } /* Retrieves the number of extents * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_number_of_extents( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_number_of_extents"; int number_of_extents = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_number_of_extents( pyfsntfs_file_entry->file_entry, &number_of_extents, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve number of extents.", function ); libcerror_error_free( &error ); return( NULL ); } #if PY_MAJOR_VERSION >= 3 integer_object = PyLong_FromLong( (long) number_of_extents ); #else integer_object = PyInt_FromLong( (long) number_of_extents ); #endif return( integer_object ); } /* Retrieves a specific extent by index * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_extent_by_index( pyfsntfs_file_entry_t *pyfsntfs_file_entry, int extent_index ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; PyObject *tuple_object = NULL; static char *function = "pyfsntfs_file_entry_get_extent_by_index"; off64_t extent_offset = 0; size64_t extent_size = 0; uint32_t extent_flags = 0; int result = 0; if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_extent_by_index( pyfsntfs_file_entry->file_entry, extent_index, &extent_offset, &extent_size, &extent_flags, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve extent: %d.", function, extent_index ); libcerror_error_free( &error ); goto on_error; } tuple_object = PyTuple_New( 3 ); integer_object = pyfsntfs_integer_signed_new_from_64bit( (int64_t) extent_offset ); /* Tuple set item does not increment the reference count of the integer object */ if( PyTuple_SetItem( tuple_object, 0, integer_object ) != 0 ) { goto on_error; } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( (uint64_t) extent_size ); /* Tuple set item does not increment the reference count of the integer object */ if( PyTuple_SetItem( tuple_object, 1, integer_object ) != 0 ) { goto on_error; } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( (uint64_t) extent_flags ); /* Tuple set item does not increment the reference count of the integer object */ if( PyTuple_SetItem( tuple_object, 2, integer_object ) != 0 ) { goto on_error; } return( tuple_object ); on_error: if( integer_object != NULL ) { Py_DecRef( (PyObject *) integer_object ); } if( tuple_object != NULL ) { Py_DecRef( (PyObject *) tuple_object ); } return( NULL ); } /* Retrieves a specific extent * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_extent( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ) { PyObject *sequence_object = NULL; static char *keyword_list[] = { "extent_index", NULL }; int extent_index = 0; if( PyArg_ParseTupleAndKeywords( arguments, keywords, "i", keyword_list, &extent_index ) == 0 ) { return( NULL ); } sequence_object = pyfsntfs_file_entry_get_extent_by_index( pyfsntfs_file_entry, extent_index ); return( sequence_object ); } /* Determines if the file entry is empty * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_is_empty( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; static char *function = "pyfsntfs_file_entry_is_empty"; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_is_empty( pyfsntfs_file_entry->file_entry, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to determine if file entry is empty.", function ); libcerror_error_free( &error ); return( NULL ); } if( result != 0 ) { Py_IncRef( (PyObject *) Py_True ); return( Py_True ); } Py_IncRef( (PyObject *) Py_False ); return( Py_False ); } /* Determines if the file entry is allocated (in use) * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_is_allocated( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; static char *function = "pyfsntfs_file_entry_is_allocated"; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_is_allocated( pyfsntfs_file_entry->file_entry, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to determine if file entry is allocated.", function ); libcerror_error_free( &error ); return( NULL ); } if( result != 0 ) { Py_IncRef( (PyObject *) Py_True ); return( Py_True ); } Py_IncRef( (PyObject *) Py_False ); return( Py_False ); } /* Determines if the file entry has the directory entries index * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_has_directory_entries_index( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; static char *function = "pyfsntfs_file_entry_has_directory_entries_index"; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_has_directory_entries_index( pyfsntfs_file_entry->file_entry, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to determine if file entry has directory entries index.", function ); libcerror_error_free( &error ); return( NULL ); } if( result != 0 ) { Py_IncRef( (PyObject *) Py_True ); return( Py_True ); } Py_IncRef( (PyObject *) Py_False ); return( Py_False ); } /* Determines if the file entry has a default data stream * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_has_default_data_stream( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; static char *function = "pyfsntfs_file_entry_has_default_data_stream"; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_has_default_data_stream( pyfsntfs_file_entry->file_entry, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to determine if file entry has a default data stream.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result != 0 ) { Py_IncRef( (PyObject *) Py_True ); return( Py_True ); } Py_IncRef( (PyObject *) Py_False ); return( Py_False ); } /* Determines if the file entry has a $I30 entry * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_has_i30_entry( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; static char *function = "pyfsntfs_file_entry_has_i30_entry"; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_has_i30_entry( pyfsntfs_file_entry->file_entry, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to determine if file entry has a $I30 entry.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result != 0 ) { Py_IncRef( (PyObject *) Py_True ); return( Py_True ); } Py_IncRef( (PyObject *) Py_False ); return( Py_False ); } /* Retrieves the file reference * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_file_reference( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_file_reference"; uint64_t file_reference = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_file_reference( pyfsntfs_file_entry->file_entry, &file_reference, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve file reference.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( file_reference ); return( integer_object ); } /* Retrieves the base record file reference * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_base_record_file_reference( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_base_record_file_reference"; uint64_t file_reference = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_base_record_file_reference( pyfsntfs_file_entry->file_entry, &file_reference, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve base record file reference.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( file_reference ); return( integer_object ); } /* Retrieves the parent file reference * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_parent_file_reference( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_parent_file_reference"; uint64_t file_reference = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_parent_file_reference( pyfsntfs_file_entry->file_entry, &file_reference, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve parent file reference.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( file_reference ); return( integer_object ); } /* Retrieves the parent file reference for a specific $FILE_NAME attribute * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_parent_file_reference_by_attribute_index( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_parent_file_reference_by_attribute_index"; static char *keyword_list[] = { "attribute_index", NULL }; uint64_t file_reference = 0; int attribute_index = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } if( PyArg_ParseTupleAndKeywords( arguments, keywords, "i", keyword_list, &attribute_index ) == 0 ) { return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_parent_file_reference_by_attribute_index( pyfsntfs_file_entry->file_entry, attribute_index, &file_reference, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve parent file reference from attribute: %d.", function, attribute_index ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( file_reference ); return( integer_object ); } /* Retrieves the journal sequence number * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_journal_sequence_number( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_journal_sequence_number"; uint64_t journal_sequence_number = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_journal_sequence_number( pyfsntfs_file_entry->file_entry, &journal_sequence_number, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve journal sequence number.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( journal_sequence_number ); return( integer_object ); } /* Retrieves the creation date and time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_creation_time( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *date_time_object = NULL; static char *function = "pyfsntfs_file_entry_get_creation_time"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_creation_time( pyfsntfs_file_entry->file_entry, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve creation time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } date_time_object = pyfsntfs_datetime_new_from_filetime( filetime ); return( date_time_object ); } /* Retrieves the creation date and time as an integer * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_creation_time_as_integer( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_creation_time_as_integer"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_creation_time( pyfsntfs_file_entry->file_entry, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve creation time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( filetime ); return( integer_object ); } /* Retrieves the modification date and time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_modification_time( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *date_time_object = NULL; static char *function = "pyfsntfs_file_entry_get_modification_time"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_modification_time( pyfsntfs_file_entry->file_entry, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve modification time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } date_time_object = pyfsntfs_datetime_new_from_filetime( filetime ); return( date_time_object ); } /* Retrieves the modification date and time as an integer * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_modification_time_as_integer( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_modification_time_as_integer"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_modification_time( pyfsntfs_file_entry->file_entry, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve modification time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( filetime ); return( integer_object ); } /* Retrieves the access date and time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_access_time( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *date_time_object = NULL; static char *function = "pyfsntfs_file_entry_get_access_time"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_access_time( pyfsntfs_file_entry->file_entry, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve access time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } date_time_object = pyfsntfs_datetime_new_from_filetime( filetime ); return( date_time_object ); } /* Retrieves the access date and time as an integer * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_access_time_as_integer( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_access_time_as_integer"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_access_time( pyfsntfs_file_entry->file_entry, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve access time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( filetime ); return( integer_object ); } /* Retrieves the entry modification date and time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_entry_modification_time( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *date_time_object = NULL; static char *function = "pyfsntfs_file_entry_get_entry_modification_time"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_entry_modification_time( pyfsntfs_file_entry->file_entry, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve entry modification time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } date_time_object = pyfsntfs_datetime_new_from_filetime( filetime ); return( date_time_object ); } /* Retrieves the entry modification date and time as an integer * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_entry_modification_time_as_integer( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_entry_modification_time_as_integer"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_entry_modification_time( pyfsntfs_file_entry->file_entry, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve entry modification time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_signed_new_from_64bit( filetime ); return( integer_object ); } /* Retrieves the file attribute flags * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_file_attribute_flags( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_file_entry_flags"; uint32_t file_attribute_flags = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_file_attribute_flags( pyfsntfs_file_entry->file_entry, &file_attribute_flags, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve file attribute flags.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( (uint64_t) file_attribute_flags ); return( integer_object ); } /* Retrieves the $I30 entry file reference * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_i30_file_reference( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_i30_file_reference"; uint64_t file_reference = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_i30_file_reference( pyfsntfs_file_entry->file_entry, &file_reference, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve file reference.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( file_reference ); return( integer_object ); } /* Retrieves the $I30 entry creation date and time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_i30_creation_time( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *date_time_object = NULL; static char *function = "pyfsntfs_file_entry_get_i30_creation_time"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_i30_creation_time( pyfsntfs_file_entry->file_entry, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve creation time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } date_time_object = pyfsntfs_datetime_new_from_filetime( filetime ); return( date_time_object ); } /* Retrieves the $I30 entry creation date and time as an integer * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_i30_creation_time_as_integer( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_i30_creation_time_as_integer"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_i30_creation_time( pyfsntfs_file_entry->file_entry, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve creation time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( filetime ); return( integer_object ); } /* Retrieves the $I30 entry modification date and time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_i30_modification_time( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *date_time_object = NULL; static char *function = "pyfsntfs_file_entry_get_i30_modification_time"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_i30_modification_time( pyfsntfs_file_entry->file_entry, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve modification time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } date_time_object = pyfsntfs_datetime_new_from_filetime( filetime ); return( date_time_object ); } /* Retrieves the $I30 entry modification date and time as an integer * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_i30_modification_time_as_integer( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_i30_modification_time_as_integer"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_i30_modification_time( pyfsntfs_file_entry->file_entry, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve modification time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( filetime ); return( integer_object ); } /* Retrieves the $I30 entry access date and time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_i30_access_time( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *date_time_object = NULL; static char *function = "pyfsntfs_file_entry_get_i30_access_time"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_i30_access_time( pyfsntfs_file_entry->file_entry, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve access time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } date_time_object = pyfsntfs_datetime_new_from_filetime( filetime ); return( date_time_object ); } /* Retrieves the $I30 entry access date and time as an integer * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_i30_access_time_as_integer( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_i30_access_time_as_integer"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_i30_access_time( pyfsntfs_file_entry->file_entry, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve access time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( filetime ); return( integer_object ); } /* Retrieves the $I30 entry entry modification date and time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_i30_entry_modification_time( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *date_time_object = NULL; static char *function = "pyfsntfs_file_entry_get_i30_entry_modification_time"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_i30_entry_modification_time( pyfsntfs_file_entry->file_entry, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve entry modification time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } date_time_object = pyfsntfs_datetime_new_from_filetime( filetime ); return( date_time_object ); } /* Retrieves the $I30 entry modification date and time as an integer * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_i30_entry_modification_time_as_integer( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_i30_entry_modification_time_as_integer"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_i30_entry_modification_time( pyfsntfs_file_entry->file_entry, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve entry modification time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_signed_new_from_64bit( filetime ); return( integer_object ); } /* Retrieves the $I30 entry file attribute flags * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_i30_file_attribute_flags( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_i30_file_entry_flags"; uint32_t file_attribute_flags = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_i30_file_attribute_flags( pyfsntfs_file_entry->file_entry, &file_attribute_flags, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve file attribute flags.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( (uint64_t) file_attribute_flags ); return( integer_object ); } /* Retrieves the name * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_name( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { PyObject *string_object = NULL; libcerror_error_t *error = NULL; uint8_t *utf8_string = NULL; static char *function = "pyfsntfs_file_entry_get_name"; size_t utf8_string_size = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_utf8_name_size( pyfsntfs_file_entry->file_entry, &utf8_string_size, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to determine size of name as UTF-8 string.", function ); libcerror_error_free( &error ); goto on_error; } else if( ( result == 0 ) || ( utf8_string_size == 0 ) ) { Py_IncRef( Py_None ); return( Py_None ); } utf8_string = (uint8_t *) PyMem_Malloc( sizeof( uint8_t ) * utf8_string_size ); if( utf8_string == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create UTF-8 string.", function ); goto on_error; } Py_BEGIN_ALLOW_THREADS /* Using RFC 2279 UTF-8 to support unpaired UTF-16 surrogates */ result = libfsntfs_file_entry_get_utf8_name( pyfsntfs_file_entry->file_entry, utf8_string, utf8_string_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve name as UTF-8 string.", function ); libcerror_error_free( &error ); goto on_error; } #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 string_object = pyfsntfs_string_new_from_utf8_rfc2279( utf8_string, utf8_string_size ); #else /* Pass the string length to PyUnicode_DecodeUTF8 * otherwise it makes the end of string character is part * of the string */ string_object = PyUnicode_DecodeUTF8( (char *) utf8_string, (Py_ssize_t) utf8_string_size - 1, NULL ); #endif if( string_object == NULL ) { PyErr_Format( PyExc_IOError, "%s: unable to convert UTF-8 string into Unicode object.", function ); goto on_error; } PyMem_Free( utf8_string ); return( string_object ); on_error: if( utf8_string != NULL ) { PyMem_Free( utf8_string ); } return( NULL ); } /* Retrieves the name attribute index * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_name_attribute_index( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_name_attribute_index"; int attribute_index = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_name_attribute_index( pyfsntfs_file_entry->file_entry, &attribute_index, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve name attribute index.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } #if PY_MAJOR_VERSION >= 3 integer_object = PyLong_FromLong( (long) attribute_index ); #else integer_object = PyInt_FromLong( (long) attribute_index ); #endif return( integer_object ); } /* Retrieves the name for a specific $FILE_NAME attribute * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_name_by_attribute_index( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ) { PyObject *string_object = NULL; libcerror_error_t *error = NULL; uint8_t *utf8_string = NULL; static char *function = "pyfsntfs_file_entry_get_name_by_attribute_index"; static char *keyword_list[] = { "attribute_index", NULL }; size_t utf8_string_size = 0; int attribute_index = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } if( PyArg_ParseTupleAndKeywords( arguments, keywords, "i", keyword_list, &attribute_index ) == 0 ) { return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_utf8_name_size_by_attribute_index( pyfsntfs_file_entry->file_entry, attribute_index, &utf8_string_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to determine size of name as UTF-8 string.", function ); libcerror_error_free( &error ); goto on_error; } else if( utf8_string_size == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } utf8_string = (uint8_t *) PyMem_Malloc( sizeof( uint8_t ) * utf8_string_size ); if( utf8_string == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create UTF-8 string.", function ); goto on_error; } Py_BEGIN_ALLOW_THREADS /* Using RFC 2279 UTF-8 to support unpaired UTF-16 surrogates */ result = libfsntfs_file_entry_get_utf8_name_by_attribute_index( pyfsntfs_file_entry->file_entry, attribute_index, utf8_string, utf8_string_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve name as UTF-8 string.", function ); libcerror_error_free( &error ); goto on_error; } #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 string_object = pyfsntfs_string_new_from_utf8_rfc2279( utf8_string, utf8_string_size ); #else /* Pass the string length to PyUnicode_DecodeUTF8 * otherwise it makes the end of string character is part * of the string */ string_object = PyUnicode_DecodeUTF8( (char *) utf8_string, (Py_ssize_t) utf8_string_size - 1, NULL ); #endif if( string_object == NULL ) { PyErr_Format( PyExc_IOError, "%s: unable to convert UTF-8 string into Unicode object.", function ); goto on_error; } PyMem_Free( utf8_string ); return( string_object ); on_error: if( utf8_string != NULL ) { PyMem_Free( utf8_string ); } return( NULL ); } /* Retrieves the path hint for a specific $FILE_NAME attribute * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_path_hint( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ) { libcerror_error_t *error = NULL; PyObject *string_object = NULL; uint8_t *path = NULL; static char *function = "pyfsntfs_file_entry_get_path_hint"; static char *keyword_list[] = { "attribute_index", NULL }; size_t path_size = 0; int attribute_index = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } if( PyArg_ParseTupleAndKeywords( arguments, keywords, "i", keyword_list, &attribute_index ) == 0 ) { return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_utf8_path_hint_size( pyfsntfs_file_entry->file_entry, attribute_index, &path_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve path size.", function ); libcerror_error_free( &error ); goto on_error; } else if( path_size == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } path = (uint8_t *) PyMem_Malloc( sizeof( uint8_t ) * path_size ); if( path == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create path.", function ); goto on_error; } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_utf8_path_hint( pyfsntfs_file_entry->file_entry, attribute_index, path, path_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve path.", function ); libcerror_error_free( &error ); goto on_error; } /* Pass the string length to PyUnicode_DecodeUTF8 * otherwise it makes the end of string character is part * of the string */ string_object = PyUnicode_DecodeUTF8( (char *) path, (Py_ssize_t) path_size - 1, NULL ); PyMem_Free( path ); return( string_object ); on_error: if( path != NULL ) { PyMem_Free( path ); } return( NULL ); } /* Retrieves the symbolic link target * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_symbolic_link_target( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *string_object = NULL; uint8_t *name = NULL; static char *function = "pyfsntfs_file_entry_get_symbolic_link_target"; size_t name_size = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_utf8_symbolic_link_target_size( pyfsntfs_file_entry->file_entry, &name_size, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve symbolic link target size.", function ); libcerror_error_free( &error ); goto on_error; } else if( ( result == 0 ) || ( name_size == 0 ) ) { Py_IncRef( Py_None ); return( Py_None ); } name = (uint8_t *) PyMem_Malloc( sizeof( uint8_t ) * name_size ); if( name == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create name.", function ); goto on_error; } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_utf8_symbolic_link_target( pyfsntfs_file_entry->file_entry, name, name_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve symbolic link target.", function ); libcerror_error_free( &error ); goto on_error; } /* Pass the string length to PyUnicode_DecodeUTF8 * otherwise it makes the end of string character is part * of the string */ string_object = PyUnicode_DecodeUTF8( (char *) name, (Py_ssize_t) name_size - 1, NULL ); PyMem_Free( name ); return( string_object ); on_error: if( name != NULL ) { PyMem_Free( name ); } return( NULL ); } /* Retrieves the security descriptor data * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_security_descriptor_data( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *string_object = NULL; static char *function = "pyfsntfs_file_entry_get_security_descriptor_data"; char *security_desciptor_data = NULL; size_t security_desciptor_data_size = 0; int result = 0; if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_security_descriptor_size( pyfsntfs_file_entry->file_entry, &security_desciptor_data_size, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to determine security descriptor data size.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } #if PY_MAJOR_VERSION >= 3 string_object = PyBytes_FromStringAndSize( NULL, security_desciptor_data_size ); security_desciptor_data = PyBytes_AsString( string_object ); #else /* Note that a size of 0 is not supported */ string_object = PyString_FromStringAndSize( NULL, security_desciptor_data_size ); security_desciptor_data = PyString_AsString( string_object ); #endif Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_security_descriptor( pyfsntfs_file_entry->file_entry, (uint8_t *) security_desciptor_data, security_desciptor_data_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve security descriptor data.", function ); libcerror_error_free( &error ); Py_DecRef( (PyObject *) string_object ); return( NULL ); } return( string_object ); } /* Retrieves the number of attributes * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_number_of_attributes( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_number_of_attributes"; int number_of_attributes = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_number_of_attributes( pyfsntfs_file_entry->file_entry, &number_of_attributes, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve number of attributes.", function ); libcerror_error_free( &error ); return( NULL ); } #if PY_MAJOR_VERSION >= 3 integer_object = PyLong_FromLong( (long) number_of_attributes ); #else integer_object = PyInt_FromLong( (long) number_of_attributes ); #endif return( integer_object ); } /* Retrieves a specific attribute by index * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_attribute_by_index( PyObject *pyfsntfs_file_entry, int attribute_index ) { libcerror_error_t *error = NULL; libfsntfs_attribute_t *attribute = NULL; PyObject *attribute_object = NULL; PyTypeObject *type_object = NULL; static char *function = "pyfsntfs_file_entry_get_attribute_by_index"; uint32_t attribute_type = 0; int result = 0; if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_attribute_by_index( ( (pyfsntfs_file_entry_t *) pyfsntfs_file_entry )->file_entry, attribute_index, &attribute, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve attribute: %d.", function, attribute_index ); libcerror_error_free( &error ); goto on_error; } Py_BEGIN_ALLOW_THREADS result = libfsntfs_attribute_get_type( attribute, &attribute_type, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve type.", function ); libcerror_error_free( &error ); return( NULL ); } switch( attribute_type ) { case LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME: type_object = &pyfsntfs_file_name_attribute_type_object; break; case LIBFSNTFS_ATTRIBUTE_TYPE_OBJECT_IDENTIFIER: type_object = &pyfsntfs_object_identifier_attribute_type_object; break; case LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT: type_object = &pyfsntfs_reparse_point_attribute_type_object; break; case LIBFSNTFS_ATTRIBUTE_TYPE_SECURITY_DESCRIPTOR: type_object = &pyfsntfs_security_descriptor_attribute_type_object; break; case LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION: type_object = &pyfsntfs_standard_information_attribute_type_object; break; case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_INFORMATION: type_object = &pyfsntfs_volume_information_attribute_type_object; break; case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME: type_object = &pyfsntfs_volume_name_attribute_type_object; break; default: type_object = &pyfsntfs_attribute_type_object; break; } attribute_object = pyfsntfs_attribute_new( type_object, attribute, pyfsntfs_file_entry ); if( attribute_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create attribute object.", function ); goto on_error; } return( attribute_object ); on_error: if( attribute != NULL ) { libfsntfs_attribute_free( &attribute, NULL ); } return( NULL ); } /* Retrieves a specific attribute * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_attribute( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ) { PyObject *attribute_object = NULL; static char *keyword_list[] = { "attribute_index", NULL }; int attribute_index = 0; if( PyArg_ParseTupleAndKeywords( arguments, keywords, "i", keyword_list, &attribute_index ) == 0 ) { return( NULL ); } attribute_object = pyfsntfs_file_entry_get_attribute_by_index( (PyObject *) pyfsntfs_file_entry, attribute_index ); return( attribute_object ); } /* Retrieves an attributes sequence and iterator object for the attributes * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_attributes( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *attributes_object = NULL; static char *function = "pyfsntfs_file_entry_get_attributes"; int number_of_attributes = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_number_of_attributes( pyfsntfs_file_entry->file_entry, &number_of_attributes, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve number of attributes.", function ); libcerror_error_free( &error ); return( NULL ); } attributes_object = pyfsntfs_attributes_new( (PyObject *) pyfsntfs_file_entry, &pyfsntfs_file_entry_get_attribute_by_index, number_of_attributes ); if( attributes_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create attributes object.", function ); return( NULL ); } return( attributes_object ); } /* Retrieves the number of alternate data streams * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_number_of_alternate_data_streams( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_number_of_alternate_data_streams"; int number_of_alternate_data_streams = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_number_of_alternate_data_streams( pyfsntfs_file_entry->file_entry, &number_of_alternate_data_streams, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve number of alternate data streams.", function ); libcerror_error_free( &error ); return( NULL ); } #if PY_MAJOR_VERSION >= 3 integer_object = PyLong_FromLong( (long) number_of_alternate_data_streams ); #else integer_object = PyInt_FromLong( (long) number_of_alternate_data_streams ); #endif return( integer_object ); } /* Retrieves a specific alternate data stream by index * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_alternate_data_stream_by_index( PyObject *pyfsntfs_file_entry, int alternate_data_stream_index ) { libcerror_error_t *error = NULL; libfsntfs_data_stream_t *data_stream = NULL; PyObject *data_stream_object = NULL; static char *function = "pyfsntfs_file_entry_get_alternate_data_stream_by_index"; int result = 0; if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_alternate_data_stream_by_index( ( (pyfsntfs_file_entry_t *) pyfsntfs_file_entry )->file_entry, alternate_data_stream_index, &data_stream, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve alternate data stream: %d.", function, alternate_data_stream_index ); libcerror_error_free( &error ); goto on_error; } data_stream_object = pyfsntfs_data_stream_new( data_stream, pyfsntfs_file_entry ); if( data_stream_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create alternate data stream object.", function ); goto on_error; } return( data_stream_object ); on_error: if( data_stream != NULL ) { libfsntfs_data_stream_free( &data_stream, NULL ); } return( NULL ); } /* Retrieves a specific alternate data stream * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_alternate_data_stream( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ) { PyObject *data_stream_object = NULL; static char *keyword_list[] = { "alternate_data_stream_index", NULL }; int alternate_data_stream_index = 0; if( PyArg_ParseTupleAndKeywords( arguments, keywords, "i", keyword_list, &alternate_data_stream_index ) == 0 ) { return( NULL ); } data_stream_object = pyfsntfs_file_entry_get_alternate_data_stream_by_index( (PyObject *) pyfsntfs_file_entry, alternate_data_stream_index ); return( data_stream_object ); } /* Retrieves a data streams sequence and iterator object for the alternate data streams * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_alternate_data_streams( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *data_streams_object = NULL; static char *function = "pyfsntfs_file_entry_get_alternate_data_streams"; int number_of_alternate_data_streams = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_number_of_alternate_data_streams( pyfsntfs_file_entry->file_entry, &number_of_alternate_data_streams, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve number of alternate data streams.", function ); libcerror_error_free( &error ); return( NULL ); } data_streams_object = pyfsntfs_data_streams_new( (PyObject *) pyfsntfs_file_entry, &pyfsntfs_file_entry_get_alternate_data_stream_by_index, number_of_alternate_data_streams ); if( data_streams_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create data streams object.", function ); return( NULL ); } return( data_streams_object ); } /* Determines if there is an alternate data stream specified by the name * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_has_alternate_data_stream_by_name( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ) { libcerror_error_t *error = NULL; char *data_stream_name = NULL; static char *keyword_list[] = { "data_stream_name", NULL }; static char *function = "pyfsntfs_file_entry_has_alternate_data_stream_by_name"; size_t data_stream_name_length = 0; int result = 0; if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } if( PyArg_ParseTupleAndKeywords( arguments, keywords, "s", keyword_list, &data_stream_name ) == 0 ) { return( NULL ); } data_stream_name_length = narrow_string_length( data_stream_name ); Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_has_alternate_data_stream_by_utf8_name( pyfsntfs_file_entry->file_entry, (uint8_t *) data_stream_name, data_stream_name_length, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to determine if alternate data stream exists.", function ); libcerror_error_free( &error ); return( NULL ); } /* Check if the alternate data stream is present */ if( result != 0 ) { Py_IncRef( (PyObject *) Py_True ); return( Py_True ); } Py_IncRef( (PyObject *) Py_False ); return( Py_False ); } /* Retrieves the alternate data stream specified by the name * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_alternate_data_stream_by_name( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ) { libcerror_error_t *error = NULL; libfsntfs_data_stream_t *data_stream = NULL; PyObject *data_stream_object = NULL; char *data_stream_name = NULL; static char *keyword_list[] = { "data_stream_name", NULL }; static char *function = "pyfsntfs_file_entry_get_alternate_data_stream_by_name"; size_t data_stream_name_length = 0; int result = 0; if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } if( PyArg_ParseTupleAndKeywords( arguments, keywords, "s", keyword_list, &data_stream_name ) == 0 ) { goto on_error; } data_stream_name_length = narrow_string_length( data_stream_name ); Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_alternate_data_stream_by_utf8_name( pyfsntfs_file_entry->file_entry, (uint8_t *) data_stream_name, data_stream_name_length, &data_stream, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve alternate data stream.", function ); libcerror_error_free( &error ); goto on_error; } /* Check if the alternate data stream is present */ else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } data_stream_object = pyfsntfs_data_stream_new( data_stream, (PyObject *) pyfsntfs_file_entry ); if( data_stream_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create data stream object.", function ); goto on_error; } return( data_stream_object ); on_error: if( data_stream != NULL ) { libfsntfs_data_stream_free( &data_stream, NULL ); } return( NULL ); } /* Retrieves the number of sub file entries * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_number_of_sub_file_entries( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_entry_get_number_of_sub_file_entries"; int number_of_sub_file_entries = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_number_of_sub_file_entries( pyfsntfs_file_entry->file_entry, &number_of_sub_file_entries, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve number of sub file entries.", function ); libcerror_error_free( &error ); return( NULL ); } #if PY_MAJOR_VERSION >= 3 integer_object = PyLong_FromLong( (long) number_of_sub_file_entries ); #else integer_object = PyInt_FromLong( (long) number_of_sub_file_entries ); #endif return( integer_object ); } /* Retrieves a specific sub file entry by index * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_sub_file_entry_by_index( PyObject *pyfsntfs_file_entry, int sub_file_entry_index ) { libcerror_error_t *error = NULL; libfsntfs_file_entry_t *sub_file_entry = NULL; PyObject *file_entry_object = NULL; static char *function = "pyfsntfs_file_entry_get_sub_file_entry_by_index"; int result = 0; if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_sub_file_entry_by_index( ( (pyfsntfs_file_entry_t *) pyfsntfs_file_entry )->file_entry, sub_file_entry_index, &sub_file_entry, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve sub file entry: %d.", function, sub_file_entry_index ); libcerror_error_free( &error ); goto on_error; } file_entry_object = pyfsntfs_file_entry_new( sub_file_entry, ( (pyfsntfs_file_entry_t *) pyfsntfs_file_entry )->parent_object ); if( file_entry_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create file entry object.", function ); goto on_error; } return( file_entry_object ); on_error: if( sub_file_entry != NULL ) { libfsntfs_file_entry_free( &sub_file_entry, NULL ); } return( NULL ); } /* Retrieves a specific sub file entry * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_sub_file_entry( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ) { PyObject *file_entry_object = NULL; static char *keyword_list[] = { "sub_file_entry_index", NULL }; int sub_file_entry_index = 0; if( PyArg_ParseTupleAndKeywords( arguments, keywords, "i", keyword_list, &sub_file_entry_index ) == 0 ) { return( NULL ); } file_entry_object = pyfsntfs_file_entry_get_sub_file_entry_by_index( (PyObject *) pyfsntfs_file_entry, sub_file_entry_index ); return( file_entry_object ); } /* Retrieves a file entries sequence and iterator object for the sub file entries * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_entry_get_sub_file_entries( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *file_entries_object = NULL; static char *function = "pyfsntfs_file_entry_get_sub_file_entries"; int number_of_sub_file_entries = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_file_entry == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid file entry.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_entry_get_number_of_sub_file_entries( pyfsntfs_file_entry->file_entry, &number_of_sub_file_entries, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve number of sub file entries.", function ); libcerror_error_free( &error ); return( NULL ); } file_entries_object = pyfsntfs_file_entries_new( (PyObject *) pyfsntfs_file_entry, &pyfsntfs_file_entry_get_sub_file_entry_by_index, number_of_sub_file_entries ); if( file_entries_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create file entries object.", function ); return( NULL ); } return( file_entries_object ); } ================================================ FILE: pyfsntfs/pyfsntfs_file_entry.h ================================================ /* * Python object wrapper of libfsntfs_file_entry_t * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_FILE_ENTRY_H ) #define _PYFSNTFS_FILE_ENTRY_H #include #include #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct pyfsntfs_file_entry pyfsntfs_file_entry_t; struct pyfsntfs_file_entry { /* Python object initialization */ PyObject_HEAD /* The libfsntfs file entry */ libfsntfs_file_entry_t *file_entry; /* The parent object */ PyObject *parent_object; }; extern PyMethodDef pyfsntfs_file_entry_object_methods[]; extern PyTypeObject pyfsntfs_file_entry_type_object; PyObject *pyfsntfs_file_entry_new( libfsntfs_file_entry_t *file_entry, PyObject *parent_object ); int pyfsntfs_file_entry_init( pyfsntfs_file_entry_t *pyfsntfs_file_entry ); void pyfsntfs_file_entry_free( pyfsntfs_file_entry_t *pyfsntfs_file_entry ); PyObject *pyfsntfs_file_entry_read_buffer( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_file_entry_read_buffer_at_offset( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_file_entry_seek_offset( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_file_entry_get_offset( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_size( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_number_of_extents( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_extent_by_index( pyfsntfs_file_entry_t *pyfsntfs_file_entry, int extent_index ); PyObject *pyfsntfs_file_entry_get_extent( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_file_entry_is_empty( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_is_allocated( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_has_directory_entries_index( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_has_default_data_stream( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_has_i30_entry( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_file_reference( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_base_record_file_reference( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_parent_file_reference( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_parent_file_reference_by_attribute_index( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_file_entry_get_journal_sequence_number( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_creation_time( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_creation_time_as_integer( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_modification_time( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_modification_time_as_integer( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_access_time( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_access_time_as_integer( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_entry_modification_time( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_entry_modification_time_as_integer( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_file_attribute_flags( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_i30_file_reference( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_i30_creation_time( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_i30_creation_time_as_integer( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_i30_modification_time( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_i30_modification_time_as_integer( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_i30_access_time( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_i30_access_time_as_integer( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_i30_entry_modification_time( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_i30_entry_modification_time_as_integer( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_i30_file_attribute_flags( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_name( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_name_attribute_index( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_name_by_attribute_index( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_file_entry_get_name( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_path_hint( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_file_entry_get_symbolic_link_target( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_security_descriptor_data( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_number_of_attributes( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_attribute_by_index( PyObject *pyfsntfs_file_entry, int attribute_index ); PyObject *pyfsntfs_file_entry_get_attribute( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_file_entry_get_attributes( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_number_of_alternate_data_streams( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_alternate_data_stream_by_index( PyObject *pyfsntfs_file_entry, int alternate_data_stream_index ); PyObject *pyfsntfs_file_entry_get_alternate_data_stream( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_file_entry_get_alternate_data_streams( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_has_alternate_data_stream_by_name( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_file_entry_get_alternate_data_stream_by_name( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_file_entry_get_number_of_sub_file_entries( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); PyObject *pyfsntfs_file_entry_get_sub_file_entry_by_index( PyObject *pyfsntfs_file_entry, int sub_file_entry_index ); PyObject *pyfsntfs_file_entry_get_sub_file_entry( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_file_entry_get_sub_file_entries( pyfsntfs_file_entry_t *pyfsntfs_file_entry, PyObject *arguments ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_FILE_ENTRY_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_file_name_attribute.c ================================================ /* * Python object definition of the libfsntfs file name attribute * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_attribute.h" #include "pyfsntfs_datetime.h" #include "pyfsntfs_error.h" #include "pyfsntfs_file_name_attribute.h" #include "pyfsntfs_integer.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #include "pyfsntfs_string.h" #include "pyfsntfs_unused.h" PyMethodDef pyfsntfs_file_name_attribute_object_methods[] = { /* Functions to access the attribute values */ { "get_parent_file_reference", (PyCFunction) pyfsntfs_file_name_attribute_get_parent_file_reference, METH_NOARGS, "get_parent_file_reference() -> Integer\n" "\n" "Returns the parent file reference, a combination of MFT entry index and sequence number." }, { "get_creation_time", (PyCFunction) pyfsntfs_file_name_attribute_get_creation_time, METH_NOARGS, "get_creation_time() -> Datetime or None\n" "\n" "Returns the creation date and time." }, { "get_creation_time_as_integer", (PyCFunction) pyfsntfs_file_name_attribute_get_creation_time_as_integer, METH_NOARGS, "get_creation_time_as_integer() -> Integer or None\n" "\n" "Returns the creation date and time as a 64-bit integer containing a FILETIME value." }, { "get_modification_time", (PyCFunction) pyfsntfs_file_name_attribute_get_modification_time, METH_NOARGS, "get_modification_time() -> Datetime or None\n" "\n" "Returns the modification date and time." }, { "get_modification_time_as_integer", (PyCFunction) pyfsntfs_file_name_attribute_get_modification_time_as_integer, METH_NOARGS, "get_modification_time_as_integer() -> Integer or None\n" "\n" "Returns the modification date and time as a 64-bit integer containing a FILETIME value." }, { "get_access_time", (PyCFunction) pyfsntfs_file_name_attribute_get_access_time, METH_NOARGS, "get_access_time() -> Datetime or None\n" "\n" "Returns the access date and time." }, { "get_access_time_as_integer", (PyCFunction) pyfsntfs_file_name_attribute_get_access_time_as_integer, METH_NOARGS, "get_access_time_as_integer() -> Integer or None\n" "\n" "Returns the access date and time as a 64-bit integer containing a FILETIME value." }, { "get_entry_modification_time", (PyCFunction) pyfsntfs_file_name_attribute_get_entry_modification_time, METH_NOARGS, "get_entry_modification_time() -> Datetime or None\n" "\n" "Returns the entry modification date and time." }, { "get_entry_modification_time_as_integer", (PyCFunction) pyfsntfs_file_name_attribute_get_entry_modification_time_as_integer, METH_NOARGS, "get_entry_modification_time_as_integer() -> Integer or None\n" "\n" "Returns the entry modification date and time as a 64-bit integer containing a FILETIME value." }, { "get_file_attribute_flags", (PyCFunction) pyfsntfs_file_name_attribute_get_file_attribute_flags, METH_NOARGS, "get_file_attribute_flags() -> Integer\n" "\n" "Returns the file attribute flags." }, { "get_name_space", (PyCFunction) pyfsntfs_file_name_attribute_get_name_space, METH_NOARGS, "get_name_space() -> Integer\n" "\n" "Returns the name space." }, { "get_name", (PyCFunction) pyfsntfs_file_name_attribute_get_name, METH_NOARGS, "get_name() -> Unicode string or None\n" "\n" "Returns the name." }, /* Sentinel */ { NULL, NULL, 0, NULL } }; PyGetSetDef pyfsntfs_file_name_attribute_object_get_set_definitions[] = { { "parent_file_reference", (getter) pyfsntfs_file_name_attribute_get_parent_file_reference, (setter) 0, "The parent file reference, a combination of MFT entry index and sequence number.", NULL }, { "creation_time", (getter) pyfsntfs_file_name_attribute_get_creation_time, (setter) 0, "The creation date and time.", NULL }, { "modification_time", (getter) pyfsntfs_file_name_attribute_get_modification_time, (setter) 0, "The modification date and time.", NULL }, { "access_time", (getter) pyfsntfs_file_name_attribute_get_access_time, (setter) 0, "The access date and time.", NULL }, { "entry_modification_time", (getter) pyfsntfs_file_name_attribute_get_entry_modification_time, (setter) 0, "The entry modification date and time.", NULL }, { "file_attribute_flags", (getter) pyfsntfs_file_name_attribute_get_file_attribute_flags, (setter) 0, "The file attribute flags.", NULL }, { "name_space", (getter) pyfsntfs_file_name_attribute_get_name_space, (setter) 0, "The name space.", NULL }, { "name", (getter) pyfsntfs_file_name_attribute_get_name, (setter) 0, "The name.", NULL }, /* Sentinel */ { NULL, NULL, NULL, NULL, NULL } }; PyTypeObject pyfsntfs_file_name_attribute_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs.file_name_attribute", /* tp_basicsize */ sizeof( pyfsntfs_attribute_t ), /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_doc */ "pyfsntfs file name attribute object (wraps libfsntfs_attribute_t type LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME)", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ pyfsntfs_file_name_attribute_object_methods, /* tp_members */ 0, /* tp_getset */ pyfsntfs_file_name_attribute_object_get_set_definitions, /* tp_base */ &pyfsntfs_attribute_type_object, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Retrieves the parent file reference * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_name_attribute_get_parent_file_reference( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_name_attribute_get_parent_file_reference"; uint64_t file_reference = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_name_attribute_get_parent_file_reference( pyfsntfs_attribute->attribute, &file_reference, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve parent file reference.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( file_reference ); return( integer_object ); } /* Retrieves the creation date and time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_name_attribute_get_creation_time( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *date_time_object = NULL; static char *function = "pyfsntfs_file_name_attribute_get_creation_time"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_name_attribute_get_creation_time( pyfsntfs_attribute->attribute, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve creation time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } date_time_object = pyfsntfs_datetime_new_from_filetime( filetime ); return( date_time_object ); } /* Retrieves the creation date and time as an integer * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_name_attribute_get_creation_time_as_integer( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_name_attribute_get_creation_time_as_integer"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_name_attribute_get_creation_time( pyfsntfs_attribute->attribute, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve creation time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( filetime ); return( integer_object ); } /* Retrieves the modification date and time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_name_attribute_get_modification_time( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *date_time_object = NULL; static char *function = "pyfsntfs_file_name_attribute_get_modification_time"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_name_attribute_get_modification_time( pyfsntfs_attribute->attribute, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve modification time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } date_time_object = pyfsntfs_datetime_new_from_filetime( filetime ); return( date_time_object ); } /* Retrieves the modification date and time as an integer * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_name_attribute_get_modification_time_as_integer( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_name_attribute_get_modification_time_as_integer"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_name_attribute_get_modification_time( pyfsntfs_attribute->attribute, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve modification time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( filetime ); return( integer_object ); } /* Retrieves the access date and time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_name_attribute_get_access_time( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *date_time_object = NULL; static char *function = "pyfsntfs_file_name_attribute_get_access_time"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_name_attribute_get_access_time( pyfsntfs_attribute->attribute, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve access time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } date_time_object = pyfsntfs_datetime_new_from_filetime( filetime ); return( date_time_object ); } /* Retrieves the access date and time as an integer * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_name_attribute_get_access_time_as_integer( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_name_attribute_get_access_time_as_integer"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_name_attribute_get_access_time( pyfsntfs_attribute->attribute, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve access time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( filetime ); return( integer_object ); } /* Retrieves the entry modification date and time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_name_attribute_get_entry_modification_time( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *date_time_object = NULL; static char *function = "pyfsntfs_file_name_attribute_get_entry_modification_time"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_name_attribute_get_entry_modification_time( pyfsntfs_attribute->attribute, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve entry modification time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } date_time_object = pyfsntfs_datetime_new_from_filetime( filetime ); return( date_time_object ); } /* Retrieves the entry modification date and time as an integer * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_name_attribute_get_entry_modification_time_as_integer( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_name_attribute_get_entry_modification_time_as_integer"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_name_attribute_get_entry_modification_time( pyfsntfs_attribute->attribute, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve entry modification time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_signed_new_from_64bit( filetime ); return( integer_object ); } /* Retrieves the file attribute flags * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_name_attribute_get_file_attribute_flags( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_file_name_attribute_get_file_attribute_flags"; uint32_t file_attribute_flags = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_name_attribute_get_file_attribute_flags( pyfsntfs_attribute->attribute, &file_attribute_flags, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve file attribute flags.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( (uint64_t) file_attribute_flags ); return( integer_object ); } /* Retrieves the name space * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_name_attribute_get_name_space( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { PyObject *integer_object = NULL; libcerror_error_t *error = NULL; static char *function = "pyfsntfs_file_name_attribute_get_name_space"; uint8_t name_space = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_name_attribute_get_name_space( pyfsntfs_attribute->attribute, &name_space, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve name space.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( (uint64_t) name_space ); return( integer_object ); } /* Retrieves the name * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_file_name_attribute_get_name( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { PyObject *string_object = NULL; libcerror_error_t *error = NULL; uint8_t *utf8_string = NULL; static char *function = "pyfsntfs_file_utf8_stringute_get_name"; size_t utf8_string_size = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_file_name_attribute_get_utf8_name_size( pyfsntfs_attribute->attribute, &utf8_string_size, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to determine size of name as UTF-8 string.", function ); libcerror_error_free( &error ); goto on_error; } else if( ( result == 0 ) || ( utf8_string_size == 0 ) ) { Py_IncRef( Py_None ); return( Py_None ); } utf8_string = (uint8_t *) PyMem_Malloc( sizeof( uint8_t ) * utf8_string_size ); if( utf8_string == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create UTF-8 string.", function ); goto on_error; } Py_BEGIN_ALLOW_THREADS /* Using RFC 2279 UTF-8 to support unpaired UTF-16 surrogates */ result = libfsntfs_file_name_attribute_get_utf8_name( pyfsntfs_attribute->attribute, utf8_string, utf8_string_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve name as UTF-8 string.", function ); libcerror_error_free( &error ); goto on_error; } #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 string_object = pyfsntfs_string_new_from_utf8_rfc2279( utf8_string, utf8_string_size ); #else /* Pass the string length to PyUnicode_DecodeUTF8 * otherwise it makes the end of string character is part * of the string */ string_object = PyUnicode_DecodeUTF8( (char *) utf8_string, (Py_ssize_t) utf8_string_size - 1, NULL ); #endif if( string_object == NULL ) { PyErr_Format( PyExc_IOError, "%s: unable to convert UTF-8 string into Unicode object.", function ); goto on_error; } PyMem_Free( utf8_string ); return( string_object ); on_error: if( utf8_string != NULL ) { PyMem_Free( utf8_string ); } return( NULL ); } ================================================ FILE: pyfsntfs/pyfsntfs_file_name_attribute.h ================================================ /* * Python object definition of the libfsntfs file name attribute * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_FILE_NAME_ATTRIBUTE_H ) #define _PYFSNTFS_FILE_NAME_ATTRIBUTE_H #include #include #include "pyfsntfs_attribute.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif extern PyMethodDef pyfsntfs_file_name_attribute_object_methods[]; extern PyTypeObject pyfsntfs_file_name_attribute_type_object; PyObject *pyfsntfs_file_name_attribute_get_parent_file_reference( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_file_name_attribute_get_creation_time( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_file_name_attribute_get_creation_time_as_integer( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_file_name_attribute_get_modification_time( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_file_name_attribute_get_modification_time_as_integer( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_file_name_attribute_get_access_time( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_file_name_attribute_get_access_time_as_integer( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_file_name_attribute_get_entry_modification_time( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_file_name_attribute_get_entry_modification_time_as_integer( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_file_name_attribute_get_file_attribute_flags( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_file_name_attribute_get_name_space( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_file_name_attribute_get_name( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_FILE_NAME_ATTRIBUTE_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_file_object_io_handle.c ================================================ /* * Python file object IO handle functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "pyfsntfs_error.h" #include "pyfsntfs_file_object_io_handle.h" #include "pyfsntfs_integer.h" #include "pyfsntfs_libbfio.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_python.h" /* Creates a file object IO handle * Make sure the value file_object_io_handle is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int pyfsntfs_file_object_io_handle_initialize( pyfsntfs_file_object_io_handle_t **file_object_io_handle, PyObject *file_object, libcerror_error_t **error ) { static char *function = "pyfsntfs_file_object_io_handle_initialize"; if( file_object_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file object IO handle.", function ); return( -1 ); } if( *file_object_io_handle != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid file object IO handle value already set.", function ); return( -1 ); } if( file_object == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file object.", function ); return( -1 ); } *file_object_io_handle = (pyfsntfs_file_object_io_handle_t *) PyMem_Malloc( sizeof( pyfsntfs_file_object_io_handle_t ) ); if( *file_object_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create file object IO handle.", function ); goto on_error; } if( memory_set( *file_object_io_handle, 0, sizeof( pyfsntfs_file_object_io_handle_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear file object IO handle.", function ); goto on_error; } ( *file_object_io_handle )->file_object = file_object; Py_IncRef( ( *file_object_io_handle )->file_object ); return( 1 ); on_error: if( *file_object_io_handle != NULL ) { PyMem_Free( *file_object_io_handle ); *file_object_io_handle = NULL; } return( -1 ); } /* Initializes the file object IO handle * Returns 1 if successful or -1 on error */ int pyfsntfs_file_object_initialize( libbfio_handle_t **handle, PyObject *file_object, libcerror_error_t **error ) { pyfsntfs_file_object_io_handle_t *file_object_io_handle = NULL; static char *function = "pyfsntfs_file_object_initialize"; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } if( *handle != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid handle value already set.", function ); return( -1 ); } if( pyfsntfs_file_object_io_handle_initialize( &file_object_io_handle, file_object, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file object IO handle.", function ); goto on_error; } if( libbfio_handle_initialize( handle, (intptr_t *) file_object_io_handle, (int (*)(intptr_t **, libcerror_error_t **)) pyfsntfs_file_object_io_handle_free, (int (*)(intptr_t **, intptr_t *, libcerror_error_t **)) pyfsntfs_file_object_io_handle_clone, (int (*)(intptr_t *, int, libcerror_error_t **)) pyfsntfs_file_object_io_handle_open, (int (*)(intptr_t *, libcerror_error_t **)) pyfsntfs_file_object_io_handle_close, (ssize_t (*)(intptr_t *, uint8_t *, size_t, libcerror_error_t **)) pyfsntfs_file_object_io_handle_read, (ssize_t (*)(intptr_t *, const uint8_t *, size_t, libcerror_error_t **)) pyfsntfs_file_object_io_handle_write, (off64_t (*)(intptr_t *, off64_t, int, libcerror_error_t **)) pyfsntfs_file_object_io_handle_seek_offset, (int (*)(intptr_t *, libcerror_error_t **)) pyfsntfs_file_object_io_handle_exists, (int (*)(intptr_t *, libcerror_error_t **)) pyfsntfs_file_object_io_handle_is_open, (int (*)(intptr_t *, size64_t *, libcerror_error_t **)) pyfsntfs_file_object_io_handle_get_size, LIBBFIO_FLAG_IO_HANDLE_MANAGED | LIBBFIO_FLAG_IO_HANDLE_CLONE_BY_FUNCTION, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create handle.", function ); goto on_error; } return( 1 ); on_error: if( file_object_io_handle != NULL ) { pyfsntfs_file_object_io_handle_free( &file_object_io_handle, NULL ); } return( -1 ); } /* Frees a file object IO handle * Returns 1 if succesful or -1 on error */ int pyfsntfs_file_object_io_handle_free( pyfsntfs_file_object_io_handle_t **file_object_io_handle, libcerror_error_t **error ) { static char *function = "pyfsntfs_file_object_io_handle_free"; PyGILState_STATE gil_state = 0; if( file_object_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file object IO handle.", function ); return( -1 ); } if( *file_object_io_handle != NULL ) { gil_state = PyGILState_Ensure(); Py_DecRef( ( *file_object_io_handle )->file_object ); PyMem_Free( *file_object_io_handle ); *file_object_io_handle = NULL; PyGILState_Release( gil_state ); } return( 1 ); } /* Clones (duplicates) the file object IO handle and its attributes * Returns 1 if succesful or -1 on error */ int pyfsntfs_file_object_io_handle_clone( pyfsntfs_file_object_io_handle_t **destination_file_object_io_handle, pyfsntfs_file_object_io_handle_t *source_file_object_io_handle, libcerror_error_t **error ) { static char *function = "pyfsntfs_file_object_io_handle_clone"; if( destination_file_object_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid destination file object IO handle.", function ); return( -1 ); } if( *destination_file_object_io_handle != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: destination file object IO handle already set.", function ); return( -1 ); } if( source_file_object_io_handle == NULL ) { *destination_file_object_io_handle = NULL; return( 1 ); } if( pyfsntfs_file_object_io_handle_initialize( destination_file_object_io_handle, source_file_object_io_handle->file_object, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file object IO handle.", function ); return( -1 ); } if( *destination_file_object_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing destination file object IO handle.", function ); return( -1 ); } return( 1 ); } /* Opens the file object IO handle * Returns 1 if successful or -1 on error */ int pyfsntfs_file_object_io_handle_open( pyfsntfs_file_object_io_handle_t *file_object_io_handle, int access_flags, libcerror_error_t **error ) { static char *function = "pyfsntfs_file_object_io_handle_open"; if( file_object_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file object IO handle.", function ); return( -1 ); } if( file_object_io_handle->file_object == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid file object IO handle - missing file object.", function ); return( -1 ); } if( ( ( access_flags & LIBBFIO_ACCESS_FLAG_READ ) != 0 ) && ( ( access_flags & LIBBFIO_ACCESS_FLAG_WRITE ) != 0 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported access flags.", function ); return( -1 ); } if( ( access_flags & LIBBFIO_ACCESS_FLAG_WRITE ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: write access currently not supported.", function ); return( -1 ); } /* No need to do anything here, because the file object is already open */ file_object_io_handle->access_flags = access_flags; return( 1 ); } /* Closes the file object IO handle * Returns 0 if successful or -1 on error */ int pyfsntfs_file_object_io_handle_close( pyfsntfs_file_object_io_handle_t *file_object_io_handle, libcerror_error_t **error ) { static char *function = "pyfsntfs_file_object_io_handle_close"; if( file_object_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file object IO handle.", function ); return( -1 ); } if( file_object_io_handle->file_object == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid file object IO handle - missing file object.", function ); return( -1 ); } /* Do not close the file object, have Python deal with it */ file_object_io_handle->access_flags = 0; return( 0 ); } /* Reads a buffer from the file object * Make sure to hold the GIL state before calling this function * Returns the number of bytes read if successful, or -1 on error */ ssize_t pyfsntfs_file_object_read_buffer( PyObject *file_object, uint8_t *buffer, size_t size, libcerror_error_t **error ) { PyObject *argument_size = NULL; PyObject *method_name = NULL; PyObject *method_result = NULL; static char *function = "pyfsntfs_file_object_read_buffer"; char *safe_buffer = NULL; Py_ssize_t safe_read_count = 0; ssize_t read_count = 0; int result = 0; if( file_object == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file object.", function ); return( -1 ); } if( buffer == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid buffer.", function ); return( -1 ); } if( size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid size value exceeds maximum.", function ); return( -1 ); } if( size > 0 ) { #if PY_MAJOR_VERSION >= 3 method_name = PyUnicode_FromString( "read" ); #else method_name = PyString_FromString( "read" ); #endif argument_size = PyLong_FromSize_t( size ); PyErr_Clear(); method_result = PyObject_CallMethodObjArgs( file_object, method_name, argument_size, NULL ); if( PyErr_Occurred() ) { pyfsntfs_error_fetch( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read from file object.", function ); goto on_error; } if( method_result == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing method result.", function ); goto on_error; } #if PY_MAJOR_VERSION >= 3 result = PyObject_IsInstance( method_result, (PyObject *) &PyBytes_Type ); #else result = PyObject_IsInstance( method_result, (PyObject *) &PyString_Type ); #endif if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if method result is a binary string object.", function ); goto on_error; } else if( result == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: invalid method result value is not a binary string object.", function ); goto on_error; } #if PY_MAJOR_VERSION >= 3 result = PyBytes_AsStringAndSize( method_result, &safe_buffer, &safe_read_count ); #else result = PyString_AsStringAndSize( method_result, &safe_buffer, &safe_read_count ); #endif if( result == -1 ) { pyfsntfs_error_fetch( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read from file object.", function ); goto on_error; } if( safe_read_count > (Py_ssize_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid read count value exceeds maximum.", function ); goto on_error; } read_count = (ssize_t) safe_read_count; if( memory_copy( buffer, safe_buffer, read_count ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to copy data to buffer.", function ); goto on_error; } Py_DecRef( method_result ); Py_DecRef( argument_size ); Py_DecRef( method_name ); } return( read_count ); on_error: if( method_result != NULL ) { Py_DecRef( method_result ); } if( argument_size != NULL ) { Py_DecRef( argument_size ); } if( method_name != NULL ) { Py_DecRef( method_name ); } return( -1 ); } /* Reads a buffer from the file object IO handle * Returns the number of bytes read if successful, or -1 on error */ ssize_t pyfsntfs_file_object_io_handle_read( pyfsntfs_file_object_io_handle_t *file_object_io_handle, uint8_t *buffer, size_t size, libcerror_error_t **error ) { static char *function = "pyfsntfs_file_object_io_handle_read"; PyGILState_STATE gil_state = 0; ssize_t read_count = 0; if( file_object_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file object IO handle.", function ); return( -1 ); } gil_state = PyGILState_Ensure(); read_count = pyfsntfs_file_object_read_buffer( file_object_io_handle->file_object, buffer, size, error ); if( read_count == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read from file object.", function ); goto on_error; } PyGILState_Release( gil_state ); return( read_count ); on_error: PyGILState_Release( gil_state ); return( -1 ); } /* Writes a buffer to the file object * Make sure to hold the GIL state before calling this function * Returns the number of bytes written if successful, or -1 on error */ ssize_t pyfsntfs_file_object_write_buffer( PyObject *file_object, const uint8_t *buffer, size_t size, libcerror_error_t **error ) { PyObject *argument_string = NULL; PyObject *method_name = NULL; PyObject *method_result = NULL; static char *function = "pyfsntfs_file_object_write_buffer"; if( file_object == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file object.", function ); return( -1 ); } if( buffer == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid buffer.", function ); return( -1 ); } #if SIZEOF_SIZE_T > SIZEOF_INT if( size > (size_t) INT_MAX ) #else if( size > (size_t) SSIZE_MAX ) #endif { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid size value exceeds maximum.", function ); return( -1 ); } if( size > 0 ) { #if PY_MAJOR_VERSION >= 3 method_name = PyUnicode_FromString( "write" ); #else method_name = PyString_FromString( "write" ); #endif #if PY_MAJOR_VERSION >= 3 argument_string = PyBytes_FromStringAndSize( (char *) buffer, size ); #else argument_string = PyString_FromStringAndSize( (char *) buffer, size ); #endif PyErr_Clear(); method_result = PyObject_CallMethodObjArgs( file_object, method_name, argument_string, NULL ); if( PyErr_Occurred() ) { pyfsntfs_error_fetch( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_WRITE_FAILED, "%s: unable to write to file object.", function ); goto on_error; } if( method_result == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing method result.", function ); goto on_error; } Py_DecRef( method_result ); Py_DecRef( argument_string ); Py_DecRef( method_name ); } return( (ssize_t) size ); on_error: if( method_result != NULL ) { Py_DecRef( method_result ); } if( argument_string != NULL ) { Py_DecRef( argument_string ); } if( method_name != NULL ) { Py_DecRef( method_name ); } return( -1 ); } /* Writes a buffer to the file object IO handle * Returns the number of bytes written if successful, or -1 on error */ ssize_t pyfsntfs_file_object_io_handle_write( pyfsntfs_file_object_io_handle_t *file_object_io_handle, const uint8_t *buffer, size_t size, libcerror_error_t **error ) { static char *function = "pyfsntfs_file_object_io_handle_write"; PyGILState_STATE gil_state = 0; ssize_t write_count = 0; if( file_object_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file object IO handle.", function ); return( -1 ); } gil_state = PyGILState_Ensure(); write_count = pyfsntfs_file_object_write_buffer( file_object_io_handle->file_object, buffer, size, error ); if( write_count == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_WRITE_FAILED, "%s: unable to write from file object.", function ); goto on_error; } PyGILState_Release( gil_state ); return( write_count ); on_error: PyGILState_Release( gil_state ); return( -1 ); } /* Seeks a certain offset within the file object * Make sure to hold the GIL state before calling this function * Returns 1 if successful or -1 on error */ int pyfsntfs_file_object_seek_offset( PyObject *file_object, off64_t offset, int whence, libcerror_error_t **error ) { PyObject *argument_offset = NULL; PyObject *argument_whence = NULL; PyObject *method_name = NULL; PyObject *method_result = NULL; static char *function = "pyfsntfs_file_object_seek_offset"; if( file_object == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file object.", function ); return( -1 ); } #if defined( HAVE_LONG_LONG ) if( offset > (off64_t) INT64_MAX ) #else if( offset > (off64_t) LONG_MAX ) #endif { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid offset value exceeds maximum.", function ); return( -1 ); } if( ( whence != SEEK_CUR ) && ( whence != SEEK_END ) && ( whence != SEEK_SET ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported whence.", function ); return( -1 ); } #if PY_MAJOR_VERSION >= 3 method_name = PyUnicode_FromString( "seek" ); #else method_name = PyString_FromString( "seek" ); #endif #if defined( HAVE_LONG_LONG ) argument_offset = PyLong_FromLongLong( (PY_LONG_LONG) offset ); #else argument_offset = PyLong_FromLongLong( (long) offset ); #endif #if PY_MAJOR_VERSION >= 3 argument_whence = PyLong_FromLong( (long) whence ); #else argument_whence = PyInt_FromLong( (long) whence ); #endif PyErr_Clear(); method_result = PyObject_CallMethodObjArgs( file_object, method_name, argument_offset, argument_whence, NULL ); if( PyErr_Occurred() ) { pyfsntfs_error_fetch( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek in file object.", function ); goto on_error; } if( method_result == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing method result.", function ); goto on_error; } Py_DecRef( method_result ); Py_DecRef( argument_whence ); Py_DecRef( argument_offset ); Py_DecRef( method_name ); return( 1 ); on_error: if( method_result != NULL ) { Py_DecRef( method_result ); } if( argument_whence != NULL ) { Py_DecRef( argument_whence ); } if( argument_offset != NULL ) { Py_DecRef( argument_offset ); } if( method_name != NULL ) { Py_DecRef( method_name ); } return( -1 ); } /* Retrieves the current offset within the file object * Make sure to hold the GIL state before calling this function * Returns 1 if successful or -1 on error */ int pyfsntfs_file_object_get_offset( PyObject *file_object, off64_t *offset, libcerror_error_t **error ) { PyObject *method_name = NULL; PyObject *method_result = NULL; static char *function = "pyfsntfs_file_object_get_offset"; int result = 0; if( file_object == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file object.", function ); return( -1 ); } if( offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid offset.", function ); return( -1 ); } #if PY_MAJOR_VERSION >= 3 method_name = PyUnicode_FromString( "get_offset" ); #else method_name = PyString_FromString( "get_offset" ); #endif PyErr_Clear(); /* Determine if the file object has the get_offset method */ result = PyObject_HasAttr( file_object, method_name ); if( result == 0 ) { Py_DecRef( method_name ); /* Fall back to the tell method */ #if PY_MAJOR_VERSION >= 3 method_name = PyUnicode_FromString( "tell" ); #else method_name = PyString_FromString( "tell" ); #endif } PyErr_Clear(); method_result = PyObject_CallMethodObjArgs( file_object, method_name, NULL ); if( PyErr_Occurred() ) { pyfsntfs_error_fetch( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve current offset in file object.", function ); goto on_error; } if( method_result == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing method result.", function ); goto on_error; } if( pyfsntfs_integer_signed_copy_to_64bit( method_result, offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to convert method result into current offset of file object.", function ); goto on_error; } Py_DecRef( method_result ); Py_DecRef( method_name ); return( 1 ); on_error: if( method_result != NULL ) { Py_DecRef( method_result ); } if( method_name != NULL ) { Py_DecRef( method_name ); } return( -1 ); } /* Seeks a certain offset within the file object IO handle * Returns the offset if the seek is successful or -1 on error */ off64_t pyfsntfs_file_object_io_handle_seek_offset( pyfsntfs_file_object_io_handle_t *file_object_io_handle, off64_t offset, int whence, libcerror_error_t **error ) { static char *function = "pyfsntfs_file_object_io_handle_seek_offset"; PyGILState_STATE gil_state = 0; if( file_object_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file object IO handle.", function ); return( -1 ); } gil_state = PyGILState_Ensure(); if( pyfsntfs_file_object_seek_offset( file_object_io_handle->file_object, offset, whence, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek in file object.", function ); goto on_error; } if( pyfsntfs_file_object_get_offset( file_object_io_handle->file_object, &offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to retrieve current offset in file object.", function ); goto on_error; } PyGILState_Release( gil_state ); return( offset ); on_error: PyGILState_Release( gil_state ); return( -1 ); } /* Function to determine if a file exists * Returns 1 if file exists, 0 if not or -1 on error */ int pyfsntfs_file_object_io_handle_exists( pyfsntfs_file_object_io_handle_t *file_object_io_handle, libcerror_error_t **error ) { static char *function = "pyfsntfs_file_object_io_handle_exists"; if( file_object_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file object IO handle.", function ); return( -1 ); } if( file_object_io_handle->file_object == NULL ) { return( 0 ); } return( 1 ); } /* Check if the file is open * Returns 1 if open, 0 if not or -1 on error */ int pyfsntfs_file_object_io_handle_is_open( pyfsntfs_file_object_io_handle_t *file_object_io_handle, libcerror_error_t **error ) { static char *function = "pyfsntfs_file_object_io_handle_is_open"; if( file_object_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file object IO handle.", function ); return( -1 ); } if( file_object_io_handle->file_object == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid file object IO handle - missing file object.", function ); return( -1 ); } /* As far as BFIO is concerned the file object is always open */ return( 1 ); } /* Retrieves the size of the file object * Make sure to hold the GIL state before calling this function * Returns 1 if successful or -1 on error */ int pyfsntfs_file_object_get_size( PyObject *file_object, size64_t *size, libcerror_error_t **error ) { PyObject *method_name = NULL; PyObject *method_result = NULL; static char *function = "pyfsntfs_file_object_get_size"; if( file_object == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file object.", function ); return( -1 ); } if( size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid size.", function ); return( -1 ); } #if PY_MAJOR_VERSION >= 3 method_name = PyUnicode_FromString( "get_size" ); #else method_name = PyString_FromString( "get_size" ); #endif PyErr_Clear(); method_result = PyObject_CallMethodObjArgs( file_object, method_name, NULL ); if( PyErr_Occurred() ) { pyfsntfs_error_fetch( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of file object.", function ); goto on_error; } if( method_result == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing method result.", function ); goto on_error; } if( pyfsntfs_integer_unsigned_copy_to_64bit( method_result, size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to convert method result into size of file object.", function ); goto on_error; } Py_DecRef( method_result ); Py_DecRef( method_name ); return( 1 ); on_error: if( method_result != NULL ) { Py_DecRef( method_result ); } if( method_name != NULL ) { Py_DecRef( method_name ); } return( -1 ); } /* Retrieves the file size * Returns 1 if successful or -1 on error */ int pyfsntfs_file_object_io_handle_get_size( pyfsntfs_file_object_io_handle_t *file_object_io_handle, size64_t *size, libcerror_error_t **error ) { PyObject *method_name = NULL; static char *function = "pyfsntfs_file_object_io_handle_get_size"; PyGILState_STATE gil_state = 0; off64_t current_offset = 0; int result = 0; if( file_object_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file object IO handle.", function ); return( -1 ); } if( file_object_io_handle->file_object == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid file object IO handle - missing file object.", function ); return( -1 ); } gil_state = PyGILState_Ensure(); #if PY_MAJOR_VERSION >= 3 method_name = PyUnicode_FromString( "get_size" ); #else method_name = PyString_FromString( "get_size" ); #endif PyErr_Clear(); /* Determine if the file object has the get_size method */ result = PyObject_HasAttr( file_object_io_handle->file_object, method_name ); if( result != 0 ) { if( pyfsntfs_file_object_get_size( file_object_io_handle->file_object, size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of file object.", function ); goto on_error; } } else { if( pyfsntfs_file_object_get_offset( file_object_io_handle->file_object, ¤t_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve current offset in file object.", function ); goto on_error; } if( pyfsntfs_file_object_seek_offset( file_object_io_handle->file_object, 0, SEEK_END, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek end of file object.", function ); goto on_error; } if( pyfsntfs_file_object_get_offset( file_object_io_handle->file_object, (off64_t *) size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve end offset in file object.", function ); pyfsntfs_file_object_seek_offset( file_object_io_handle->file_object, current_offset, SEEK_SET, NULL ); goto on_error; } if( pyfsntfs_file_object_seek_offset( file_object_io_handle->file_object, current_offset, SEEK_SET, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek current offset in file object.", function ); goto on_error; } } Py_DecRef( method_name ); PyGILState_Release( gil_state ); return( 1 ); on_error: if( method_name != NULL ) { Py_DecRef( method_name ); } PyGILState_Release( gil_state ); return( 1 ); } ================================================ FILE: pyfsntfs/pyfsntfs_file_object_io_handle.h ================================================ /* * Python file object IO handle functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_FILE_OBJECT_IO_HANDLE_H ) #define _PYFSNTFS_FILE_OBJECT_IO_HANDLE_H #include #include #include "pyfsntfs_libbfio.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct pyfsntfs_file_object_io_handle pyfsntfs_file_object_io_handle_t; struct pyfsntfs_file_object_io_handle { /* The python file (like) object */ PyObject *file_object; /* The access flags */ int access_flags; }; int pyfsntfs_file_object_io_handle_initialize( pyfsntfs_file_object_io_handle_t **file_object_io_handle, PyObject *file_object, libcerror_error_t **error ); int pyfsntfs_file_object_initialize( libbfio_handle_t **handle, PyObject *file_object, libcerror_error_t **error ); int pyfsntfs_file_object_io_handle_free( pyfsntfs_file_object_io_handle_t **file_object_io_handle, libcerror_error_t **error ); int pyfsntfs_file_object_io_handle_clone( pyfsntfs_file_object_io_handle_t **destination_file_object_io_handle, pyfsntfs_file_object_io_handle_t *source_file_object_io_handle, libcerror_error_t **error ); int pyfsntfs_file_object_io_handle_open( pyfsntfs_file_object_io_handle_t *file_object_io_handle, int access_flags, libcerror_error_t **error ); int pyfsntfs_file_object_io_handle_close( pyfsntfs_file_object_io_handle_t *file_object_io_handle, libcerror_error_t **error ); ssize_t pyfsntfs_file_object_read_buffer( PyObject *file_object, uint8_t *buffer, size_t size, libcerror_error_t **error ); ssize_t pyfsntfs_file_object_io_handle_read( pyfsntfs_file_object_io_handle_t *file_object_io_handle, uint8_t *buffer, size_t size, libcerror_error_t **error ); ssize_t pyfsntfs_file_object_write_buffer( PyObject *file_object, const uint8_t *buffer, size_t size, libcerror_error_t **error ); ssize_t pyfsntfs_file_object_io_handle_write( pyfsntfs_file_object_io_handle_t *file_object_io_handle, const uint8_t *buffer, size_t size, libcerror_error_t **error ); int pyfsntfs_file_object_seek_offset( PyObject *file_object, off64_t offset, int whence, libcerror_error_t **error ); int pyfsntfs_file_object_get_offset( PyObject *file_object, off64_t *offset, libcerror_error_t **error ); off64_t pyfsntfs_file_object_io_handle_seek_offset( pyfsntfs_file_object_io_handle_t *file_object_io_handle, off64_t offset, int whence, libcerror_error_t **error ); int pyfsntfs_file_object_io_handle_exists( pyfsntfs_file_object_io_handle_t *file_object_io_handle, libcerror_error_t **error ); int pyfsntfs_file_object_io_handle_is_open( pyfsntfs_file_object_io_handle_t *file_object_io_handle, libcerror_error_t **error ); int pyfsntfs_file_object_get_size( PyObject *file_object, size64_t *size, libcerror_error_t **error ); int pyfsntfs_file_object_io_handle_get_size( pyfsntfs_file_object_io_handle_t *file_object_io_handle, size64_t *size, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_FILE_OBJECT_IO_HANDLE_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_guid.c ================================================ /* * GUID functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include "pyfsntfs_error.h" #include "pyfsntfs_guid.h" #include "pyfsntfs_libfguid.h" #include "pyfsntfs_python.h" /* Creates a new string object from a GUID * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_string_new_from_guid( const uint8_t *guid_buffer, size_t guid_buffer_size ) { char guid_string[ 48 ]; libcerror_error_t *error = NULL; libfguid_identifier_t *guid = NULL; PyObject *string_object = NULL; static char *function = "pyfsntfs_string_new_from_guid"; if( libfguid_identifier_initialize( &guid, &error ) != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to create GUID.", function ); libcerror_error_free( &error ); goto on_error; } if( libfguid_identifier_copy_from_byte_stream( guid, guid_buffer, guid_buffer_size, LIBFGUID_ENDIAN_LITTLE, &error ) != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to copy byte stream to GUID.", function ); libcerror_error_free( &error ); goto on_error; } if( libfguid_identifier_copy_to_utf8_string( guid, (uint8_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, &error ) != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to copy GUID to string.", function ); libcerror_error_free( &error ); goto on_error; } if( libfguid_identifier_free( &guid, &error ) != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to free GUID.", function ); libcerror_error_free( &error ); goto on_error; } /* Pass the string length to PyUnicode_DecodeUTF8 * otherwise it makes the end of string character is part * of the string */ string_object = PyUnicode_DecodeUTF8( guid_string, (Py_ssize_t) 36, NULL ); return( string_object ); on_error: if( guid != NULL ) { libfguid_identifier_free( &guid, NULL ); } return( NULL ); } ================================================ FILE: pyfsntfs/pyfsntfs_guid.h ================================================ /* * GUID functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_GUID_H ) #define _PYFSNTFS_GUID_H #include #include #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif PyObject *pyfsntfs_string_new_from_guid( const uint8_t *guid_buffer, size_t guid_buffer_size ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_GUID_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_integer.c ================================================ /* * Integer functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include "pyfsntfs_error.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_integer.h" #include "pyfsntfs_python.h" /* Creates a new signed integer object from a 64-bit value * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_integer_signed_new_from_64bit( int64_t value_64bit ) { PyObject *integer_object = NULL; static char *function = "pyfsntfs_integer_signed_new_from_64bit"; #if defined( HAVE_LONG_LONG ) if( ( value_64bit < (int64_t) LLONG_MIN ) || ( value_64bit > (int64_t) LLONG_MAX ) ) { PyErr_Format( PyExc_OverflowError, "%s: 64-bit value out of bounds.", function ); return( NULL ); } integer_object = PyLong_FromLongLong( (long long) value_64bit ); #else if( current_offset > (off64_t) LONG_MAX ) { PyErr_Format( PyExc_OverflowError, "%s: 64-bit value out of bounds.", function ); return( NULL ); } integer_object = PyLong_FromLong( (long) value_64bit ); #endif return( integer_object ); } /* Creates a new unsigned integer object from a 64-bit value * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_integer_unsigned_new_from_64bit( uint64_t value_64bit ) { PyObject *integer_object = NULL; static char *function = "pyfsntfs_integer_unsigned_new_from_64bit"; #if defined( HAVE_LONG_LONG ) if( value_64bit > (uint64_t) ULLONG_MAX ) { PyErr_Format( PyExc_OverflowError, "%s: 64-bit value exceeds maximum.", function ); return( NULL ); } integer_object = PyLong_FromUnsignedLongLong( (long long) value_64bit ); #else if( value_64bit > (uint64_t) ULONG_MAX ) { PyErr_Format( PyExc_OverflowError, "%s: 64-bit value exceeds maximum.", function ); return( NULL ); } integer_object = PyLong_FromUnsignedLong( (long) value_64bit ); #endif return( integer_object ); } /* Copies a Python int or long object to a signed 64-bit value * Returns 1 if successful or -1 on error */ int pyfsntfs_integer_signed_copy_to_64bit( PyObject *integer_object, int64_t *value_64bit, libcerror_error_t **error ) { static char *function = "pyfsntfs_integer_signed_copy_to_64bit"; int result = 0; #if defined( HAVE_LONG_LONG ) PY_LONG_LONG long_value = 0; #else long long_value = 0; #endif if( integer_object == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid integer object.", function ); return( -1 ); } PyErr_Clear(); result = PyObject_IsInstance( integer_object, (PyObject *) &PyLong_Type ); if( result == -1 ) { pyfsntfs_error_fetch( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if integer object is of type long.", function ); return( -1 ); } else if( result != 0 ) { PyErr_Clear(); #if defined( HAVE_LONG_LONG ) long_value = PyLong_AsLongLong( integer_object ); #else long_value = PyLong_AsLong( integer_object ); #endif } #if PY_MAJOR_VERSION < 3 if( result == 0 ) { PyErr_Clear(); result = PyObject_IsInstance( integer_object, (PyObject *) &PyInt_Type ); if( result == -1 ) { pyfsntfs_error_fetch( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if integer object is of type int.", function ); return( -1 ); } else if( result != 0 ) { PyErr_Clear(); long_value = PyInt_AsLong( integer_object ); } } #endif /* PY_MAJOR_VERSION < 3 */ if( result == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unsupported integer object type.", function ); return( -1 ); } if( PyErr_Occurred() ) { pyfsntfs_error_fetch( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to convert integer object to long.", function ); return( -1 ); } #if defined( HAVE_LONG_LONG ) && ( SIZEOF_LONG_LONG > 8 ) if( ( long_value < (PY_LONG_LONG) INT64_MIN ) || ( long_value > (PY_LONG_LONG) INT64_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid long value out of bounds.", function ); return( -1 ); } #elif ( SIZEOF_LONG > 8 ) if( ( long_value > (long) INT64_MIN ) || ( long_value > (long) INT64_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid long value out of bounds.", function ); return( -1 ); } #endif *value_64bit = (int64_t) long_value; return( 1 ); } /* Copies a Python int or long object to an unsigned 64-bit value * Returns 1 if successful or -1 on error */ int pyfsntfs_integer_unsigned_copy_to_64bit( PyObject *integer_object, uint64_t *value_64bit, libcerror_error_t **error ) { static char *function = "pyfsntfs_integer_unsigned_copy_to_64bit"; int result = 0; #if defined( HAVE_LONG_LONG ) PY_LONG_LONG long_value = 0; #else long long_value = 0; #endif if( integer_object == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid integer object.", function ); return( -1 ); } PyErr_Clear(); result = PyObject_IsInstance( integer_object, (PyObject *) &PyLong_Type ); if( result == -1 ) { pyfsntfs_error_fetch( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if integer object is of type long.", function ); return( -1 ); } else if( result != 0 ) { PyErr_Clear(); #if defined( HAVE_LONG_LONG ) long_value = PyLong_AsUnsignedLongLong( integer_object ); #else long_value = PyLong_AsUnsignedLong( integer_object ); #endif } #if PY_MAJOR_VERSION < 3 if( result == 0 ) { PyErr_Clear(); result = PyObject_IsInstance( integer_object, (PyObject *) &PyInt_Type ); if( result == -1 ) { pyfsntfs_error_fetch( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if integer object is of type int.", function ); return( -1 ); } else if( result != 0 ) { PyErr_Clear(); #if defined( HAVE_LONG_LONG ) long_value = PyInt_AsUnsignedLongLongMask( integer_object ); #else long_value = PyInt_AsUnsignedLongMask( integer_object ); #endif } } #endif /* PY_MAJOR_VERSION < 3 */ if( result == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unsupported integer object type.", function ); return( -1 ); } if( PyErr_Occurred() ) { pyfsntfs_error_fetch( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to convert integer object to long.", function ); return( -1 ); } #if defined( HAVE_LONG_LONG ) #if ( SIZEOF_LONG_LONG > 8 ) if( ( long_value < (PY_LONG_LONG) 0 ) || ( long_value > (PY_LONG_LONG) UINT64_MAX ) ) #else if( long_value < (PY_LONG_LONG) 0 ) #endif { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid long value out of bounds.", function ); return( -1 ); } #else #if ( SIZEOF_LONG > 8 ) if( ( long_value < (long) 0 ) || ( long_value > (long) UINT64_MAX ) ) #else if( long_value < (PY_LONG_LONG) 0 ) #endif { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid long value out of bounds.", function ); return( -1 ); } #endif *value_64bit = (uint64_t) long_value; return( 1 ); } ================================================ FILE: pyfsntfs/pyfsntfs_integer.h ================================================ /* * Integer functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_INTEGER_H ) #define _PYFSNTFS_INTEGER_H #include #include #include "pyfsntfs_libcerror.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif PyObject *pyfsntfs_integer_signed_new_from_64bit( int64_t value_64bit ); PyObject *pyfsntfs_integer_unsigned_new_from_64bit( uint64_t value_64bit ); int pyfsntfs_integer_signed_copy_to_64bit( PyObject *integer_object, int64_t *value_64bit, libcerror_error_t **error ); int pyfsntfs_integer_unsigned_copy_to_64bit( PyObject *integer_object, uint64_t *value_64bit, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_INTEGER_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_libbfio.h ================================================ /* * The libbfio header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_LIBBFIO_H ) #define _PYFSNTFS_LIBBFIO_H #include /* Define HAVE_LOCAL_LIBBFIO for local use of libbfio */ #if defined( HAVE_LOCAL_LIBBFIO ) #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBBFIO_DLL_IMPORT * before including libbfio.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBBFIO_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBBFIO ) */ #endif /* !defined( _PYFSNTFS_LIBBFIO_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_libcerror.h ================================================ /* * The libcerror header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_LIBCERROR_H ) #define _PYFSNTFS_LIBCERROR_H #include /* Define HAVE_LOCAL_LIBCERROR for local use of libcerror */ #if defined( HAVE_LOCAL_LIBCERROR ) #include #include #include #include #else /* If libtool DLL support is enabled set LIBCERROR_DLL_IMPORT * before including libcerror.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBCERROR_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBCERROR ) */ #endif /* !defined( _PYFSNTFS_LIBCERROR_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_libclocale.h ================================================ /* * The libclocale header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_LIBCLOCALE_H ) #define _PYFSNTFS_LIBCLOCALE_H #include /* Define HAVE_LOCAL_LIBCLOCALE for local use of libclocale */ #if defined( HAVE_LOCAL_LIBCLOCALE ) #include #include #include #include #else /* If libtool DLL support is enabled set LIBCLOCALE_DLL_IMPORT * before including libclocale.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBCLOCALE_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBCLOCALE ) */ #endif /* !defined( _PYFSNTFS_LIBCLOCALE_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_libfguid.h ================================================ /* * The libfguid header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_LIBFGUID_H ) #define _PYFSNTFS_LIBFGUID_H #include /* Define HAVE_LOCAL_LIBFGUID for local use of libfguid */ #if defined( HAVE_LOCAL_LIBFGUID ) #include #include #include #else /* If libtool DLL support is enabled set LIBFGUID_DLL_IMPORT * before including libfguid.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBFGUID_DLL_IMPORT #endif #include #endif #endif /* !defined( _PYFSNTFS_LIBFGUID_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_libfsntfs.h ================================================ /* * The internal libfsntfs header * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_LIBFSNTFS_H ) #define _PYFSNTFS_LIBFSNTFS_H #include #include #endif /* !defined( _PYFSNTFS_LIBFSNTFS_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_libuna.h ================================================ /* * The libuna header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_LIBUNA_H ) #define _PYFSNTFS_LIBUNA_H #include /* Define HAVE_LOCAL_LIBUNA for local use of libuna */ #if defined( HAVE_LOCAL_LIBUNA ) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBUNA_DLL_IMPORT * before including libuna.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBUNA_DLL_IMPORT #endif #include #endif #endif /* !defined( _PYFSNTFS_LIBUNA_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_mft_metadata_file.c ================================================ /* * Python object definition of the libfsntfs MFT metadata file * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_error.h" #include "pyfsntfs_file_entry.h" #include "pyfsntfs_file_object_io_handle.h" #include "pyfsntfs_integer.h" #include "pyfsntfs_libbfio.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_mft_metadata_file.h" #include "pyfsntfs_mft_metadata_file_entries.h" #include "pyfsntfs_python.h" #include "pyfsntfs_unused.h" #if !defined( LIBFSNTFS_HAVE_BFIO ) LIBFSNTFS_EXTERN \ int libfsntfs_mft_metadata_file_open_file_io_handle( libfsntfs_mft_metadata_file_t *mft_metadata_file, libbfio_handle_t *file_io_handle, int access_flags, libfsntfs_error_t **error ); #endif /* !defined( LIBFSNTFS_HAVE_BFIO ) */ PyMethodDef pyfsntfs_mft_metadata_file_object_methods[] = { /* Functions to access the MFT metadata file */ { "open", (PyCFunction) pyfsntfs_mft_metadata_file_open, METH_VARARGS | METH_KEYWORDS, "open(filename, mode='r') -> None\n" "\n" "Opens a MFT metadata file." }, { "open_file_object", (PyCFunction) pyfsntfs_mft_metadata_file_open_file_object, METH_VARARGS | METH_KEYWORDS, "open_file_object(file_object, mode='r') -> None\n" "\n" "Opens a MFT metadata file using a file-like object." }, { "close", (PyCFunction) pyfsntfs_mft_metadata_file_close, METH_NOARGS, "close() -> None\n" "\n" "Closes a MFT metadata file." }, /* Functions to access the MFT metadata file values */ { "get_volume_name", (PyCFunction) pyfsntfs_mft_metadata_file_get_volume_name, METH_NOARGS, "get_volume_name() -> Unicode string or None\n" "\n" "Retrieves the volume name." }, /* Functions to access the file entries */ { "get_number_of_file_entries", (PyCFunction) pyfsntfs_mft_metadata_file_get_number_of_file_entries, METH_NOARGS, "get_number_of_file_entries() -> Integer\n" "\n" "Retrieves the number of file entries." }, { "get_file_entry", (PyCFunction) pyfsntfs_mft_metadata_file_get_file_entry, METH_VARARGS | METH_KEYWORDS, "get_file_entry(file_entry_index) -> Object\n" "\n" "Retrieves a specific file entry." }, /* Sentinel */ { NULL, NULL, 0, NULL } }; PyGetSetDef pyfsntfs_mft_metadata_file_object_get_set_definitions[] = { { "volume_name", (getter) pyfsntfs_mft_metadata_file_get_volume_name, (setter) 0, "The volume name.", NULL }, { "number_of_file_entries", (getter) pyfsntfs_mft_metadata_file_get_number_of_file_entries, (setter) 0, "The number of file entries.", NULL }, { "file_entries", (getter) pyfsntfs_mft_metadata_file_get_file_entries, (setter) 0, "The file entries", NULL }, /* Sentinel */ { NULL, NULL, NULL, NULL, NULL } }; PyTypeObject pyfsntfs_mft_metadata_file_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs.mft_metadata_file", /* tp_basicsize */ sizeof( pyfsntfs_mft_metadata_file_t ), /* tp_itemsize */ 0, /* tp_dealloc */ (destructor) pyfsntfs_mft_metadata_file_free, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_doc */ "pyfsntfs MFT metadata file object (wraps libfsntfs_mft_metadata_file_t)", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ pyfsntfs_mft_metadata_file_object_methods, /* tp_members */ 0, /* tp_getset */ pyfsntfs_mft_metadata_file_object_get_set_definitions, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ (initproc) pyfsntfs_mft_metadata_file_init, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Initializes a MFT metadata file object * Returns 0 if successful or -1 on error */ int pyfsntfs_mft_metadata_file_init( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file ) { libcerror_error_t *error = NULL; static char *function = "pyfsntfs_mft_metadata_file_init"; if( pyfsntfs_mft_metadata_file == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid MFT metadata file.", function ); return( -1 ); } /* Make sure libfsntfs MFT metadata file is set to NULL */ pyfsntfs_mft_metadata_file->mft_metadata_file = NULL; pyfsntfs_mft_metadata_file->file_io_handle = NULL; if( libfsntfs_mft_metadata_file_initialize( &( pyfsntfs_mft_metadata_file->mft_metadata_file ), &error ) != 1 ) { pyfsntfs_error_raise( error, PyExc_MemoryError, "%s: unable to initialize MFT metadata file.", function ); libcerror_error_free( &error ); return( -1 ); } return( 0 ); } /* Frees a MFT metadata file object */ void pyfsntfs_mft_metadata_file_free( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file ) { struct _typeobject *ob_type = NULL; libcerror_error_t *error = NULL; static char *function = "pyfsntfs_mft_metadata_file_free"; int result = 0; if( pyfsntfs_mft_metadata_file == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid MFT metadata file.", function ); return; } ob_type = Py_TYPE( pyfsntfs_mft_metadata_file ); if( ob_type == NULL ) { PyErr_Format( PyExc_ValueError, "%s: missing ob_type.", function ); return; } if( ob_type->tp_free == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid ob_type - missing tp_free.", function ); return; } if( pyfsntfs_mft_metadata_file->mft_metadata_file != NULL ) { Py_BEGIN_ALLOW_THREADS result = libfsntfs_mft_metadata_file_free( &( pyfsntfs_mft_metadata_file->mft_metadata_file ), &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_MemoryError, "%s: unable to free libfsntfs MFT metadata file.", function ); libcerror_error_free( &error ); } } ob_type->tp_free( (PyObject*) pyfsntfs_mft_metadata_file ); } /* Opens a MFT metadata file * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_mft_metadata_file_open( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file, PyObject *arguments, PyObject *keywords ) { PyObject *string_object = NULL; libcerror_error_t *error = NULL; static char *function = "pyfsntfs_mft_metadata_file_open"; static char *keyword_list[] = { "filename", "mode", NULL }; const char *filename_narrow = NULL; char *mode = NULL; int result = 0; #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) const wchar_t *filename_wide = NULL; #else PyObject *utf8_string_object = NULL; #endif if( pyfsntfs_mft_metadata_file == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid MFT metadata file.", function ); return( NULL ); } /* Note that PyArg_ParseTupleAndKeywords with "s" will force Unicode strings to be converted to narrow character string. * On Windows the narrow character strings contains an extended ASCII string with a codepage. Hence we get a conversion * exception. This will also fail if the default encoding is not set correctly. We cannot use "u" here either since that * does not allow us to pass non Unicode string objects and Python (at least 2.7) does not seems to automatically upcast them. */ if( PyArg_ParseTupleAndKeywords( arguments, keywords, "O|s", keyword_list, &string_object, &mode ) == 0 ) { return( NULL ); } if( ( mode != NULL ) && ( mode[ 0 ] != 'r' ) ) { PyErr_Format( PyExc_ValueError, "%s: unsupported mode: %s.", function, mode ); return( NULL ); } PyErr_Clear(); result = PyObject_IsInstance( string_object, (PyObject *) &PyUnicode_Type ); if( result == -1 ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to determine if string object is of type Unicode.", function ); return( NULL ); } else if( result != 0 ) { PyErr_Clear(); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 filename_wide = (wchar_t *) PyUnicode_AsWideCharString( string_object, NULL ); #else filename_wide = (wchar_t *) PyUnicode_AsUnicode( string_object ); #endif Py_BEGIN_ALLOW_THREADS result = libfsntfs_mft_metadata_file_open_wide( pyfsntfs_mft_metadata_file->mft_metadata_file, filename_wide, LIBFSNTFS_OPEN_READ, &error ); Py_END_ALLOW_THREADS #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 PyMem_Free( filename_wide ); #endif #else utf8_string_object = PyUnicode_AsUTF8String( string_object ); if( utf8_string_object == NULL ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to convert unicode string to UTF-8.", function ); return( NULL ); } #if PY_MAJOR_VERSION >= 3 filename_narrow = PyBytes_AsString( utf8_string_object ); #else filename_narrow = PyString_AsString( utf8_string_object ); #endif Py_BEGIN_ALLOW_THREADS result = libfsntfs_mft_metadata_file_open( pyfsntfs_mft_metadata_file->mft_metadata_file, filename_narrow, LIBFSNTFS_OPEN_READ, &error ); Py_END_ALLOW_THREADS Py_DecRef( utf8_string_object ); #endif if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to open MFT metadata file.", function ); libcerror_error_free( &error ); return( NULL ); } Py_IncRef( Py_None ); return( Py_None ); } PyErr_Clear(); #if PY_MAJOR_VERSION >= 3 result = PyObject_IsInstance( string_object, (PyObject *) &PyBytes_Type ); #else result = PyObject_IsInstance( string_object, (PyObject *) &PyString_Type ); #endif if( result == -1 ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to determine if string object is of type string.", function ); return( NULL ); } else if( result != 0 ) { PyErr_Clear(); #if PY_MAJOR_VERSION >= 3 filename_narrow = PyBytes_AsString( string_object ); #else filename_narrow = PyString_AsString( string_object ); #endif Py_BEGIN_ALLOW_THREADS result = libfsntfs_mft_metadata_file_open( pyfsntfs_mft_metadata_file->mft_metadata_file, filename_narrow, LIBFSNTFS_OPEN_READ, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to open MFT metadata file.", function ); libcerror_error_free( &error ); return( NULL ); } Py_IncRef( Py_None ); return( Py_None ); } PyErr_Format( PyExc_TypeError, "%s: unsupported string object type.", function ); return( NULL ); } /* Opens a MFT metadata file using a file-like object * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_mft_metadata_file_open_file_object( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file, PyObject *arguments, PyObject *keywords ) { PyObject *file_object = NULL; libcerror_error_t *error = NULL; char *mode = NULL; static char *keyword_list[] = { "file_object", "mode", NULL }; static char *function = "pyfsntfs_mft_metadata_file_open_file_object"; int result = 0; if( pyfsntfs_mft_metadata_file == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid MFT metadata file.", function ); return( NULL ); } if( PyArg_ParseTupleAndKeywords( arguments, keywords, "O|s", keyword_list, &file_object, &mode ) == 0 ) { return( NULL ); } if( ( mode != NULL ) && ( mode[ 0 ] != 'r' ) ) { PyErr_Format( PyExc_ValueError, "%s: unsupported mode: %s.", function, mode ); return( NULL ); } if( pyfsntfs_file_object_initialize( &( pyfsntfs_mft_metadata_file->file_io_handle ), file_object, &error ) != 1 ) { pyfsntfs_error_raise( error, PyExc_MemoryError, "%s: unable to initialize file IO handle.", function ); libcerror_error_free( &error ); goto on_error; } Py_BEGIN_ALLOW_THREADS result = libfsntfs_mft_metadata_file_open_file_io_handle( pyfsntfs_mft_metadata_file->mft_metadata_file, pyfsntfs_mft_metadata_file->file_io_handle, LIBFSNTFS_OPEN_READ, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to open MFT metadata file.", function ); libcerror_error_free( &error ); goto on_error; } Py_IncRef( Py_None ); return( Py_None ); on_error: if( pyfsntfs_mft_metadata_file->file_io_handle != NULL ) { libbfio_handle_free( &( pyfsntfs_mft_metadata_file->file_io_handle ), NULL ); } return( NULL ); } /* Closes a MFT metadata file * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_mft_metadata_file_close( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; static char *function = "pyfsntfs_mft_metadata_file_close"; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_mft_metadata_file == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid MFT metadata file.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_mft_metadata_file_close( pyfsntfs_mft_metadata_file->mft_metadata_file, &error ); Py_END_ALLOW_THREADS if( result != 0 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to close MFT metadata file.", function ); libcerror_error_free( &error ); return( NULL ); } if( pyfsntfs_mft_metadata_file->file_io_handle != NULL ) { Py_BEGIN_ALLOW_THREADS result = libbfio_handle_free( &( pyfsntfs_mft_metadata_file->file_io_handle ), &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to free libbfio file IO handle.", function ); libcerror_error_free( &error ); return( NULL ); } } Py_IncRef( Py_None ); return( Py_None ); } /* Retrieves the volume name * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_mft_metadata_file_get_volume_name( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *string_object = NULL; uint8_t *volume_name = NULL; static char *function = "pyfsntfs_mft_metadata_file_get_volume_name"; size_t volume_name_size = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_mft_metadata_file == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid MFT metadata file.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_mft_metadata_file_get_utf8_volume_name_size( pyfsntfs_mft_metadata_file->mft_metadata_file, &volume_name_size, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve volume name size.", function ); libcerror_error_free( &error ); goto on_error; } else if( ( result == 0 ) || ( volume_name_size == 0 ) ) { Py_IncRef( Py_None ); return( Py_None ); } volume_name = (uint8_t *) PyMem_Malloc( sizeof( uint8_t ) * volume_name_size ); if( volume_name == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create volume name.", function ); goto on_error; } Py_BEGIN_ALLOW_THREADS result = libfsntfs_mft_metadata_file_get_utf8_volume_name( pyfsntfs_mft_metadata_file->mft_metadata_file, volume_name, volume_name_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve volume name.", function ); libcerror_error_free( &error ); goto on_error; } /* Pass the string length to PyUnicode_DecodeUTF8 * otherwise it makes the end of string character is part * of the string */ string_object = PyUnicode_DecodeUTF8( (char *) volume_name, (Py_ssize_t) volume_name_size - 1, NULL ); PyMem_Free( volume_name ); return( string_object ); on_error: if( volume_name != NULL ) { PyMem_Free( volume_name ); } return( NULL ); } /* Retrieves the number of file entries * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_mft_metadata_file_get_number_of_file_entries( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_mft_metadata_file_get_number_of_file_entries"; uint64_t number_of_file_entries = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_mft_metadata_file == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid MFT metadata file.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_mft_metadata_file_get_number_of_file_entries( pyfsntfs_mft_metadata_file->mft_metadata_file, &number_of_file_entries, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve number of file entries.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( number_of_file_entries ); return( integer_object ); } /* Retrieves a specific file entry by index * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_mft_metadata_file_get_file_entry_by_index( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file, uint64_t file_entry_index ) { libcerror_error_t *error = NULL; libfsntfs_file_entry_t *file_entry = NULL; PyObject *file_entry_object = NULL; static char *function = "pyfsntfs_mft_metadata_file_get_file_entry_by_index"; int result = 0; if( pyfsntfs_mft_metadata_file == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid MFT metadata file.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_mft_metadata_file_get_file_entry_by_index( pyfsntfs_mft_metadata_file->mft_metadata_file, file_entry_index, &file_entry, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve file entry: %" PRIu64 ".", function, file_entry_index ); libcerror_error_free( &error ); goto on_error; } file_entry_object = pyfsntfs_file_entry_new( file_entry, (PyObject *) pyfsntfs_mft_metadata_file ); if( file_entry_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create file entry object.", function ); goto on_error; } return( file_entry_object ); on_error: if( file_entry != NULL ) { libfsntfs_file_entry_free( &file_entry, NULL ); } return( NULL ); } /* Retrieves a specific file entry * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_mft_metadata_file_get_file_entry( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file, PyObject *arguments, PyObject *keywords ) { PyObject *file_entry_object = NULL; static char *keyword_list[] = { "file_entry_index", NULL }; int file_entry_index = 0; if( PyArg_ParseTupleAndKeywords( arguments, keywords, "i", keyword_list, &file_entry_index ) == 0 ) { return( NULL ); } file_entry_object = pyfsntfs_mft_metadata_file_get_file_entry_by_index( pyfsntfs_mft_metadata_file, file_entry_index ); return( file_entry_object ); } /* Retrieves a file entries sequence and iterator object for the MFT metadata file entries * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_mft_metadata_file_get_file_entries( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *mft_metadata_file_entries_object = NULL; static char *function = "pyfsntfs_mft_metadata_file_get_file_entries"; uint64_t number_of_file_entries = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_mft_metadata_file == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid MFT metadata file.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_mft_metadata_file_get_number_of_file_entries( pyfsntfs_mft_metadata_file->mft_metadata_file, &number_of_file_entries, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve number of file entries.", function ); libcerror_error_free( &error ); return( NULL ); } mft_metadata_file_entries_object = pyfsntfs_mft_metadata_file_entries_new( pyfsntfs_mft_metadata_file, &pyfsntfs_mft_metadata_file_get_file_entry_by_index, number_of_file_entries ); if( mft_metadata_file_entries_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create MFT metadata file entries object.", function ); return( NULL ); } return( mft_metadata_file_entries_object ); } ================================================ FILE: pyfsntfs/pyfsntfs_mft_metadata_file.h ================================================ /* * Python object wrapper of libfsntfs_mft_metadata_file_t * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_MFT_METADATA_FILE_H ) #define _PYFSNTFS_MFT_METADATA_FILE_H #include #include #include "pyfsntfs_libbfio.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct pyfsntfs_mft_metadata_file pyfsntfs_mft_metadata_file_t; struct pyfsntfs_mft_metadata_file { /* Python object initialization */ PyObject_HEAD /* The libfsntfs MFT metadata file */ libfsntfs_mft_metadata_file_t *mft_metadata_file; /* The libbfio file IO handle */ libbfio_handle_t *file_io_handle; }; extern PyMethodDef pyfsntfs_mft_metadata_file_object_methods[]; extern PyTypeObject pyfsntfs_mft_metadata_file_type_object; int pyfsntfs_mft_metadata_file_init( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file ); void pyfsntfs_mft_metadata_file_free( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file ); PyObject *pyfsntfs_mft_metadata_file_open( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_mft_metadata_file_open_file_object( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_mft_metadata_file_close( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file, PyObject *arguments ); PyObject *pyfsntfs_mft_metadata_file_get_volume_name( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file, PyObject *arguments ); PyObject *pyfsntfs_mft_metadata_file_get_number_of_file_entries( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file, PyObject *arguments ); PyObject *pyfsntfs_mft_metadata_file_get_file_entry_by_index( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file, uint64_t file_entry_index ); PyObject *pyfsntfs_mft_metadata_file_get_file_entry( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_mft_metadata_file_get_file_entries( pyfsntfs_mft_metadata_file_t *pyfsntfs_mft_metadata_file, PyObject *arguments ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_MFT_METADATA_FILE_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_mft_metadata_file_entries.c ================================================ /* * Python object definition of the MFT metadata file entries sequence and iterator * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_file_entry.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_mft_metadata_file_entries.h" #include "pyfsntfs_python.h" PySequenceMethods pyfsntfs_mft_metadata_file_entries_sequence_methods = { /* sq_length */ (lenfunc) pyfsntfs_mft_metadata_file_entries_len, /* sq_concat */ 0, /* sq_repeat */ 0, /* sq_item */ (ssizeargfunc) pyfsntfs_mft_metadata_file_entries_getitem, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ 0, /* sq_contains */ 0, /* sq_inplace_concat */ 0, /* sq_inplace_repeat */ 0 }; PyTypeObject pyfsntfs_mft_metadata_file_entries_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs._mft_metadata_file_entries", /* tp_basicsize */ sizeof( pyfsntfs_mft_metadata_file_entries_t ), /* tp_itemsize */ 0, /* tp_dealloc */ (destructor) pyfsntfs_mft_metadata_file_entries_free, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ &pyfsntfs_mft_metadata_file_entries_sequence_methods, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /* tp_doc */ "internal pyfsntfs MFT metadata file entries sequence and iterator object", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ (getiterfunc) pyfsntfs_mft_metadata_file_entries_iter, /* tp_iternext */ (iternextfunc) pyfsntfs_mft_metadata_file_entries_iternext, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ (initproc) pyfsntfs_mft_metadata_file_entries_init, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Creates a new MFT metadata file entries object * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_mft_metadata_file_entries_new( pyfsntfs_mft_metadata_file_t *mft_metadata_file_object, PyObject* (*get_file_entry_by_index)( pyfsntfs_mft_metadata_file_t *mft_metadata_file_object, uint64_t file_entry_index ), uint64_t number_of_file_entries ) { pyfsntfs_mft_metadata_file_entries_t *pyfsntfs_mft_metadata_file_entries = NULL; static char *function = "pyfsntfs_mft_metadata_file_entries_new"; if( mft_metadata_file_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid MFT metadata file object.", function ); return( NULL ); } if( get_file_entry_by_index == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid get file entry by index function.", function ); return( NULL ); } /* Make sure the MFT metadata file entries values are initialized */ pyfsntfs_mft_metadata_file_entries = PyObject_New( struct pyfsntfs_mft_metadata_file_entries, &pyfsntfs_mft_metadata_file_entries_type_object ); if( pyfsntfs_mft_metadata_file_entries == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to initialize MFT metadata file entries.", function ); goto on_error; } if( pyfsntfs_mft_metadata_file_entries_init( pyfsntfs_mft_metadata_file_entries ) != 0 ) { PyErr_Format( PyExc_MemoryError, "%s: unable to initialize MFT metadata file entries.", function ); goto on_error; } pyfsntfs_mft_metadata_file_entries->mft_metadata_file_object = mft_metadata_file_object; pyfsntfs_mft_metadata_file_entries->get_file_entry_by_index = get_file_entry_by_index; pyfsntfs_mft_metadata_file_entries->number_of_file_entries = number_of_file_entries; Py_IncRef( (PyObject *) pyfsntfs_mft_metadata_file_entries->mft_metadata_file_object ); return( (PyObject *) pyfsntfs_mft_metadata_file_entries ); on_error: if( pyfsntfs_mft_metadata_file_entries != NULL ) { Py_DecRef( (PyObject *) pyfsntfs_mft_metadata_file_entries ); } return( NULL ); } /* Initializes a MFT metadata file entries object * Returns 0 if successful or -1 on error */ int pyfsntfs_mft_metadata_file_entries_init( pyfsntfs_mft_metadata_file_entries_t *pyfsntfs_mft_metadata_file_entries ) { static char *function = "pyfsntfs_mft_metadata_file_entries_init"; if( pyfsntfs_mft_metadata_file_entries == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid MFT metadata file entries.", function ); return( -1 ); } /* Make sure the MFT metadata file entries values are initialized */ pyfsntfs_mft_metadata_file_entries->mft_metadata_file_object = NULL; pyfsntfs_mft_metadata_file_entries->get_file_entry_by_index = NULL; pyfsntfs_mft_metadata_file_entries->file_entry_index = 0; pyfsntfs_mft_metadata_file_entries->number_of_file_entries = 0; return( 0 ); } /* Frees a MFT metadata file entries object */ void pyfsntfs_mft_metadata_file_entries_free( pyfsntfs_mft_metadata_file_entries_t *pyfsntfs_mft_metadata_file_entries ) { struct _typeobject *ob_type = NULL; static char *function = "pyfsntfs_mft_metadata_file_entries_free"; if( pyfsntfs_mft_metadata_file_entries == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid MFT metadata file entries.", function ); return; } ob_type = Py_TYPE( pyfsntfs_mft_metadata_file_entries ); if( ob_type == NULL ) { PyErr_Format( PyExc_ValueError, "%s: missing ob_type.", function ); return; } if( ob_type->tp_free == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid ob_type - missing tp_free.", function ); return; } if( pyfsntfs_mft_metadata_file_entries->mft_metadata_file_object != NULL ) { Py_DecRef( (PyObject *) pyfsntfs_mft_metadata_file_entries->mft_metadata_file_object ); } ob_type->tp_free( (PyObject*) pyfsntfs_mft_metadata_file_entries ); } /* The MFT metadata file entries len() function */ Py_ssize_t pyfsntfs_mft_metadata_file_entries_len( pyfsntfs_mft_metadata_file_entries_t *pyfsntfs_mft_metadata_file_entries ) { static char *function = "pyfsntfs_mft_metadata_file_entries_len"; if( pyfsntfs_mft_metadata_file_entries == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid MFT metadata file entries.", function ); return( -1 ); } return( (Py_ssize_t) pyfsntfs_mft_metadata_file_entries->number_of_file_entries ); } /* The MFT metadata file entries getitem() function */ PyObject *pyfsntfs_mft_metadata_file_entries_getitem( pyfsntfs_mft_metadata_file_entries_t *pyfsntfs_mft_metadata_file_entries, Py_ssize_t item_index ) { PyObject *file_entry_object = NULL; static char *function = "pyfsntfs_mft_metadata_file_entries_getitem"; if( pyfsntfs_mft_metadata_file_entries == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid MFT metadata file entries.", function ); return( NULL ); } if( pyfsntfs_mft_metadata_file_entries->get_file_entry_by_index == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid MFT metadata file entries - missing get file entry by index function.", function ); return( NULL ); } if( pyfsntfs_mft_metadata_file_entries->number_of_file_entries < 0 ) { PyErr_Format( PyExc_ValueError, "%s: invalid MFT metadata file entries - invalid number of file entries.", function ); return( NULL ); } if( ( item_index < 0 ) || ( item_index >= (Py_ssize_t) pyfsntfs_mft_metadata_file_entries->number_of_file_entries ) ) { PyErr_Format( PyExc_ValueError, "%s: invalid invalid item index value out of bounds.", function ); return( NULL ); } file_entry_object = pyfsntfs_mft_metadata_file_entries->get_file_entry_by_index( pyfsntfs_mft_metadata_file_entries->mft_metadata_file_object, (uint64_t) item_index ); return( file_entry_object ); } /* The MFT metadata file entries iter() function */ PyObject *pyfsntfs_mft_metadata_file_entries_iter( pyfsntfs_mft_metadata_file_entries_t *pyfsntfs_mft_metadata_file_entries ) { static char *function = "pyfsntfs_mft_metadata_file_entries_iter"; if( pyfsntfs_mft_metadata_file_entries == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid MFT metadata file entries.", function ); return( NULL ); } Py_IncRef( (PyObject *) pyfsntfs_mft_metadata_file_entries ); return( (PyObject *) pyfsntfs_mft_metadata_file_entries ); } /* The MFT metadata file entries iternext() function */ PyObject *pyfsntfs_mft_metadata_file_entries_iternext( pyfsntfs_mft_metadata_file_entries_t *pyfsntfs_mft_metadata_file_entries ) { PyObject *file_entry_object = NULL; static char *function = "pyfsntfs_mft_metadata_file_entries_iternext"; if( pyfsntfs_mft_metadata_file_entries == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid MFT metadata file entries.", function ); return( NULL ); } if( pyfsntfs_mft_metadata_file_entries->get_file_entry_by_index == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid MFT metadata file entries - missing get file entry by index function.", function ); return( NULL ); } if( pyfsntfs_mft_metadata_file_entries->file_entry_index < 0 ) { PyErr_Format( PyExc_ValueError, "%s: invalid MFT metadata file entries - invalid file entry index.", function ); return( NULL ); } if( pyfsntfs_mft_metadata_file_entries->number_of_file_entries < 0 ) { PyErr_Format( PyExc_ValueError, "%s: invalid MFT metadata file entries - invalid number of file entries.", function ); return( NULL ); } if( pyfsntfs_mft_metadata_file_entries->file_entry_index >= pyfsntfs_mft_metadata_file_entries->number_of_file_entries ) { PyErr_SetNone( PyExc_StopIteration ); return( NULL ); } file_entry_object = pyfsntfs_mft_metadata_file_entries->get_file_entry_by_index( pyfsntfs_mft_metadata_file_entries->mft_metadata_file_object, pyfsntfs_mft_metadata_file_entries->file_entry_index ); if( file_entry_object != NULL ) { pyfsntfs_mft_metadata_file_entries->file_entry_index++; } return( file_entry_object ); } ================================================ FILE: pyfsntfs/pyfsntfs_mft_metadata_file_entries.h ================================================ /* * Python object definition of the MFT metadata file entries sequence and iterator * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_MFT_METADATA_FILE_ENTRIES_H ) #define _PYFSNTFS_MFT_METADATA_FILE_ENTRIES_H #include #include #include "pyfsntfs_file_entry.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_mft_metadata_file.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct pyfsntfs_mft_metadata_file_entries pyfsntfs_mft_metadata_file_entries_t; struct pyfsntfs_mft_metadata_file_entries { /* Python object initialization */ PyObject_HEAD /* The MFT metadata file object */ pyfsntfs_mft_metadata_file_t *mft_metadata_file_object; /* The get file entry by index callback function */ PyObject* (*get_file_entry_by_index)( pyfsntfs_mft_metadata_file_t *mft_metadata_file_object, uint64_t file_entry_index ); /* The (current) file entry index */ uint64_t file_entry_index; /* The number of file entries */ uint64_t number_of_file_entries; }; extern PyTypeObject pyfsntfs_mft_metadata_file_entries_type_object; PyObject *pyfsntfs_mft_metadata_file_entries_new( pyfsntfs_mft_metadata_file_t *mft_metadata_file, PyObject* (*get_file_entry_by_index)( pyfsntfs_mft_metadata_file_t *mft_metadata_file_object, uint64_t file_entry_index ), uint64_t number_of_file_entries ); int pyfsntfs_mft_metadata_file_entries_init( pyfsntfs_mft_metadata_file_entries_t *pyfsntfs_mft_metadata_file_entries ); void pyfsntfs_mft_metadata_file_entries_free( pyfsntfs_mft_metadata_file_entries_t *pyfsntfs_mft_metadata_file_entries ); Py_ssize_t pyfsntfs_mft_metadata_file_entries_len( pyfsntfs_mft_metadata_file_entries_t *pyfsntfs_mft_metadata_file_entries ); PyObject *pyfsntfs_mft_metadata_file_entries_getitem( pyfsntfs_mft_metadata_file_entries_t *pyfsntfs_mft_metadata_file_entries, Py_ssize_t item_index ); PyObject *pyfsntfs_mft_metadata_file_entries_iter( pyfsntfs_mft_metadata_file_entries_t *pyfsntfs_mft_metadata_file_entries ); PyObject *pyfsntfs_mft_metadata_file_entries_iternext( pyfsntfs_mft_metadata_file_entries_t *pyfsntfs_mft_metadata_file_entries ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_MFT_METADATA_FILE_ENTRIES_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_object_identifier_attribute.c ================================================ /* * Python object definition of the libfsntfs object identifier attribute * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_attribute.h" #include "pyfsntfs_error.h" #include "pyfsntfs_guid.h" #include "pyfsntfs_integer.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #include "pyfsntfs_unused.h" #include "pyfsntfs_object_identifier_attribute.h" PyMethodDef pyfsntfs_object_identifier_attribute_object_methods[] = { /* Functions to access the attribute values */ { "get_droid_file_identifier", (PyCFunction) pyfsntfs_object_identifier_attribute_get_droid_file_identifier, METH_NOARGS, "get_droid_file_identifier() -> Unicode string or None\n" "\n" "Returns the droid file identifier (GUID)." }, { "get_birth_droid_volume_identifier", (PyCFunction) pyfsntfs_object_identifier_attribute_get_birth_droid_volume_identifier, METH_NOARGS, "get_birth_droid_volume_identifier() -> Unicode string or None\n" "\n" "Returns the birth droid volume identifier (GUID)." }, { "get_birth_droid_file_identifier", (PyCFunction) pyfsntfs_object_identifier_attribute_get_birth_droid_file_identifier, METH_NOARGS, "get_birth_droid_file_identifier() -> Unicode string or None\n" "\n" "Returns the birth droid file identifier (GUID)." }, { "get_birth_droid_domain_identifier", (PyCFunction) pyfsntfs_object_identifier_attribute_get_birth_droid_domain_identifier, METH_NOARGS, "get_birth_droid_domain_identifier() -> Unicode string or None\n" "\n" "Returns the birth droid domain identifier (GUID)." }, /* Sentinel */ { NULL, NULL, 0, NULL } }; PyGetSetDef pyfsntfs_object_identifier_attribute_object_get_set_definitions[] = { { "droid_file_identifier", (getter) pyfsntfs_object_identifier_attribute_get_droid_file_identifier, (setter) 0, "The droid file identifier.", NULL }, { "birth_droid_volume_identifier", (getter) pyfsntfs_object_identifier_attribute_get_birth_droid_volume_identifier, (setter) 0, "The birth droid volume identifier.", NULL }, { "birth_droid_file_identifier", (getter) pyfsntfs_object_identifier_attribute_get_birth_droid_file_identifier, (setter) 0, "The birth droid file identifier.", NULL }, { "birth_droid_domain_identifier", (getter) pyfsntfs_object_identifier_attribute_get_birth_droid_domain_identifier, (setter) 0, "The birth droid domain identifier.", NULL }, /* Sentinel */ { NULL, NULL, NULL, NULL, NULL } }; PyTypeObject pyfsntfs_object_identifier_attribute_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs.object_identifier_attribute", /* tp_basicsize */ sizeof( pyfsntfs_attribute_t ), /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_doc */ "pyfsntfs object identifier attribute object (wraps libfsntfs_attribute_t type LIBFSNTFS_ATTRIBUTE_TYPE_OBJECT_IDENTIFIER)", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ pyfsntfs_object_identifier_attribute_object_methods, /* tp_members */ 0, /* tp_getset */ pyfsntfs_object_identifier_attribute_object_get_set_definitions, /* tp_base */ &pyfsntfs_attribute_type_object, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Retrieves the droid file identifier * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_object_identifier_attribute_get_droid_file_identifier( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { uint8_t guid_data[ 16 ]; libcerror_error_t *error = NULL; PyObject *string_object = NULL; static char *function = "pyfsntfs_object_identifier_attribute_get_droid_file_identifier"; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_object_identifier_attribute_get_droid_file_identifier( pyfsntfs_attribute->attribute, guid_data, 16, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve droid file identifier.", function ); libcerror_error_free( &error ); return( NULL ); } string_object = pyfsntfs_string_new_from_guid( guid_data, 16 ); return( string_object ); } /* Retrieves the birth droid volume identifier * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_object_identifier_attribute_get_birth_droid_volume_identifier( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { uint8_t guid_data[ 16 ]; libcerror_error_t *error = NULL; PyObject *string_object = NULL; static char *function = "pyfsntfs_object_identifier_attribute_get_birth_droid_volume_identifier"; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_object_identifier_attribute_get_birth_droid_volume_identifier( pyfsntfs_attribute->attribute, guid_data, 16, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve birth droid volume identifier.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } string_object = pyfsntfs_string_new_from_guid( guid_data, 16 ); return( string_object ); } /* Retrieves the birth droid file identifier * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_object_identifier_attribute_get_birth_droid_file_identifier( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { uint8_t guid_data[ 16 ]; libcerror_error_t *error = NULL; PyObject *string_object = NULL; static char *function = "pyfsntfs_object_identifier_attribute_get_birth_droid_file_identifier"; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_object_identifier_attribute_get_birth_droid_file_identifier( pyfsntfs_attribute->attribute, guid_data, 16, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve birth droid file identifier.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } string_object = pyfsntfs_string_new_from_guid( guid_data, 16 ); return( string_object ); } /* Retrieves the birth droid domain identifier * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_object_identifier_attribute_get_birth_droid_domain_identifier( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { uint8_t guid_data[ 16 ]; libcerror_error_t *error = NULL; PyObject *string_object = NULL; static char *function = "pyfsntfs_object_identifier_attribute_get_birth_droid_domain_identifier"; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_object_identifier_attribute_get_birth_droid_domain_identifier( pyfsntfs_attribute->attribute, guid_data, 16, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve birth droid domain identifier.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } string_object = pyfsntfs_string_new_from_guid( guid_data, 16 ); return( string_object ); } ================================================ FILE: pyfsntfs/pyfsntfs_object_identifier_attribute.h ================================================ /* * Python object definition of the libfsntfs object identifier attribute * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_OBJECT_IDENTIFIER_ATTRIBUTE_H ) #define _PYFSNTFS_OBJECT_IDENTIFIER_ATTRIBUTE_H #include #include #include "pyfsntfs_attribute.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif extern PyMethodDef pyfsntfs_object_identifier_attribute_object_methods[]; extern PyTypeObject pyfsntfs_object_identifier_attribute_type_object; PyObject *pyfsntfs_object_identifier_attribute_get_droid_file_identifier( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_object_identifier_attribute_get_birth_droid_volume_identifier( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_object_identifier_attribute_get_birth_droid_file_identifier( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_object_identifier_attribute_get_birth_droid_domain_identifier( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_OBJECT_IDENTIFIER_ATTRIBUTE_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_python.h ================================================ /* * The python header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_PYTHON_H ) #define _PYFSNTFS_PYTHON_H #include #if PY_MAJOR_VERSION < 3 /* Fix defines in pyconfig.h */ #undef _POSIX_C_SOURCE #undef _XOPEN_SOURCE /* Fix defines in pyport.h */ #undef HAVE_FSTAT #undef HAVE_STAT #undef HAVE_SSIZE_T #undef HAVE_INT32_T #undef HAVE_UINT32_T #undef HAVE_INT64_T #undef HAVE_UINT64_T #endif /* PY_MAJOR_VERSION < 3 */ /* Define PY_SSIZE_T_CLEAN to silence: * DeprecationWarning: PY_SSIZE_T_CLEAN will be required for '#' formats * * PY_SSIZE_T_CLEAN was introduced in Python 2.5 */ #define PY_SSIZE_T_CLEAN #include /* Python compatibility macros */ #if !defined( PyMODINIT_FUNC ) #if PY_MAJOR_VERSION >= 3 #define PyMODINIT_FUNC PyObject * #else #define PyMODINIT_FUNC void #endif #endif /* !defined( PyMODINIT_FUNC ) */ #if !defined( PyVarObject_HEAD_INIT ) #define PyVarObject_HEAD_INIT( type, size ) \ PyObject_HEAD_INIT( type ) \ size, #endif /* !defined( PyVarObject_HEAD_INIT ) */ #if PY_MAJOR_VERSION >= 3 #define Py_TPFLAGS_HAVE_ITER 0 #endif #if !defined( Py_TYPE ) #define Py_TYPE( object ) \ ( ( (PyObject *) object )->ob_type ) #endif /* !defined( Py_TYPE ) */ #endif /* !defined( _PYFSNTFS_PYTHON_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_reparse_point_attribute.c ================================================ /* * Python object definition of the libfsntfs reparse point attribute * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_attribute.h" #include "pyfsntfs_datetime.h" #include "pyfsntfs_error.h" #include "pyfsntfs_integer.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #include "pyfsntfs_reparse_point_attribute.h" #include "pyfsntfs_unused.h" PyMethodDef pyfsntfs_reparse_point_attribute_object_methods[] = { /* Functions to access the attribute values */ { "get_tag", (PyCFunction) pyfsntfs_reparse_point_attribute_get_tag, METH_NOARGS, "get_tag() -> Integer\n" "\n" "Returns the tag." }, { "get_substitute_name", (PyCFunction) pyfsntfs_reparse_point_attribute_get_substitute_name, METH_NOARGS, "get_substitute_name() -> Unicode string or None\n" "\n" "Returns the substitute name." }, { "get_print_name", (PyCFunction) pyfsntfs_reparse_point_attribute_get_print_name, METH_NOARGS, "get_print_name() -> Unicode string or None\n" "\n" "Returns the print name." }, /* Sentinel */ { NULL, NULL, 0, NULL } }; PyGetSetDef pyfsntfs_reparse_point_attribute_object_get_set_definitions[] = { { "tag", (getter) pyfsntfs_reparse_point_attribute_get_tag, (setter) 0, "The type and flags.", NULL }, { "substitute_name", (getter) pyfsntfs_reparse_point_attribute_get_substitute_name, (setter) 0, "The substitute name.", NULL }, { "print_name", (getter) pyfsntfs_reparse_point_attribute_get_print_name, (setter) 0, "The print name.", NULL }, /* Sentinel */ { NULL, NULL, NULL, NULL, NULL } }; PyTypeObject pyfsntfs_reparse_point_attribute_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs.reparse_point_attribute", /* tp_basicsize */ sizeof( pyfsntfs_attribute_t ), /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_doc */ "pyfsntfs reparse point attribute object (wraps libfsntfs_attribute_t type LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT)", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ pyfsntfs_reparse_point_attribute_object_methods, /* tp_members */ 0, /* tp_getset */ pyfsntfs_reparse_point_attribute_object_get_set_definitions, /* tp_base */ &pyfsntfs_attribute_type_object, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Retrieves the type and flags * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_reparse_point_attribute_get_tag( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_reparse_point_attribute_get_tag"; uint32_t tag = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_reparse_point_attribute_get_tag( pyfsntfs_attribute->attribute, &tag, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve type and flags.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( (uint64_t) tag ); return( integer_object ); } /* Retrieves the substitute name * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_reparse_point_attribute_get_substitute_name( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *string_object = NULL; uint8_t *name = NULL; static char *function = "pyfsntfs_reparse_point_attribute_get_substitute_name"; size_t name_size = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_reparse_point_attribute_get_utf8_substitute_name_size( pyfsntfs_attribute->attribute, &name_size, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve substitute name size.", function ); libcerror_error_free( &error ); goto on_error; } else if( ( result == 0 ) || ( name_size == 0 ) ) { Py_IncRef( Py_None ); return( Py_None ); } name = (uint8_t *) PyMem_Malloc( sizeof( uint8_t ) * name_size ); if( name == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create substitute name.", function ); goto on_error; } Py_BEGIN_ALLOW_THREADS result = libfsntfs_reparse_point_attribute_get_utf8_substitute_name( pyfsntfs_attribute->attribute, name, name_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve substitute name.", function ); libcerror_error_free( &error ); goto on_error; } /* Pass the string length to PyUnicode_DecodeUTF8 * otherwise it makes the end of string character is part * of the string */ string_object = PyUnicode_DecodeUTF8( (char *) name, (Py_ssize_t) name_size - 1, NULL ); PyMem_Free( name ); return( string_object ); on_error: if( name != NULL ) { PyMem_Free( name ); } return( NULL ); } /* Retrieves the print name * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_reparse_point_attribute_get_print_name( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *string_object = NULL; uint8_t *name = NULL; static char *function = "pyfsntfs_reparse_point_attribute_get_print_name"; size_t name_size = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_reparse_point_attribute_get_utf8_print_name_size( pyfsntfs_attribute->attribute, &name_size, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve print name size.", function ); libcerror_error_free( &error ); goto on_error; } else if( ( result == 0 ) || ( name_size == 0 ) ) { Py_IncRef( Py_None ); return( Py_None ); } name = (uint8_t *) PyMem_Malloc( sizeof( uint8_t ) * name_size ); if( name == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create print name.", function ); goto on_error; } Py_BEGIN_ALLOW_THREADS result = libfsntfs_reparse_point_attribute_get_utf8_print_name( pyfsntfs_attribute->attribute, name, name_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve print name.", function ); libcerror_error_free( &error ); goto on_error; } /* Pass the string length to PyUnicode_DecodeUTF8 * otherwise it makes the end of string character is part * of the string */ string_object = PyUnicode_DecodeUTF8( (char *) name, (Py_ssize_t) name_size - 1, NULL ); PyMem_Free( name ); return( string_object ); on_error: if( name != NULL ) { PyMem_Free( name ); } return( NULL ); } ================================================ FILE: pyfsntfs/pyfsntfs_reparse_point_attribute.h ================================================ /* * Python object definition of the libfsntfs reparse point attribute * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_REPARSE_POINT_ATTRIBUTE_H ) #define _PYFSNTFS_REPARSE_POINT_ATTRIBUTE_H #include #include #include "pyfsntfs_attribute.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif extern PyMethodDef pyfsntfs_reparse_point_attribute_object_methods[]; extern PyTypeObject pyfsntfs_reparse_point_attribute_type_object; PyObject *pyfsntfs_reparse_point_attribute_get_tag( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_reparse_point_attribute_get_substitute_name( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_reparse_point_attribute_get_print_name( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_REPARSE_POINT_ATTRIBUTE_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_security_descriptor_attribute.c ================================================ /* * Python object definition of the libfsntfs security descriptor attribute * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_attribute.h" #include "pyfsntfs_error.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #include "pyfsntfs_security_descriptor_attribute.h" #include "pyfsntfs_unused.h" PyMethodDef pyfsntfs_security_descriptor_attribute_object_methods[] = { /* Functions to access the attribute values */ { "get_data", (PyCFunction) pyfsntfs_security_descriptor_attribute_get_data, METH_NOARGS, "get_data() -> String\n" "\n" "Returns the security descriptor data." }, /* Sentinel */ { NULL, NULL, 0, NULL } }; PyGetSetDef pyfsntfs_security_descriptor_attribute_object_get_set_definitions[] = { { "data", (getter) pyfsntfs_security_descriptor_attribute_get_data, (setter) 0, "The security descriptor data.", NULL }, /* Sentinel */ { NULL, NULL, NULL, NULL, NULL } }; PyTypeObject pyfsntfs_security_descriptor_attribute_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs.security_descriptor_attribute", /* tp_basicsize */ sizeof( pyfsntfs_attribute_t ), /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_doc */ "pyfsntfs security descriptor attribute object (wraps libfsntfs_attribute_t type LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION)", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ pyfsntfs_security_descriptor_attribute_object_methods, /* tp_members */ 0, /* tp_getset */ pyfsntfs_security_descriptor_attribute_object_get_set_definitions, /* tp_base */ &pyfsntfs_attribute_type_object, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Retrieves the security descriptor data * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_security_descriptor_attribute_get_data( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *string_object = NULL; static char *function = "pyfsntfs_security_descriptor_attribute_get_data"; char *security_desciptor_data = NULL; size_t security_desciptor_data_size = 0; int result = 0; if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_security_descriptor_attribute_get_security_descriptor_size( pyfsntfs_attribute->attribute, &security_desciptor_data_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to determine security descriptor data size.", function ); libcerror_error_free( &error ); return( NULL ); } #if PY_MAJOR_VERSION >= 3 string_object = PyBytes_FromStringAndSize( NULL, security_desciptor_data_size ); security_desciptor_data = PyBytes_AsString( string_object ); #else /* Note that a size of 0 is not supported */ string_object = PyString_FromStringAndSize( NULL, security_desciptor_data_size ); security_desciptor_data = PyString_AsString( string_object ); #endif Py_BEGIN_ALLOW_THREADS result = libfsntfs_security_descriptor_attribute_get_security_descriptor( pyfsntfs_attribute->attribute, (uint8_t *) security_desciptor_data, security_desciptor_data_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve security descriptor data.", function ); libcerror_error_free( &error ); Py_DecRef( (PyObject *) string_object ); return( NULL ); } return( string_object ); } ================================================ FILE: pyfsntfs/pyfsntfs_security_descriptor_attribute.h ================================================ /* * Python object definition of the libfsntfs security descriptor attribute * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_SECURITY_DESCRIPTOR_ATTRIBUTE_H ) #define _PYFSNTFS_SECURITY_DESCRIPTOR_ATTRIBUTE_H #include #include #include "pyfsntfs_attribute.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif extern PyMethodDef pyfsntfs_security_descriptor_attribute_object_methods[]; extern PyTypeObject pyfsntfs_security_descriptor_attribute_type_object; PyObject *pyfsntfs_security_descriptor_attribute_get_data( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_SECURITY_DESCRIPTOR_ATTRIBUTE_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_standard_information_attribute.c ================================================ /* * Python object definition of the libfsntfs standard information attribute * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_attribute.h" #include "pyfsntfs_datetime.h" #include "pyfsntfs_error.h" #include "pyfsntfs_integer.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #include "pyfsntfs_standard_information_attribute.h" #include "pyfsntfs_unused.h" PyMethodDef pyfsntfs_standard_information_attribute_object_methods[] = { /* Functions to access the attribute values */ { "get_creation_time", (PyCFunction) pyfsntfs_standard_information_attribute_get_creation_time, METH_NOARGS, "get_creation_time() -> Datetime or None\n" "\n" "Returns the creation date and time." }, { "get_creation_time_as_integer", (PyCFunction) pyfsntfs_standard_information_attribute_get_creation_time_as_integer, METH_NOARGS, "get_creation_time_as_integer() -> Integer or None\n" "\n" "Returns the creation date and time as a 64-bit integer containing a FILETIME value." }, { "get_modification_time", (PyCFunction) pyfsntfs_standard_information_attribute_get_modification_time, METH_NOARGS, "get_modification_time() -> Datetime or None\n" "\n" "Returns the modification date and time." }, { "get_modification_time_as_integer", (PyCFunction) pyfsntfs_standard_information_attribute_get_modification_time_as_integer, METH_NOARGS, "get_modification_time_as_integer() -> Integer or None\n" "\n" "Returns the modification date and time as a 64-bit integer containing a FILETIME value." }, { "get_access_time", (PyCFunction) pyfsntfs_standard_information_attribute_get_access_time, METH_NOARGS, "get_access_time() -> Datetime or None\n" "\n" "Returns the access date and time." }, { "get_access_time_as_integer", (PyCFunction) pyfsntfs_standard_information_attribute_get_access_time_as_integer, METH_NOARGS, "get_access_time_as_integer() -> Integer or None\n" "\n" "Returns the access date and time as a 64-bit integer containing a FILETIME value." }, { "get_entry_modification_time", (PyCFunction) pyfsntfs_standard_information_attribute_get_entry_modification_time, METH_NOARGS, "get_entry_modification_time() -> Datetime or None\n" "\n" "Returns the entry modification date and time." }, { "get_entry_modification_time_as_integer", (PyCFunction) pyfsntfs_standard_information_attribute_get_entry_modification_time_as_integer, METH_NOARGS, "get_entry_modification_time_as_integer() -> Integer or None\n" "\n" "Returns the entry modification date and time as a 64-bit integer containing a FILETIME value." }, { "get_file_attribute_flags", (PyCFunction) pyfsntfs_standard_information_attribute_get_file_attribute_flags, METH_NOARGS, "get_file_attribute_flags() -> Integer\n" "\n" "Returns the file attribute flags." }, { "get_owner_identifier", (PyCFunction) pyfsntfs_standard_information_attribute_get_owner_identifier, METH_NOARGS, "get_owner_identifier() -> Integer or None\n" "\n" "Returns the owner identifier." }, { "get_security_descriptor_identifier", (PyCFunction) pyfsntfs_standard_information_attribute_get_security_descriptor_identifier, METH_NOARGS, "get_security_descriptor_identifier() -> Integer or None\n" "\n" "Returns the security descriptor identifier." }, { "get_update_sequence_number", (PyCFunction) pyfsntfs_standard_information_attribute_get_update_sequence_number, METH_NOARGS, "get_update_sequence_number() -> Integer or None\n" "\n" "Returns the update sequence number." }, /* Sentinel */ { NULL, NULL, 0, NULL } }; PyGetSetDef pyfsntfs_standard_information_attribute_object_get_set_definitions[] = { { "creation_time", (getter) pyfsntfs_standard_information_attribute_get_creation_time, (setter) 0, "The creation date and time.", NULL }, { "modification_time", (getter) pyfsntfs_standard_information_attribute_get_modification_time, (setter) 0, "The modification date and time.", NULL }, { "access_time", (getter) pyfsntfs_standard_information_attribute_get_access_time, (setter) 0, "The access date and time.", NULL }, { "entry_modification_time", (getter) pyfsntfs_standard_information_attribute_get_entry_modification_time, (setter) 0, "The entry modification date and time.", NULL }, { "file_attribute_flags", (getter) pyfsntfs_standard_information_attribute_get_file_attribute_flags, (setter) 0, "The file attribute flags.", NULL }, { "owner_identifier", (getter) pyfsntfs_standard_information_attribute_get_owner_identifier, (setter) 0, "The owner identifier.", NULL }, { "security_descriptor_identifier", (getter) pyfsntfs_standard_information_attribute_get_security_descriptor_identifier, (setter) 0, "The security descriptor identifier.", NULL }, { "update_sequence_number", (getter) pyfsntfs_standard_information_attribute_get_update_sequence_number, (setter) 0, "The update sequence number.", NULL }, /* Sentinel */ { NULL, NULL, NULL, NULL, NULL } }; PyTypeObject pyfsntfs_standard_information_attribute_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs.standard_information_attribute", /* tp_basicsize */ sizeof( pyfsntfs_attribute_t ), /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_doc */ "pyfsntfs standard information attribute object (wraps libfsntfs_attribute_t type LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION)", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ pyfsntfs_standard_information_attribute_object_methods, /* tp_members */ 0, /* tp_getset */ pyfsntfs_standard_information_attribute_object_get_set_definitions, /* tp_base */ &pyfsntfs_attribute_type_object, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Retrieves the creation date and time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_standard_information_attribute_get_creation_time( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *date_time_object = NULL; static char *function = "pyfsntfs_standard_information_attribute_get_creation_time"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_standard_information_attribute_get_creation_time( pyfsntfs_attribute->attribute, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve creation time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } date_time_object = pyfsntfs_datetime_new_from_filetime( filetime ); return( date_time_object ); } /* Retrieves the creation date and time as an integer * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_standard_information_attribute_get_creation_time_as_integer( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_standard_information_attribute_get_creation_time_as_integer"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_standard_information_attribute_get_creation_time( pyfsntfs_attribute->attribute, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve creation time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( filetime ); return( integer_object ); } /* Retrieves the modification date and time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_standard_information_attribute_get_modification_time( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *date_time_object = NULL; static char *function = "pyfsntfs_standard_information_attribute_get_modification_time"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_standard_information_attribute_get_modification_time( pyfsntfs_attribute->attribute, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve modification time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } date_time_object = pyfsntfs_datetime_new_from_filetime( filetime ); return( date_time_object ); } /* Retrieves the modification date and time as an integer * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_standard_information_attribute_get_modification_time_as_integer( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_standard_information_attribute_get_modification_time_as_integer"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_standard_information_attribute_get_modification_time( pyfsntfs_attribute->attribute, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve modification time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( filetime ); return( integer_object ); } /* Retrieves the access date and time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_standard_information_attribute_get_access_time( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *date_time_object = NULL; static char *function = "pyfsntfs_standard_information_attribute_get_access_time"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_standard_information_attribute_get_access_time( pyfsntfs_attribute->attribute, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve access time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } date_time_object = pyfsntfs_datetime_new_from_filetime( filetime ); return( date_time_object ); } /* Retrieves the access date and time as an integer * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_standard_information_attribute_get_access_time_as_integer( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_standard_information_attribute_get_access_time_as_integer"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_standard_information_attribute_get_access_time( pyfsntfs_attribute->attribute, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve access time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( filetime ); return( integer_object ); } /* Retrieves the entry modification date and time * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_standard_information_attribute_get_entry_modification_time( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *date_time_object = NULL; static char *function = "pyfsntfs_standard_information_attribute_get_entry_modification_time"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_standard_information_attribute_get_entry_modification_time( pyfsntfs_attribute->attribute, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve entry modification time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } date_time_object = pyfsntfs_datetime_new_from_filetime( filetime ); return( date_time_object ); } /* Retrieves the entry modification date and time as an integer * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_standard_information_attribute_get_entry_modification_time_as_integer( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_standard_information_attribute_get_entry_modification_time_as_integer"; uint64_t filetime = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_standard_information_attribute_get_entry_modification_time( pyfsntfs_attribute->attribute, &filetime, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve entry modification time.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_signed_new_from_64bit( filetime ); return( integer_object ); } /* Retrieves the file attribute flags * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_standard_information_attribute_get_file_attribute_flags( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_standard_information_attribute_get_file_attribute_flags"; uint32_t file_attribute_flags = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_standard_information_attribute_get_file_attribute_flags( pyfsntfs_attribute->attribute, &file_attribute_flags, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve file attribute flags.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( (uint64_t) file_attribute_flags ); return( integer_object ); } /* Retrieves the owner identifier * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_standard_information_attribute_get_owner_identifier( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_standard_information_attribute_get_owner_identifier"; uint32_t owner_identifier = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_standard_information_attribute_get_owner_identifier( pyfsntfs_attribute->attribute, &owner_identifier, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve owner identifier.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( (uint64_t) owner_identifier ); return( integer_object ); } /* Retrieves the security identifier * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_standard_information_attribute_get_security_descriptor_identifier( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_standard_information_attribute_get_security_descriptor_identifier"; uint32_t security_descriptor_identifier = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_standard_information_attribute_get_security_descriptor_identifier( pyfsntfs_attribute->attribute, &security_descriptor_identifier, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve security descriptor identifier.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( (uint64_t) security_descriptor_identifier ); return( integer_object ); } /* Retrieves the update sequence number * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_standard_information_attribute_get_update_sequence_number( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_standard_information_attribute_get_update_sequence_number"; uint64_t update_sequence_number = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_standard_information_attribute_get_update_sequence_number( pyfsntfs_attribute->attribute, &update_sequence_number, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve update sequence number.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( update_sequence_number ); return( integer_object ); } ================================================ FILE: pyfsntfs/pyfsntfs_standard_information_attribute.h ================================================ /* * Python object definition of the libfsntfs standard information attribute * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_STANDARD_INFORMATION_ATTRIBUTE_H ) #define _PYFSNTFS_STANDARD_INFORMATION_ATTRIBUTE_H #include #include #include "pyfsntfs_attribute.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif extern PyMethodDef pyfsntfs_standard_information_attribute_object_methods[]; extern PyTypeObject pyfsntfs_standard_information_attribute_type_object; PyObject *pyfsntfs_standard_information_attribute_get_creation_time( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_standard_information_attribute_get_creation_time_as_integer( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_standard_information_attribute_get_modification_time( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_standard_information_attribute_get_modification_time_as_integer( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_standard_information_attribute_get_access_time( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_standard_information_attribute_get_access_time_as_integer( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_standard_information_attribute_get_entry_modification_time( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_standard_information_attribute_get_entry_modification_time_as_integer( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_standard_information_attribute_get_file_attribute_flags( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_standard_information_attribute_get_owner_identifier( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_standard_information_attribute_get_security_descriptor_identifier( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_standard_information_attribute_get_update_sequence_number( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_STANDARD_INFORMATION_ATTRIBUTE_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_string.c ================================================ /* * String functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "pyfsntfs_error.h" #include "pyfsntfs_libuna.h" #include "pyfsntfs_python.h" #include "pyfsntfs_string.h" #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 /* Creates a new string object from an UTF-8 RFC 2279 encoded string * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_string_new_from_utf8_rfc2279( const uint8_t *utf8_string, size_t utf8_string_size ) { PyObject *string_object = NULL; libcerror_error_t *error = NULL; uint32_t *utf32_string = NULL; static char *function = "pyfsntfs_string_new_from_utf8_rfc2279"; libuna_unicode_character_t largest_unicode_character = 127; libuna_unicode_character_t unicode_character = 0; size_t utf32_string_index = 0; size_t utf32_string_length = 0; size_t utf8_string_index = 0; if( utf8_string == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid UTF-8 string.", function ); return( NULL ); } if( ( utf8_string_size == 0 ) || ( utf8_string_size > (size_t) ( SSIZE_MAX / 4 ) ) ) { PyErr_Format( PyExc_ValueError, "%s: invalid UTF-8 string size value out of bounds.", function ); return( NULL ); } utf32_string = (uint32_t *) PyMem_Malloc( sizeof( uint32_t ) * utf8_string_size ); if( utf32_string == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create UTF-32 string.", function ); goto on_error; } /* Using RFC 2279 UTF-8 to support unpaired UTF-16 surrogates */ while( utf8_string_index < utf8_string_size ) { if( libuna_unicode_character_copy_from_utf8_rfc2279( &unicode_character, (libuna_utf8_character_t *) utf8_string, utf8_string_size, &utf8_string_index, &error ) != 1 ) { pyfsntfs_error_raise( error, PyExc_RuntimeError, "%s: unable to copy Unicode character from string.", function ); libcerror_error_free( &error ); goto on_error; } if( unicode_character == 0 ) { break; } utf32_string[ utf32_string_index++ ] = unicode_character; if( ( unicode_character >= 0x0000d800UL ) && ( unicode_character <= 0x0000dfffUL ) ) { largest_unicode_character = 0x0010ffffUL; } else if( unicode_character > largest_unicode_character ) { largest_unicode_character = unicode_character; } } utf32_string_length = utf32_string_index; if( largest_unicode_character > 65535 ) { largest_unicode_character = 0x0010ffffUL; } else if( largest_unicode_character > 255 ) { largest_unicode_character = 0x0000ffffUL; } else if( largest_unicode_character > 127 ) { largest_unicode_character = 0x000000ffUL; } /* Pass the string length to PyUnicode_New otherwise it the end of string * character is part of the string. The largest Unicode character is needed * to ensure Python Unicode strings are "canonical", otherwise string * comparison can fail. */ string_object = PyUnicode_New( utf32_string_length, largest_unicode_character); if( string_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create string object.", function ); goto on_error; } for( utf32_string_index = 0; utf32_string_index < utf32_string_length; utf32_string_index++ ) { unicode_character = utf32_string[ utf32_string_index ]; if( PyUnicode_WriteChar( string_object, (Py_ssize_t) utf32_string_index, (Py_UCS4) unicode_character ) == -1 ) { PyErr_Format( PyExc_RuntimeError, "%s: unable to copy Unicode character: 0x%08" PRIx32 " at index: %" PRIzd " to string object.", function, unicode_character, utf32_string_index ); goto on_error; } } PyMem_Free( utf32_string ); return( string_object ); on_error: if( string_object != NULL ) { Py_DecRef( (PyObject *) string_object ); } if( utf32_string != NULL ) { PyMem_Free( utf32_string ); } return( NULL ); } /* Copies a Python Unicode string object to an UTF-8 RFC 2279 encoded string * Returns 1 if successful or -1 on error */ int pyfsntfs_string_copy_to_utf8_rfc2279( PyObject *string_object, uint8_t **utf8_string, size_t *utf8_string_size, libcerror_error_t **error ) { uint8_t *safe_utf8_string = NULL; static char *function = "pyfsntfs_string_copy_to_utf8_rfc2279"; Py_UCS4 unicode_character = 0; Py_ssize_t string_index = 0; Py_ssize_t string_length = 0; size_t safe_utf8_string_size = 0; size_t utf8_character_size = 0; size_t utf8_string_index = 0; if( string_object == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid string object.", function ); return( -1 ); } if( utf8_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-8 string.", function ); return( -1 ); } if( utf8_string_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid UTF-8 string size.", function ); return( -1 ); } PyErr_Clear(); string_length = PyUnicode_GetLength( string_object ); if( ( string_length == 0 ) || ( (size_t) string_length > (size_t) ( SSIZE_MAX - 1 ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid string length value out of bounds.", function ); goto on_error; } safe_utf8_string_size = 1; /* Using RFC 2279 UTF-8 to support unpaired UTF-16 surrogates */ for( string_index = 0; string_index < string_length; string_index++ ) { unicode_character = PyUnicode_ReadChar( string_object, string_index ); if( libuna_unicode_character_size_to_utf8_rfc2279( (libuna_unicode_character_t) unicode_character, &utf8_character_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine size of Unicode character as UTF-8 string.", function ); goto on_error; } safe_utf8_string_size += utf8_character_size; } safe_utf8_string = (uint8_t *) PyMem_Malloc( sizeof( uint8_t ) * safe_utf8_string_size ); if( safe_utf8_string == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create UTF-8 string.", function ); goto on_error; } for( string_index = 0; string_index < string_length; string_index++ ) { unicode_character = PyUnicode_ReadChar( string_object, string_index ); if( libuna_unicode_character_copy_to_utf8_rfc2279( (libuna_unicode_character_t) unicode_character, (libuna_utf8_character_t *) safe_utf8_string, safe_utf8_string_size, &utf8_string_index, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy Unicode character to UTF-8 string.", function ); goto on_error; } } if( utf8_string_index >= safe_utf8_string_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid UTF-8 string size value out of bounds.", function ); goto on_error; } safe_utf8_string[ utf8_string_index++ ] = 0; *utf8_string = safe_utf8_string; *utf8_string_size = utf8_string_index; return( 1 ); on_error: if( safe_utf8_string != NULL ) { PyMem_Free( safe_utf8_string ); } return( -1 ); } #endif /* PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 */ ================================================ FILE: pyfsntfs/pyfsntfs_string.h ================================================ /* * String functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_STRING_H ) #define _PYFSNTFS_STRING_H #include #include #include "pyfsntfs_libcerror.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 PyObject *pyfsntfs_string_new_from_utf8_rfc2279( const uint8_t *utf8_string, size_t utf8_string_size ); int pyfsntfs_string_copy_to_utf8_rfc2279( PyObject *string_object, uint8_t **utf8_string, size_t *utf8_string_size, libcerror_error_t **error ); #endif /* PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 */ #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_STRING_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_unused.h ================================================ /* * Definitions to silence compiler warnings about unused function attributes/parameters. * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_UNUSED_H ) #define _PYFSNTFS_UNUSED_H #include #if !defined( PYFSNTFS_ATTRIBUTE_UNUSED ) #if defined( __GNUC__ ) && __GNUC__ >= 3 #define PYFSNTFS_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) #else #define PYFSNTFS_ATTRIBUTE_UNUSED #endif #endif #if defined( _MSC_VER ) #define PYFSNTFS_UNREFERENCED_PARAMETER( parameter ) \ UNREFERENCED_PARAMETER( parameter ); #else #define PYFSNTFS_UNREFERENCED_PARAMETER( parameter ) \ /* parameter */ #endif #endif /* !defined( _PYFSNTFS_UNUSED_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_usn_change_journal.c ================================================ /* * Python object definition of the libfsntfs update (or change) journal * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_error.h" #include "pyfsntfs_integer.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #include "pyfsntfs_unused.h" #include "pyfsntfs_usn_change_journal.h" PyMethodDef pyfsntfs_usn_change_journal_object_methods[] = { /* Functions to access the USN change journal */ { "get_offset", (PyCFunction) pyfsntfs_usn_change_journal_get_offset, METH_NOARGS, "get_offset() -> Integer\n" "\n" "Returns the current offset within the USN change journal data." }, { "read_usn_record", (PyCFunction) pyfsntfs_usn_change_journal_read_usn_record, METH_NOARGS, "read_usn_record() -> String\n" "\n" "Reads USN record data." }, /* Sentinel */ { NULL, NULL, 0, NULL } }; PyGetSetDef pyfsntfs_usn_change_journal_object_get_set_definitions[] = { /* Sentinel */ { NULL, NULL, NULL, NULL, NULL } }; PyTypeObject pyfsntfs_usn_change_journal_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs.usn_change_journal", /* tp_basicsize */ sizeof( pyfsntfs_usn_change_journal_t ), /* tp_itemsize */ 0, /* tp_dealloc */ (destructor) pyfsntfs_usn_change_journal_free, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_doc */ "pyfsntfs USN change journal object (wraps libfsntfs_usn_change_journal_t)", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ pyfsntfs_usn_change_journal_object_methods, /* tp_members */ 0, /* tp_getset */ pyfsntfs_usn_change_journal_object_get_set_definitions, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ (initproc) pyfsntfs_usn_change_journal_init, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Creates a new USN change journal object * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_usn_change_journal_new( libfsntfs_usn_change_journal_t *usn_change_journal, PyObject *parent_object ) { pyfsntfs_usn_change_journal_t *pyfsntfs_usn_change_journal = NULL; static char *function = "pyfsntfs_usn_change_journal_new"; if( usn_change_journal == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid USN change journal.", function ); return( NULL ); } /* PyObject_New does not invoke tp_init */ pyfsntfs_usn_change_journal = PyObject_New( struct pyfsntfs_usn_change_journal, &pyfsntfs_usn_change_journal_type_object ); if( pyfsntfs_usn_change_journal == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to initialize USN change journal.", function ); goto on_error; } pyfsntfs_usn_change_journal->usn_change_journal = usn_change_journal; pyfsntfs_usn_change_journal->parent_object = parent_object; if( pyfsntfs_usn_change_journal->parent_object != NULL ) { Py_IncRef( pyfsntfs_usn_change_journal->parent_object ); } return( (PyObject *) pyfsntfs_usn_change_journal ); on_error: if( pyfsntfs_usn_change_journal != NULL ) { Py_DecRef( (PyObject *) pyfsntfs_usn_change_journal ); } return( NULL ); } /* Initializes an USN change journal object * Returns 0 if successful or -1 on error */ int pyfsntfs_usn_change_journal_init( pyfsntfs_usn_change_journal_t *pyfsntfs_usn_change_journal ) { static char *function = "pyfsntfs_usn_change_journal_init"; if( pyfsntfs_usn_change_journal == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid USN change journal.", function ); return( -1 ); } /* Make sure libfsntfs USN change journal is set to NULL */ pyfsntfs_usn_change_journal->usn_change_journal = NULL; PyErr_Format( PyExc_NotImplementedError, "%s: initialize of USN change journal not supported.", function ); return( -1 ); } /* Frees an USN change journal object */ void pyfsntfs_usn_change_journal_free( pyfsntfs_usn_change_journal_t *pyfsntfs_usn_change_journal ) { struct _typeobject *ob_type = NULL; libcerror_error_t *error = NULL; static char *function = "pyfsntfs_usn_change_journal_free"; int result = 0; if( pyfsntfs_usn_change_journal == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid USN change journal.", function ); return; } ob_type = Py_TYPE( pyfsntfs_usn_change_journal ); if( ob_type == NULL ) { PyErr_Format( PyExc_ValueError, "%s: missing ob_type.", function ); return; } if( ob_type->tp_free == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid ob_type - missing tp_free.", function ); return; } if( pyfsntfs_usn_change_journal->usn_change_journal != NULL ) { Py_BEGIN_ALLOW_THREADS result = libfsntfs_usn_change_journal_free( &( pyfsntfs_usn_change_journal->usn_change_journal ), &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_MemoryError, "%s: unable to free libfsntfs USN change journal.", function ); libcerror_error_free( &error ); } } if( pyfsntfs_usn_change_journal->parent_object != NULL ) { Py_DecRef( pyfsntfs_usn_change_journal->parent_object ); } ob_type->tp_free( (PyObject*) pyfsntfs_usn_change_journal ); } /* Retrieves the offset * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_usn_change_journal_get_offset( pyfsntfs_usn_change_journal_t *pyfsntfs_usn_change_journal, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_usn_change_journal_get_offset"; off64_t offset = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_usn_change_journal == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid USN change journal.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_usn_change_journal_get_offset( pyfsntfs_usn_change_journal->usn_change_journal, &offset, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve offset.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_signed_new_from_64bit( (int64_t) offset ); return( integer_object ); } /* Reads an USN record * Returns a Python object holding the data if successful or NULL on error */ PyObject *pyfsntfs_usn_change_journal_read_usn_record( pyfsntfs_usn_change_journal_t *pyfsntfs_usn_change_journal, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *string_object = NULL; static char *function = "pyfsntfs_usn_change_journal_read_usn_record"; char *usn_record_data = NULL; size_t journal_block_size = 0x1000; ssize_t read_count = 0; if( pyfsntfs_usn_change_journal == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid USN change journal.", function ); return( NULL ); } if( pyfsntfs_usn_change_journal->usn_change_journal == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid USN change journal - missing libfsntfs USN change journal.", function ); return( NULL ); } /* TODO get journal block size from USN change journal */ if( ( journal_block_size == 0 ) || ( journal_block_size > (size_t) SSIZE_MAX ) ) { PyErr_Format( PyExc_ValueError, "%s: invalid argument read size value exceeds maximum.", function ); return( NULL ); } #if PY_MAJOR_VERSION >= 3 string_object = PyBytes_FromStringAndSize( NULL, journal_block_size ); usn_record_data = PyBytes_AsString( string_object ); #else /* Note that a size of 0 is not supported */ string_object = PyString_FromStringAndSize( NULL, journal_block_size ); usn_record_data = PyString_AsString( string_object ); #endif Py_BEGIN_ALLOW_THREADS read_count = libfsntfs_usn_change_journal_read_usn_record( pyfsntfs_usn_change_journal->usn_change_journal, (uint8_t *) usn_record_data, (size_t) journal_block_size, &error ); Py_END_ALLOW_THREADS if( read_count <= -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to read data.", function ); libcerror_error_free( &error ); Py_DecRef( (PyObject *) string_object ); return( NULL ); } /* Need to resize the string here in case journal_block_size was not fully read. */ #if PY_MAJOR_VERSION >= 3 if( _PyBytes_Resize( &string_object, (Py_ssize_t) read_count ) != 0 ) #else if( _PyString_Resize( &string_object, (Py_ssize_t) read_count ) != 0 ) #endif { Py_DecRef( (PyObject *) string_object ); return( NULL ); } return( string_object ); } ================================================ FILE: pyfsntfs/pyfsntfs_usn_change_journal.h ================================================ /* * ython object wrapper of libfsntfs_usn_change_journal_t * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_USN_CHANGE_JOURNAL_H ) #define _PYFSNTFS_USN_CHANGE_JOURNAL_H #include #include #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct pyfsntfs_usn_change_journal pyfsntfs_usn_change_journal_t; struct pyfsntfs_usn_change_journal { /* Python object initialization */ PyObject_HEAD /* The libfsntfs USN change journal */ libfsntfs_usn_change_journal_t *usn_change_journal; /* The parent object */ PyObject *parent_object; }; extern PyMethodDef pyfsntfs_usn_change_journal_object_methods[]; extern PyTypeObject pyfsntfs_usn_change_journal_type_object; PyObject *pyfsntfs_usn_change_journal_new( libfsntfs_usn_change_journal_t *usn_change_journal, PyObject *parent_object ); int pyfsntfs_usn_change_journal_init( pyfsntfs_usn_change_journal_t *pyfsntfs_usn_change_journal ); void pyfsntfs_usn_change_journal_free( pyfsntfs_usn_change_journal_t *pyfsntfs_usn_change_journal ); PyObject *pyfsntfs_usn_change_journal_get_offset( pyfsntfs_usn_change_journal_t *pyfsntfs_usn_change_journal, PyObject *arguments ); PyObject *pyfsntfs_usn_change_journal_read_usn_record( pyfsntfs_usn_change_journal_t *pyfsntfs_usn_change_journal, PyObject *arguments ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_USN_CHANGE_JOURNAL_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_volume.c ================================================ /* * Python object definition of the libfsntfs volume * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_error.h" #include "pyfsntfs_file_entry.h" #include "pyfsntfs_file_object_io_handle.h" #include "pyfsntfs_integer.h" #include "pyfsntfs_libbfio.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #include "pyfsntfs_string.h" #include "pyfsntfs_unused.h" #include "pyfsntfs_usn_change_journal.h" #include "pyfsntfs_volume.h" #include "pyfsntfs_volume_file_entries.h" #if !defined( LIBFSNTFS_HAVE_BFIO ) LIBFSNTFS_EXTERN \ int libfsntfs_volume_open_file_io_handle( libfsntfs_volume_t *volume, libbfio_handle_t *file_io_handle, int access_flags, libfsntfs_error_t **error ); #endif /* !defined( LIBFSNTFS_HAVE_BFIO ) */ PyMethodDef pyfsntfs_volume_object_methods[] = { { "signal_abort", (PyCFunction) pyfsntfs_volume_signal_abort, METH_NOARGS, "signal_abort() -> None\n" "\n" "Signals the volume to abort the current activity." }, /* Functions to access the volume */ { "open", (PyCFunction) pyfsntfs_volume_open, METH_VARARGS | METH_KEYWORDS, "open(filename, mode='r') -> None\n" "\n" "Opens a volume." }, { "open_file_object", (PyCFunction) pyfsntfs_volume_open_file_object, METH_VARARGS | METH_KEYWORDS, "open_file_object(file_object, mode='r') -> None\n" "\n" "Opens a volume using a file-like object." }, { "close", (PyCFunction) pyfsntfs_volume_close, METH_NOARGS, "close() -> None\n" "\n" "Closes a volume." }, /* Functions to access the volume values */ { "get_bytes_per_sector", (PyCFunction) pyfsntfs_volume_get_bytes_per_sector, METH_NOARGS, "get_bytes_per_sector() -> Integer\n" "\n" "Retrieves the bytes per sector." }, { "get_cluster_block_size", (PyCFunction) pyfsntfs_volume_get_cluster_block_size, METH_NOARGS, "get_cluster_block_size() -> Integer\n" "\n" "Retrieves the cluster block size." }, { "get_mft_entry_size", (PyCFunction) pyfsntfs_volume_get_mft_entry_size, METH_NOARGS, "get_mft_entry_size() -> Integer\n" "\n" "Retrieves the MFT entry size." }, { "get_index_entry_size", (PyCFunction) pyfsntfs_volume_get_index_entry_size, METH_NOARGS, "get_index_entry_size() -> Integer\n" "\n" "Retrieves the index entry size." }, { "get_name", (PyCFunction) pyfsntfs_volume_get_name, METH_NOARGS, "get_name() -> Unicode string or None\n" "\n" "Retrieves the name." }, { "get_serial_number", (PyCFunction) pyfsntfs_volume_get_serial_number, METH_NOARGS, "get_serial_number() -> Integer\n" "\n" "Retrieves the serial number." }, /* Functions to access the file entries */ { "get_number_of_file_entries", (PyCFunction) pyfsntfs_volume_get_number_of_file_entries, METH_NOARGS, "get_number_of_file_entries() -> Integer\n" "\n" "Retrieves the number of file entries." }, { "get_file_entry", (PyCFunction) pyfsntfs_volume_get_file_entry, METH_VARARGS | METH_KEYWORDS, "get_file_entry(file_entry_index) -> Object\n" "\n" "Retrieves a specific file entry." }, { "get_root_directory", (PyCFunction) pyfsntfs_volume_get_root_directory, METH_NOARGS, "get_root_directory() -> Object\n" "\n" "Retrieves the root directory." }, { "get_file_entry_by_path", (PyCFunction) pyfsntfs_volume_get_file_entry_by_path, METH_VARARGS | METH_KEYWORDS, "get_file_entry_by_path(path) -> Object or None\n" "\n" "Retrieves a file entry specified by the path." }, { "get_usn_change_journal", (PyCFunction) pyfsntfs_volume_get_usn_change_journal, METH_NOARGS, "get_usn_change_journal() -> Object or None\n" "\n" "Retrieves the USN change journal." }, /* Sentinel */ { NULL, NULL, 0, NULL } }; PyGetSetDef pyfsntfs_volume_object_get_set_definitions[] = { { "bytes_per_sector", (getter) pyfsntfs_volume_get_bytes_per_sector, (setter) 0, "The bytes per sector.", NULL }, { "cluster_block_size", (getter) pyfsntfs_volume_get_cluster_block_size, (setter) 0, "The cluster block size.", NULL }, { "mft_entry_size", (getter) pyfsntfs_volume_get_mft_entry_size, (setter) 0, "The MFT entry size.", NULL }, { "index_entry_size", (getter) pyfsntfs_volume_get_index_entry_size, (setter) 0, "The index entry size.", NULL }, { "name", (getter) pyfsntfs_volume_get_name, (setter) 0, "The name.", NULL }, { "serial_number", (getter) pyfsntfs_volume_get_serial_number, (setter) 0, "The serial number.", NULL }, { "number_of_file_entries", (getter) pyfsntfs_volume_get_number_of_file_entries, (setter) 0, "The number of file entries.", NULL }, { "file_entries", (getter) pyfsntfs_volume_get_file_entries, (setter) 0, "The file entries", NULL }, /* Sentinel */ { NULL, NULL, NULL, NULL, NULL } }; PyTypeObject pyfsntfs_volume_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs.volume", /* tp_basicsize */ sizeof( pyfsntfs_volume_t ), /* tp_itemsize */ 0, /* tp_dealloc */ (destructor) pyfsntfs_volume_free, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_doc */ "pyfsntfs volume object (wraps libfsntfs_volume_t)", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ pyfsntfs_volume_object_methods, /* tp_members */ 0, /* tp_getset */ pyfsntfs_volume_object_get_set_definitions, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ (initproc) pyfsntfs_volume_init, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Initializes a volume object * Returns 0 if successful or -1 on error */ int pyfsntfs_volume_init( pyfsntfs_volume_t *pyfsntfs_volume ) { libcerror_error_t *error = NULL; static char *function = "pyfsntfs_volume_init"; if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume.", function ); return( -1 ); } /* Make sure libfsntfs volume is set to NULL */ pyfsntfs_volume->volume = NULL; pyfsntfs_volume->file_io_handle = NULL; if( libfsntfs_volume_initialize( &( pyfsntfs_volume->volume ), &error ) != 1 ) { pyfsntfs_error_raise( error, PyExc_MemoryError, "%s: unable to initialize volume.", function ); libcerror_error_free( &error ); return( -1 ); } return( 0 ); } /* Frees a volume object */ void pyfsntfs_volume_free( pyfsntfs_volume_t *pyfsntfs_volume ) { struct _typeobject *ob_type = NULL; libcerror_error_t *error = NULL; static char *function = "pyfsntfs_volume_free"; int result = 0; if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume.", function ); return; } ob_type = Py_TYPE( pyfsntfs_volume ); if( ob_type == NULL ) { PyErr_Format( PyExc_ValueError, "%s: missing ob_type.", function ); return; } if( ob_type->tp_free == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid ob_type - missing tp_free.", function ); return; } if( pyfsntfs_volume->file_io_handle != NULL ) { if( pyfsntfs_volume_close( pyfsntfs_volume, NULL ) == NULL ) { return; } } if( pyfsntfs_volume->volume != NULL ) { Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_free( &( pyfsntfs_volume->volume ), &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_MemoryError, "%s: unable to free libfsntfs volume.", function ); libcerror_error_free( &error ); } } ob_type->tp_free( (PyObject*) pyfsntfs_volume ); } /* Signals the volume to abort the current activity * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_signal_abort( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; static char *function = "pyfsntfs_volume_signal_abort"; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_signal_abort( pyfsntfs_volume->volume, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to signal abort.", function ); libcerror_error_free( &error ); return( NULL ); } Py_IncRef( Py_None ); return( Py_None ); } /* Opens a volume * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_open( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments, PyObject *keywords ) { PyObject *string_object = NULL; libcerror_error_t *error = NULL; const char *filename_narrow = NULL; static char *function = "pyfsntfs_volume_open"; static char *keyword_list[] = { "filename", "mode", NULL }; char *mode = NULL; int result = 0; #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) const wchar_t *filename_wide = NULL; #else PyObject *utf8_string_object = NULL; #endif if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume.", function ); return( NULL ); } /* Note that PyArg_ParseTupleAndKeywords with "s" will force Unicode strings to be converted to narrow character string. * On Windows the narrow character strings contains an extended ASCII string with a codepage. Hence we get a conversion * exception. This will also fail if the default encoding is not set correctly. We cannot use "u" here either since that * does not allow us to pass non Unicode string objects and Python (at least 2.7) does not seems to automatically upcast them. */ if( PyArg_ParseTupleAndKeywords( arguments, keywords, "O|s", keyword_list, &string_object, &mode ) == 0 ) { return( NULL ); } if( ( mode != NULL ) && ( mode[ 0 ] != 'r' ) ) { PyErr_Format( PyExc_ValueError, "%s: unsupported mode: %s.", function, mode ); return( NULL ); } PyErr_Clear(); result = PyObject_IsInstance( string_object, (PyObject *) &PyUnicode_Type ); if( result == -1 ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to determine if string object is of type Unicode.", function ); return( NULL ); } else if( result != 0 ) { PyErr_Clear(); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 filename_wide = (wchar_t *) PyUnicode_AsWideCharString( string_object, NULL ); #else filename_wide = (wchar_t *) PyUnicode_AsUnicode( string_object ); #endif Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_open_wide( pyfsntfs_volume->volume, filename_wide, LIBFSNTFS_OPEN_READ, &error ); Py_END_ALLOW_THREADS #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 PyMem_Free( filename_wide ); #endif #else utf8_string_object = PyUnicode_AsUTF8String( string_object ); if( utf8_string_object == NULL ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to convert Unicode string to UTF-8.", function ); return( NULL ); } #if PY_MAJOR_VERSION >= 3 filename_narrow = PyBytes_AsString( utf8_string_object ); #else filename_narrow = PyString_AsString( utf8_string_object ); #endif Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_open( pyfsntfs_volume->volume, filename_narrow, LIBFSNTFS_OPEN_READ, &error ); Py_END_ALLOW_THREADS Py_DecRef( utf8_string_object ); #endif if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to open volume.", function ); libcerror_error_free( &error ); return( NULL ); } Py_IncRef( Py_None ); return( Py_None ); } PyErr_Clear(); #if PY_MAJOR_VERSION >= 3 result = PyObject_IsInstance( string_object, (PyObject *) &PyBytes_Type ); #else result = PyObject_IsInstance( string_object, (PyObject *) &PyString_Type ); #endif if( result == -1 ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to determine if string object is of type string.", function ); return( NULL ); } else if( result != 0 ) { PyErr_Clear(); #if PY_MAJOR_VERSION >= 3 filename_narrow = PyBytes_AsString( string_object ); #else filename_narrow = PyString_AsString( string_object ); #endif Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_open( pyfsntfs_volume->volume, filename_narrow, LIBFSNTFS_OPEN_READ, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to open volume.", function ); libcerror_error_free( &error ); return( NULL ); } Py_IncRef( Py_None ); return( Py_None ); } PyErr_Format( PyExc_TypeError, "%s: unsupported string object type.", function ); return( NULL ); } /* Opens a volume using a file-like object * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_open_file_object( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments, PyObject *keywords ) { PyObject *file_object = NULL; libcerror_error_t *error = NULL; static char *function = "pyfsntfs_volume_open_file_object"; static char *keyword_list[] = { "file_object", "mode", NULL }; char *mode = NULL; int result = 0; if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume.", function ); return( NULL ); } if( PyArg_ParseTupleAndKeywords( arguments, keywords, "O|s", keyword_list, &file_object, &mode ) == 0 ) { return( NULL ); } if( ( mode != NULL ) && ( mode[ 0 ] != 'r' ) ) { PyErr_Format( PyExc_ValueError, "%s: unsupported mode: %s.", function, mode ); return( NULL ); } PyErr_Clear(); result = PyObject_HasAttrString( file_object, "read" ); if( result != 1 ) { PyErr_Format( PyExc_TypeError, "%s: unsupported file object - missing read attribute.", function ); return( NULL ); } PyErr_Clear(); result = PyObject_HasAttrString( file_object, "seek" ); if( result != 1 ) { PyErr_Format( PyExc_TypeError, "%s: unsupported file object - missing seek attribute.", function ); return( NULL ); } if( pyfsntfs_volume->file_io_handle != NULL ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: invalid volume - file IO handle already set.", function ); goto on_error; } if( pyfsntfs_file_object_initialize( &( pyfsntfs_volume->file_io_handle ), file_object, &error ) != 1 ) { pyfsntfs_error_raise( error, PyExc_MemoryError, "%s: unable to initialize file IO handle.", function ); libcerror_error_free( &error ); goto on_error; } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_open_file_io_handle( pyfsntfs_volume->volume, pyfsntfs_volume->file_io_handle, LIBFSNTFS_OPEN_READ, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to open volume.", function ); libcerror_error_free( &error ); goto on_error; } Py_IncRef( Py_None ); return( Py_None ); on_error: if( pyfsntfs_volume->file_io_handle != NULL ) { libbfio_handle_free( &( pyfsntfs_volume->file_io_handle ), NULL ); } return( NULL ); } /* Closes a volume * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_close( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; static char *function = "pyfsntfs_volume_close"; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_close( pyfsntfs_volume->volume, &error ); Py_END_ALLOW_THREADS if( result != 0 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to close volume.", function ); libcerror_error_free( &error ); return( NULL ); } if( pyfsntfs_volume->file_io_handle != NULL ) { Py_BEGIN_ALLOW_THREADS result = libbfio_handle_free( &( pyfsntfs_volume->file_io_handle ), &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_MemoryError, "%s: unable to free libbfio file IO handle.", function ); libcerror_error_free( &error ); return( NULL ); } } Py_IncRef( Py_None ); return( Py_None ); } /* Retrieves the bytes per sector * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_get_bytes_per_sector( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { PyObject *integer_object = NULL; libcerror_error_t *error = NULL; static char *function = "pyfsntfs_volume_get_bytes_per_sector"; uint16_t bytes_per_sector = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_get_bytes_per_sector( pyfsntfs_volume->volume, &bytes_per_sector, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve bytes per sector.", function ); libcerror_error_free( &error ); return( NULL ); } #if PY_MAJOR_VERSION >= 3 integer_object = PyLong_FromLong( (long) bytes_per_sector ); #else integer_object = PyInt_FromLong( (long) bytes_per_sector ); #endif return( integer_object ); } /* Retrieves the cluster block size * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_get_cluster_block_size( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { PyObject *integer_object = NULL; libcerror_error_t *error = NULL; static char *function = "pyfsntfs_volume_get_cluster_block_size"; size32_t cluster_block_size = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_get_cluster_block_size( pyfsntfs_volume->volume, &cluster_block_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: failed to retrieve cluster block size.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = PyLong_FromUnsignedLong( (unsigned long) cluster_block_size ); return( integer_object ); } /* Retrieves the MFT entry size * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_get_mft_entry_size( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { PyObject *integer_object = NULL; libcerror_error_t *error = NULL; static char *function = "pyfsntfs_volume_get_mft_entry_size"; size32_t mft_entry_size = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_get_mft_entry_size( pyfsntfs_volume->volume, &mft_entry_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: failed to retrieve MFT entry size.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = PyLong_FromUnsignedLong( (unsigned long) mft_entry_size ); return( integer_object ); } /* Retrieves the index entry size * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_get_index_entry_size( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { PyObject *integer_object = NULL; libcerror_error_t *error = NULL; static char *function = "pyfsntfs_volume_get_index_entry_size"; size32_t index_entry_size = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_get_index_entry_size( pyfsntfs_volume->volume, &index_entry_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: failed to retrieve index entry size.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = PyLong_FromUnsignedLong( (unsigned long) index_entry_size ); return( integer_object ); } /* Retrieves the name * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_get_name( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *string_object = NULL; uint8_t *name = NULL; static char *function = "pyfsntfs_volume_get_name"; size_t name_size = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_get_utf8_name_size( pyfsntfs_volume->volume, &name_size, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve name size.", function ); libcerror_error_free( &error ); goto on_error; } else if( ( result == 0 ) || ( name_size == 0 ) ) { Py_IncRef( Py_None ); return( Py_None ); } name = (uint8_t *) PyMem_Malloc( sizeof( uint8_t ) * name_size ); if( name == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create name.", function ); goto on_error; } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_get_utf8_name( pyfsntfs_volume->volume, name, name_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve name.", function ); libcerror_error_free( &error ); goto on_error; } /* Pass the string length to PyUnicode_DecodeUTF8 * otherwise it makes the end of string character is part * of the string */ string_object = PyUnicode_DecodeUTF8( (char *) name, (Py_ssize_t) name_size - 1, NULL ); PyMem_Free( name ); return( string_object ); on_error: if( name != NULL ) { PyMem_Free( name ); } return( NULL ); } /* Retrieves the serial number * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_get_serial_number( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { PyObject *integer_object = NULL; libcerror_error_t *error = NULL; static char *function = "pyfsntfs_volume_get_serial_number"; uint64_t value_64bit = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_get_serial_number( pyfsntfs_volume->volume, &value_64bit, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve serial number.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( (uint64_t) value_64bit ); return( integer_object ); } /* Retrieves the number of file entries * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_get_number_of_file_entries( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_volume_get_number_of_file_entries"; uint64_t number_of_file_entries = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_get_number_of_file_entries( pyfsntfs_volume->volume, &number_of_file_entries, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve number of file entries.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( number_of_file_entries ); return( integer_object ); } /* Retrieves a specific file entry by index * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_get_file_entry_by_index( pyfsntfs_volume_t *pyfsntfs_volume, uint64_t file_entry_index ) { libcerror_error_t *error = NULL; libfsntfs_file_entry_t *file_entry = NULL; PyObject *file_entry_object = NULL; static char *function = "pyfsntfs_volume_get_file_entry_by_index"; int result = 0; if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_get_file_entry_by_index( pyfsntfs_volume->volume, file_entry_index, &file_entry, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve file entry: %" PRIu64 ".", function, file_entry_index ); libcerror_error_free( &error ); goto on_error; } file_entry_object = pyfsntfs_file_entry_new( file_entry, (PyObject *) pyfsntfs_volume ); if( file_entry_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create file entry object.", function ); goto on_error; } return( file_entry_object ); on_error: if( file_entry != NULL ) { libfsntfs_file_entry_free( &file_entry, NULL ); } return( NULL ); } /* Retrieves a specific file entry * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_get_file_entry( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments, PyObject *keywords ) { PyObject *file_entry_object = NULL; static char *keyword_list[] = { "file_entry_index", NULL }; int file_entry_index = 0; if( PyArg_ParseTupleAndKeywords( arguments, keywords, "i", keyword_list, &file_entry_index ) == 0 ) { return( NULL ); } file_entry_object = pyfsntfs_volume_get_file_entry_by_index( pyfsntfs_volume, file_entry_index ); return( file_entry_object ); } /* Retrieves a file entries sequence and iterator object for the volume file entries * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_get_file_entries( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *volume_file_entries_object = NULL; static char *function = "pyfsntfs_volume_get_file_entries"; uint64_t number_of_file_entries = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_get_number_of_file_entries( pyfsntfs_volume->volume, &number_of_file_entries, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve number of file entries.", function ); libcerror_error_free( &error ); return( NULL ); } volume_file_entries_object = pyfsntfs_volume_file_entries_new( pyfsntfs_volume, &pyfsntfs_volume_get_file_entry_by_index, number_of_file_entries ); if( volume_file_entries_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create volume file entries object.", function ); return( NULL ); } return( volume_file_entries_object ); } /* Retrieves the file entry specified by the path * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_get_file_entry_by_path( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments, PyObject *keywords ) { PyObject *file_entry_object = NULL; PyObject *string_object = NULL; libcerror_error_t *error = NULL; libfsntfs_file_entry_t *file_entry = NULL; static char *function = "pyfsntfs_volume_get_file_entry_by_path"; static char *keyword_list[] = { "path", NULL }; char *path = NULL; const char *narrow_string = NULL; size_t path_length = 0; size_t path_size = 0; int result = 0; #if PY_MAJOR_VERSION <= 2 || ( PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION <= 2 ) PyObject *utf8_string_object = NULL; #endif if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume.", function ); return( NULL ); } if( PyArg_ParseTupleAndKeywords( arguments, keywords, "O", keyword_list, &string_object ) == 0 ) { goto on_error; } PyErr_Clear(); result = PyObject_IsInstance( string_object, (PyObject *) &PyUnicode_Type ); if( result == -1 ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to determine if string object is of type Unicode.", function ); goto on_error; } else if( result != 0 ) { #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 if( pyfsntfs_string_copy_to_utf8_rfc2279( string_object, (uint8_t **) &path, &path_size, &error ) != 1 ) { pyfsntfs_error_raise( error, PyExc_RuntimeError, "%s: unable to copy string object to UTF-8 string.", function ); libcerror_error_free( &error ); goto on_error; } narrow_string = path; path_length = path_size - 1; #else PyErr_Clear(); utf8_string_object = PyUnicode_AsUTF8String( string_object ); if( utf8_string_object == NULL ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to convert Unicode string to UTF-8.", function ); goto on_error; } #if PY_MAJOR_VERSION >= 3 narrow_string = PyBytes_AsString( utf8_string_object ); #else narrow_string = PyString_AsString( utf8_string_object ); #endif path_length = narrow_string_length( narrow_string ); #endif } else if( result == 0 ) { PyErr_Clear(); #if PY_MAJOR_VERSION >= 3 result = PyObject_IsInstance( string_object, (PyObject *) &PyBytes_Type ); #else result = PyObject_IsInstance( string_object, (PyObject *) &PyString_Type ); #endif if( result == -1 ) { pyfsntfs_error_fetch_and_raise( PyExc_RuntimeError, "%s: unable to determine if string object is of type string.", function ); goto on_error; } else if( result == 0 ) { PyErr_Format( PyExc_TypeError, "%s: unsupported string object type.", function ); goto on_error; } PyErr_Clear(); #if PY_MAJOR_VERSION >= 3 narrow_string = PyBytes_AsString( string_object ); #else narrow_string = PyString_AsString( string_object ); #endif path_length = narrow_string_length( narrow_string ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_get_file_entry_by_utf8_path( pyfsntfs_volume->volume, (uint8_t *) narrow_string, path_length, &file_entry, &error ); Py_END_ALLOW_THREADS #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 if( path != NULL ) { PyMem_Free( path ); path = NULL; } #else if( utf8_string_object != NULL ) { Py_DecRef( utf8_string_object ); utf8_string_object = NULL; } #endif if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve file entry.", function ); libcerror_error_free( &error ); goto on_error; } /* Check if the file entry is present */ else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } file_entry_object = pyfsntfs_file_entry_new( file_entry, (PyObject *) pyfsntfs_volume ); if( file_entry_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create file entry object.", function ); goto on_error; } return( file_entry_object ); on_error: if( file_entry != NULL ) { libfsntfs_file_entry_free( &file_entry, NULL ); } #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 if( path != NULL ) { PyMem_Free( path ); } #else if( utf8_string_object != NULL ) { Py_DecRef( utf8_string_object ); } #endif return( NULL ); } /* Retrieves the root directory * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_get_root_directory( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; libfsntfs_file_entry_t *root_directory = NULL; PyObject *file_entry_object = NULL; static char *function = "pyfsntfs_volume_get_root_directory"; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_get_root_directory( pyfsntfs_volume->volume, &root_directory, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve root directory.", function ); libcerror_error_free( &error ); goto on_error; } file_entry_object = pyfsntfs_file_entry_new( root_directory, (PyObject *) pyfsntfs_volume ); if( file_entry_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create file entry object.", function ); goto on_error; } return( file_entry_object ); on_error: if( root_directory != NULL ) { libfsntfs_file_entry_free( &root_directory, NULL ); } return( NULL ); } /* Retrieves the USN change journal * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_get_usn_change_journal( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; libfsntfs_usn_change_journal_t *usn_change_journal = NULL; PyObject *usn_change_journal_object = NULL; static char *function = "pyfsntfs_volume_get_usn_change_journal"; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_volume == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_get_usn_change_journal( pyfsntfs_volume->volume, &usn_change_journal, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve USN change journal.", function ); libcerror_error_free( &error ); goto on_error; } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } usn_change_journal_object = pyfsntfs_usn_change_journal_new( usn_change_journal, (PyObject *) pyfsntfs_volume ); if( usn_change_journal_object == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create USN change journal object.", function ); goto on_error; } return( usn_change_journal_object ); on_error: if( usn_change_journal != NULL ) { libfsntfs_usn_change_journal_free( &usn_change_journal, NULL ); } return( NULL ); } ================================================ FILE: pyfsntfs/pyfsntfs_volume.h ================================================ /* * Python object definition of the libfsntfs volume * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_VOLUME_H ) #define _PYFSNTFS_VOLUME_H #include #include #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_libbfio.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct pyfsntfs_volume pyfsntfs_volume_t; struct pyfsntfs_volume { /* Python object initialization */ PyObject_HEAD /* The libfsntfs volume */ libfsntfs_volume_t *volume; /* The libbfio file IO handle */ libbfio_handle_t *file_io_handle; }; extern PyMethodDef pyfsntfs_volume_object_methods[]; extern PyTypeObject pyfsntfs_volume_type_object; int pyfsntfs_volume_init( pyfsntfs_volume_t *pyfsntfs_volume ); void pyfsntfs_volume_free( pyfsntfs_volume_t *pyfsntfs_volume ); PyObject *pyfsntfs_volume_signal_abort( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments ); PyObject *pyfsntfs_volume_open( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_volume_open_file_object( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_volume_close( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments ); PyObject *pyfsntfs_volume_get_bytes_per_sector( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments ); PyObject *pyfsntfs_volume_get_cluster_block_size( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments ); PyObject *pyfsntfs_volume_get_mft_entry_size( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments ); PyObject *pyfsntfs_volume_get_index_entry_size( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments ); PyObject *pyfsntfs_volume_get_name( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments ); PyObject *pyfsntfs_volume_get_serial_number( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments ); PyObject *pyfsntfs_volume_get_number_of_file_entries( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments ); PyObject *pyfsntfs_volume_get_file_entry_by_index( pyfsntfs_volume_t *pyfsntfs_volume, uint64_t file_entry_index ); PyObject *pyfsntfs_volume_get_file_entry( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_volume_get_file_entries( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments ); PyObject *pyfsntfs_volume_get_file_entry_by_path( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments, PyObject *keywords ); PyObject *pyfsntfs_volume_get_root_directory( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments ); PyObject *pyfsntfs_volume_get_usn_change_journal( pyfsntfs_volume_t *pyfsntfs_volume, PyObject *arguments ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_VOLUME_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_volume_file_entries.c ================================================ /* * Python object definition of the volume file entries sequence and iterator * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_file_entry.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #include "pyfsntfs_volume_file_entries.h" PySequenceMethods pyfsntfs_volume_file_entries_sequence_methods = { /* sq_length */ (lenfunc) pyfsntfs_volume_file_entries_len, /* sq_concat */ 0, /* sq_repeat */ 0, /* sq_item */ (ssizeargfunc) pyfsntfs_volume_file_entries_getitem, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ 0, /* sq_contains */ 0, /* sq_inplace_concat */ 0, /* sq_inplace_repeat */ 0 }; PyTypeObject pyfsntfs_volume_file_entries_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs._volume_file_entries", /* tp_basicsize */ sizeof( pyfsntfs_volume_file_entries_t ), /* tp_itemsize */ 0, /* tp_dealloc */ (destructor) pyfsntfs_volume_file_entries_free, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ &pyfsntfs_volume_file_entries_sequence_methods, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /* tp_doc */ "internal pyfsntfs volume file entries sequence and iterator object", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ (getiterfunc) pyfsntfs_volume_file_entries_iter, /* tp_iternext */ (iternextfunc) pyfsntfs_volume_file_entries_iternext, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ (initproc) pyfsntfs_volume_file_entries_init, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Creates a new volume file entries object * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_file_entries_new( pyfsntfs_volume_t *volume_object, PyObject* (*get_file_entry_by_index)( pyfsntfs_volume_t *volume_object, uint64_t file_entry_index ), uint64_t number_of_file_entries ) { pyfsntfs_volume_file_entries_t *pyfsntfs_volume_file_entries = NULL; static char *function = "pyfsntfs_volume_file_entries_new"; if( volume_object == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume object.", function ); return( NULL ); } if( get_file_entry_by_index == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid get file entry by index function.", function ); return( NULL ); } /* Make sure the volume file entries values are initialized */ pyfsntfs_volume_file_entries = PyObject_New( struct pyfsntfs_volume_file_entries, &pyfsntfs_volume_file_entries_type_object ); if( pyfsntfs_volume_file_entries == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to initialize volume file entries.", function ); goto on_error; } if( pyfsntfs_volume_file_entries_init( pyfsntfs_volume_file_entries ) != 0 ) { PyErr_Format( PyExc_MemoryError, "%s: unable to initialize volume file entries.", function ); goto on_error; } pyfsntfs_volume_file_entries->volume_object = volume_object; pyfsntfs_volume_file_entries->get_file_entry_by_index = get_file_entry_by_index; pyfsntfs_volume_file_entries->number_of_file_entries = number_of_file_entries; Py_IncRef( (PyObject *) pyfsntfs_volume_file_entries->volume_object ); return( (PyObject *) pyfsntfs_volume_file_entries ); on_error: if( pyfsntfs_volume_file_entries != NULL ) { Py_DecRef( (PyObject *) pyfsntfs_volume_file_entries ); } return( NULL ); } /* Initializes a volume file entries object * Returns 0 if successful or -1 on error */ int pyfsntfs_volume_file_entries_init( pyfsntfs_volume_file_entries_t *pyfsntfs_volume_file_entries ) { static char *function = "pyfsntfs_volume_file_entries_init"; if( pyfsntfs_volume_file_entries == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume file entries.", function ); return( -1 ); } /* Make sure the volume file entries values are initialized */ pyfsntfs_volume_file_entries->volume_object = NULL; pyfsntfs_volume_file_entries->get_file_entry_by_index = NULL; pyfsntfs_volume_file_entries->file_entry_index = 0; pyfsntfs_volume_file_entries->number_of_file_entries = 0; return( 0 ); } /* Frees a volume file entries object */ void pyfsntfs_volume_file_entries_free( pyfsntfs_volume_file_entries_t *pyfsntfs_volume_file_entries ) { struct _typeobject *ob_type = NULL; static char *function = "pyfsntfs_volume_file_entries_free"; if( pyfsntfs_volume_file_entries == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume file entries.", function ); return; } ob_type = Py_TYPE( pyfsntfs_volume_file_entries ); if( ob_type == NULL ) { PyErr_Format( PyExc_ValueError, "%s: missing ob_type.", function ); return; } if( ob_type->tp_free == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid ob_type - missing tp_free.", function ); return; } if( pyfsntfs_volume_file_entries->volume_object != NULL ) { Py_DecRef( (PyObject *) pyfsntfs_volume_file_entries->volume_object ); } ob_type->tp_free( (PyObject*) pyfsntfs_volume_file_entries ); } /* The volume file entries len() function */ Py_ssize_t pyfsntfs_volume_file_entries_len( pyfsntfs_volume_file_entries_t *pyfsntfs_volume_file_entries ) { static char *function = "pyfsntfs_volume_file_entries_len"; if( pyfsntfs_volume_file_entries == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume file entries.", function ); return( -1 ); } return( (Py_ssize_t) pyfsntfs_volume_file_entries->number_of_file_entries ); } /* The volume file entries getitem() function */ PyObject *pyfsntfs_volume_file_entries_getitem( pyfsntfs_volume_file_entries_t *pyfsntfs_volume_file_entries, Py_ssize_t item_index ) { PyObject *file_entry_object = NULL; static char *function = "pyfsntfs_volume_file_entries_getitem"; if( pyfsntfs_volume_file_entries == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume file entries.", function ); return( NULL ); } if( pyfsntfs_volume_file_entries->get_file_entry_by_index == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume file entries - missing get file entry by index function.", function ); return( NULL ); } if( pyfsntfs_volume_file_entries->number_of_file_entries < 0 ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume file entries - invalid number of file entries.", function ); return( NULL ); } if( ( item_index < 0 ) || ( item_index >= (Py_ssize_t) pyfsntfs_volume_file_entries->number_of_file_entries ) ) { PyErr_Format( PyExc_ValueError, "%s: invalid invalid item index value out of bounds.", function ); return( NULL ); } file_entry_object = pyfsntfs_volume_file_entries->get_file_entry_by_index( pyfsntfs_volume_file_entries->volume_object, (uint64_t) item_index ); return( file_entry_object ); } /* The volume file entries iter() function */ PyObject *pyfsntfs_volume_file_entries_iter( pyfsntfs_volume_file_entries_t *pyfsntfs_volume_file_entries ) { static char *function = "pyfsntfs_volume_file_entries_iter"; if( pyfsntfs_volume_file_entries == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume file entries.", function ); return( NULL ); } Py_IncRef( (PyObject *) pyfsntfs_volume_file_entries ); return( (PyObject *) pyfsntfs_volume_file_entries ); } /* The volume file entries iternext() function */ PyObject *pyfsntfs_volume_file_entries_iternext( pyfsntfs_volume_file_entries_t *pyfsntfs_volume_file_entries ) { PyObject *file_entry_object = NULL; static char *function = "pyfsntfs_volume_file_entries_iternext"; if( pyfsntfs_volume_file_entries == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume file entries.", function ); return( NULL ); } if( pyfsntfs_volume_file_entries->get_file_entry_by_index == NULL ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume file entries - missing get file entry by index function.", function ); return( NULL ); } if( pyfsntfs_volume_file_entries->file_entry_index < 0 ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume file entries - invalid file entry index.", function ); return( NULL ); } if( pyfsntfs_volume_file_entries->number_of_file_entries < 0 ) { PyErr_Format( PyExc_ValueError, "%s: invalid volume file entries - invalid number of file entries.", function ); return( NULL ); } if( pyfsntfs_volume_file_entries->file_entry_index >= pyfsntfs_volume_file_entries->number_of_file_entries ) { PyErr_SetNone( PyExc_StopIteration ); return( NULL ); } file_entry_object = pyfsntfs_volume_file_entries->get_file_entry_by_index( pyfsntfs_volume_file_entries->volume_object, pyfsntfs_volume_file_entries->file_entry_index ); if( file_entry_object != NULL ) { pyfsntfs_volume_file_entries->file_entry_index++; } return( file_entry_object ); } ================================================ FILE: pyfsntfs/pyfsntfs_volume_file_entries.h ================================================ /* * Python object definition of the volume file entries sequence and iterator * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_VOLUME_FILE_ENTRIES_H ) #define _PYFSNTFS_VOLUME_FILE_ENTRIES_H #include #include #include "pyfsntfs_file_entry.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #include "pyfsntfs_volume.h" #if defined( __cplusplus ) extern "C" { #endif typedef struct pyfsntfs_volume_file_entries pyfsntfs_volume_file_entries_t; struct pyfsntfs_volume_file_entries { /* Python object initialization */ PyObject_HEAD /* The volume object */ pyfsntfs_volume_t *volume_object; /* The get file entry by index callback function */ PyObject* (*get_file_entry_by_index)( pyfsntfs_volume_t *volume_object, uint64_t file_entry_index ); /* The (current) file entry index */ uint64_t file_entry_index; /* The number of file entries */ uint64_t number_of_file_entries; }; extern PyTypeObject pyfsntfs_volume_file_entries_type_object; PyObject *pyfsntfs_volume_file_entries_new( pyfsntfs_volume_t *volume, PyObject* (*get_file_entry_by_index)( pyfsntfs_volume_t *volume_object, uint64_t file_entry_index ), uint64_t number_of_file_entries ); int pyfsntfs_volume_file_entries_init( pyfsntfs_volume_file_entries_t *pyfsntfs_volume_file_entries ); void pyfsntfs_volume_file_entries_free( pyfsntfs_volume_file_entries_t *pyfsntfs_volume_file_entries ); Py_ssize_t pyfsntfs_volume_file_entries_len( pyfsntfs_volume_file_entries_t *pyfsntfs_volume_file_entries ); PyObject *pyfsntfs_volume_file_entries_getitem( pyfsntfs_volume_file_entries_t *pyfsntfs_volume_file_entries, Py_ssize_t item_index ); PyObject *pyfsntfs_volume_file_entries_iter( pyfsntfs_volume_file_entries_t *pyfsntfs_volume_file_entries ); PyObject *pyfsntfs_volume_file_entries_iternext( pyfsntfs_volume_file_entries_t *pyfsntfs_volume_file_entries ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_VOLUME_FILE_ENTRIES_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_volume_information_attribute.c ================================================ /* * Python object definition of the libfsntfs volume information attribute * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_attribute.h" #include "pyfsntfs_datetime.h" #include "pyfsntfs_error.h" #include "pyfsntfs_integer.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #include "pyfsntfs_unused.h" #include "pyfsntfs_volume_information_attribute.h" PyMethodDef pyfsntfs_volume_information_attribute_object_methods[] = { /* Functions to access the attribute values */ { "get_version", (PyCFunction) pyfsntfs_volume_information_attribute_get_version, METH_NOARGS, "get_version() -> Unicode string or None\n" "\n" "Returns the version." }, { "get_flags", (PyCFunction) pyfsntfs_volume_information_attribute_get_flags, METH_NOARGS, "get_flags() -> Integer\n" "\n" "Returns the flags." }, /* Sentinel */ { NULL, NULL, 0, NULL } }; PyGetSetDef pyfsntfs_volume_information_attribute_object_get_set_definitions[] = { { "version", (getter) pyfsntfs_volume_information_attribute_get_version, (setter) 0, "The version.", NULL }, { "flags", (getter) pyfsntfs_volume_information_attribute_get_flags, (setter) 0, "The flags.", NULL }, /* Sentinel */ { NULL, NULL, NULL, NULL, NULL } }; PyTypeObject pyfsntfs_volume_information_attribute_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs.volume_information_attribute", /* tp_basicsize */ sizeof( pyfsntfs_attribute_t ), /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_doc */ "pyfsntfs volume information attribute object (wraps libfsntfs_attribute_t type LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_INFORMATION)", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ pyfsntfs_volume_information_attribute_object_methods, /* tp_members */ 0, /* tp_getset */ pyfsntfs_volume_information_attribute_object_get_set_definitions, /* tp_base */ &pyfsntfs_attribute_type_object, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Retrieves the version * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_information_attribute_get_version( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { char version_string[ 4 ]; PyObject *string_object = NULL; libcerror_error_t *error = NULL; static char *function = "pyfsntfs_volume_information_attribute_get_version"; uint8_t major_version = 0; uint8_t minor_version = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_information_attribute_get_version( pyfsntfs_attribute->attribute, &major_version, &minor_version, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve version.", function ); libcerror_error_free( &error ); return( NULL ); } else if( result == 0 ) { Py_IncRef( Py_None ); return( Py_None ); } if( major_version > 9 ) { PyErr_Format( PyExc_TypeError, "%s: invalid major version value out of bounds.", function ); return( NULL ); } if( minor_version > 9 ) { PyErr_Format( PyExc_TypeError, "%s: invalid minor version value out of bounds.", function ); return( NULL ); } version_string[ 0 ] = '0' + major_version; version_string[ 1 ] = '.'; version_string[ 2 ] = '0' + minor_version; version_string[ 3 ] = 0; /* Pass the string length to PyUnicode_DecodeUTF8 * otherwise it makes the end of string character is part * of the string */ string_object = PyUnicode_DecodeUTF8( version_string, (Py_ssize_t) 3, NULL ); return( string_object ); } /* Retrieves the flags * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_information_attribute_get_flags( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *integer_object = NULL; static char *function = "pyfsntfs_volume_information_attribute_get_flags"; uint16_t flags = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_information_attribute_get_flags( pyfsntfs_attribute->attribute, &flags, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve flags.", function ); libcerror_error_free( &error ); return( NULL ); } integer_object = pyfsntfs_integer_unsigned_new_from_64bit( (uint64_t) flags ); return( integer_object ); } ================================================ FILE: pyfsntfs/pyfsntfs_volume_information_attribute.h ================================================ /* * Python object definition of the libfsntfs volume information attribute * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_VOLUME_INFORMATION_ATTRIBUTE_H ) #define _PYFSNTFS_VOLUME_INFORMATION_ATTRIBUTE_H #include #include #include "pyfsntfs_attribute.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif extern PyMethodDef pyfsntfs_volume_information_attribute_object_methods[]; extern PyTypeObject pyfsntfs_volume_information_attribute_type_object; PyObject *pyfsntfs_volume_information_attribute_get_version( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); PyObject *pyfsntfs_volume_information_attribute_get_flags( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_VOLUME_INFORMATION_ATTRIBUTE_H ) */ ================================================ FILE: pyfsntfs/pyfsntfs_volume_name_attribute.c ================================================ /* * Python object definition of the libfsntfs volume name attribute * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI ) #include #endif #include "pyfsntfs_attribute.h" #include "pyfsntfs_error.h" #include "pyfsntfs_integer.h" #include "pyfsntfs_libcerror.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #include "pyfsntfs_unused.h" #include "pyfsntfs_volume_name_attribute.h" PyMethodDef pyfsntfs_volume_name_attribute_object_methods[] = { /* Functions to access the attribute values */ { "get_name", (PyCFunction) pyfsntfs_volume_name_attribute_get_name, METH_NOARGS, "get_name() -> Unicode string or None\n" "\n" "Returns the name." }, /* Sentinel */ { NULL, NULL, 0, NULL } }; PyGetSetDef pyfsntfs_volume_name_attribute_object_get_set_definitions[] = { { "name", (getter) pyfsntfs_volume_name_attribute_get_name, (setter) 0, "The name.", NULL }, /* Sentinel */ { NULL, NULL, NULL, NULL, NULL } }; PyTypeObject pyfsntfs_volume_name_attribute_type_object = { PyVarObject_HEAD_INIT( NULL, 0 ) /* tp_name */ "pyfsntfs.volume_name_attribute", /* tp_basicsize */ sizeof( pyfsntfs_attribute_t ), /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_doc */ "pyfsntfs volume name attribute object (wraps libfsntfs_attribute_t type LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME)", /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ pyfsntfs_volume_name_attribute_object_methods, /* tp_members */ 0, /* tp_getset */ pyfsntfs_volume_name_attribute_object_get_set_definitions, /* tp_base */ &pyfsntfs_attribute_type_object, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ NULL, /* tp_mro */ NULL, /* tp_cache */ NULL, /* tp_subclasses */ NULL, /* tp_weaklist */ NULL, /* tp_del */ 0 }; /* Retrieves the name * Returns a Python object if successful or NULL on error */ PyObject *pyfsntfs_volume_name_attribute_get_name( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments PYFSNTFS_ATTRIBUTE_UNUSED ) { libcerror_error_t *error = NULL; PyObject *string_object = NULL; uint8_t *name = NULL; static char *function = "pyfsntfs_volume_name_attribute_get_name"; size_t name_size = 0; int result = 0; PYFSNTFS_UNREFERENCED_PARAMETER( arguments ) if( pyfsntfs_attribute == NULL ) { PyErr_Format( PyExc_TypeError, "%s: invalid attribute.", function ); return( NULL ); } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_name_attribute_get_utf8_name_size( pyfsntfs_attribute->attribute, &name_size, &error ); Py_END_ALLOW_THREADS if( result == -1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve name size.", function ); libcerror_error_free( &error ); goto on_error; } else if( ( result == 0 ) || ( name_size == 0 ) ) { Py_IncRef( Py_None ); return( Py_None ); } name = (uint8_t *) PyMem_Malloc( sizeof( uint8_t ) * name_size ); if( name == NULL ) { PyErr_Format( PyExc_MemoryError, "%s: unable to create name.", function ); goto on_error; } Py_BEGIN_ALLOW_THREADS result = libfsntfs_volume_name_attribute_get_utf8_name( pyfsntfs_attribute->attribute, name, name_size, &error ); Py_END_ALLOW_THREADS if( result != 1 ) { pyfsntfs_error_raise( error, PyExc_IOError, "%s: unable to retrieve name.", function ); libcerror_error_free( &error ); goto on_error; } /* Pass the string length to PyUnicode_DecodeUTF8 * otherwise it makes the end of string character is part * of the string */ string_object = PyUnicode_DecodeUTF8( (char *) name, (Py_ssize_t) name_size - 1, NULL ); PyMem_Free( name ); return( string_object ); on_error: if( name != NULL ) { PyMem_Free( name ); } return( NULL ); } ================================================ FILE: pyfsntfs/pyfsntfs_volume_name_attribute.h ================================================ /* * Python object definition of the libfsntfs volume name attribute * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _PYFSNTFS_VOLUME_NAME_ATTRIBUTE_H ) #define _PYFSNTFS_VOLUME_NAME_ATTRIBUTE_H #include #include #include "pyfsntfs_attribute.h" #include "pyfsntfs_libfsntfs.h" #include "pyfsntfs_python.h" #if defined( __cplusplus ) extern "C" { #endif extern PyMethodDef pyfsntfs_volume_name_attribute_object_methods[]; extern PyTypeObject pyfsntfs_volume_name_attribute_type_object; PyObject *pyfsntfs_volume_name_attribute_get_name( pyfsntfs_attribute_t *pyfsntfs_attribute, PyObject *arguments ); #if defined( __cplusplus ) } #endif #endif /* !defined( _PYFSNTFS_VOLUME_NAME_ATTRIBUTE_H ) */ ================================================ FILE: pyproject.toml ================================================ [build-system] requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta" ================================================ FILE: runtests.ps1 ================================================ # Script that runs the tests # # Version: 20220103 $ExitSuccess = 0 $ExitFailure = 1 $ExitIgnore = 77 Set-Location -Path "tests" $Result = ${ExitSuccess} $Lines = Get-Content "Makefile.am" $InTests = $FALSE Foreach (${Line} in ${Lines}) { If (${InTests}) { If (-Not ${Line}) { ${InTests} = $FALSE Continue } ${Line} = ${Line}.TrimStart() If (${Line}.EndsWith(" \")) { ${Line} = ${Line}.Substring(0, ${Line}.Length - 2) } If (-Not (${Line}.EndsWith(".sh"))) { Continue } ${Line} = ${Line}.Substring(0, ${Line}.Length - 3) ${Line} = ".\${Line}.ps1" Try { Invoke-Expression ${Line} } Catch { $LastExitCode = ${ExitIgnore} } If (${LastExitCode} -eq ${ExitFailure}) { $Result = ${ExitFailure} Write-Host "FAIL" -foreground Red -nonewline } ElseIf (${LastExitCode} -eq ${ExitIgnore}) { Write-Host "SKIP" -foreground Cyan -nonewline } Else { Write-Host "PASS" -foreground Green -nonewline } Write-Host ": ${Line}" } ElseIf (${Line}.StartsWith("TESTS = ")) { ${InTests} = $TRUE } } Set-Location -Path ".." Exit ${Result} ================================================ FILE: runtests.sh ================================================ #!/usr/bin/env bash # Script that runs the tests # # Version: 20231119 EXIT_SUCCESS=0; EXIT_FAILURE=1; run_configure_make() { local CONFIGURE_OPTIONS=$@; ./configure ${CONFIGURE_OPTIONS[@]}; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then echo "Running: './configure' failed"; return ${RESULT}; fi make clean > /dev/null; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then echo "Running: 'make clean' failed"; return ${RESULT}; fi make > /dev/null; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then echo "Running: 'make' failed"; return ${RESULT}; fi return ${EXIT_SUCCESS}; } run_configure_make_check() { run_configure_make $@; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then return ${RESULT}; fi make check CHECK_WITH_STDERR=1; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then echo "Running: 'make check' failed"; if test -f tests/test-suite.log; then cat tests/test-suite.log; fi return ${RESULT}; fi return ${EXIT_SUCCESS}; } run_configure_make_check_with_asan() { local LDCONFIG=`which ldconfig 2> /dev/null`; if test -z ${LDCONFIG} || test ! -x ${LDCONFIG}; then return ${EXIT_SUCCESS}; fi local LIBASAN=`ldconfig -p | grep libasan | sed 's/^.* => //' | sort | tail -n 1`; if test -z ${LIBASAN} || test ! -f ${LIBASAN}; then return ${EXIT_SUCCESS}; fi # Using libasan is platform dependent. export CPPFLAGS="-DHAVE_ASAN"; export CFLAGS="-fno-omit-frame-pointer -fsanitize=address -g"; export LDFLAGS="-fsanitize=address -g"; if test -z ${CC} || test ${CC} != "clang"; then LDFLAGS="${LDFLAGS} -lasan"; fi run_configure_make $@; RESULT=$?; export CPPFLAGS=; export CFLAGS=; export LDFLAGS=; if test ${RESULT} -ne ${EXIT_SUCCESS}; then return ${RESULT}; fi make check CHECK_WITH_ASAN=1 CHECK_WITH_STDERR=1; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then echo "Running: 'make check' failed"; if test -f tests/test-suite.log; then cat tests/test-suite.log; fi return ${RESULT}; fi return ${RESULT}; } run_configure_make_check_with_coverage() { # Disable optimization so we can hook malloc and realloc. export CPPFLAGS="-DOPTIMIZATION_DISABLED"; export CFLAGS="--coverage -O0"; export LDFLAGS="--coverage"; # Disable creating a shared library so we can hook memset. run_configure_make_check $@; RESULT=$?; export CPPFLAGS=; export CFLAGS=; export LDFLAGS=; return ${RESULT}; } run_configure_make_check_python() { run_configure_make $@; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then return ${RESULT}; fi make check CHECK_WITH_STDERR=1 SKIP_LIBRARY_TESTS=1 SKIP_TOOLS_TESTS=1; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then echo "Running: 'make check' failed"; if test -f tests/test-suite.log; then cat tests/test-suite.log; fi return ${RESULT}; fi return ${EXIT_SUCCESS}; } run_setup_py_tests() { # Skip this test when running Cygwin on AppVeyor. if test -n "${APPVEYOR}" && test ${TARGET} = "cygwin"; then echo "Running: 'setup.py build' skipped"; return ${EXIT_SUCCESS}; fi PYTHON=$1; ${PYTHON} setup.py build; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then echo "Running: 'setup.py build' failed"; return ${RESULT}; fi return ${EXIT_SUCCESS}; } PROJECT_NAME=`basename $PWD`; CONFIGURE_HELP=`./configure --help`; echo "${CONFIGURE_HELP}" | grep -- '--enable-wide-character-type' > /dev/null; HAVE_ENABLE_WIDE_CHARACTER_TYPE=$?; echo "${CONFIGURE_HELP}" | grep -- '--enable-verbose-output' > /dev/null; HAVE_ENABLE_VERBOSE_OUTPUT=$?; echo "${CONFIGURE_HELP}" | grep -- '--enable-debug-output' > /dev/null; HAVE_ENABLE_DEBUG_OUTPUT=$?; echo "${CONFIGURE_HELP}" | grep -- '--with-bzip2' > /dev/null; HAVE_WITH_BZIP2=$?; echo "${CONFIGURE_HELP}" | grep -- '--with-libfuse' > /dev/null; HAVE_WITH_LIBFUSE=$?; echo "${CONFIGURE_HELP}" | grep -- '--with-lzma' > /dev/null; HAVE_WITH_LZMA=$?; echo "${CONFIGURE_HELP}" | grep -- '--with-pthread' > /dev/null; HAVE_WITH_PTHREAD=$?; echo "${CONFIGURE_HELP}" | grep -- '--with-openssl' > /dev/null; HAVE_WITH_OPENSSL=$?; echo "${CONFIGURE_HELP}" | grep -- '--with-zlib' > /dev/null; HAVE_WITH_ZLIB=$?; echo "${CONFIGURE_HELP}" | grep -- '--enable-python' > /dev/null; HAVE_ENABLE_PYTHON=$?; echo "${CONFIGURE_HELP}" | grep -- '--enable-static-executables' > /dev/null; HAVE_ENABLE_STATIC_EXECUTABLES=$?; PYTHON_CONFIG=""; if test -x /usr/bin/whereis; then PYTHON_CONFIG=`/usr/bin/whereis python-config | sed 's/^.*:[ ]*//' 2> /dev/null`; fi # Test "./configure && make && make check" without options. run_configure_make_check; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then exit ${EXIT_FAILURE}; fi if test ${HAVE_ENABLE_VERBOSE_OUTPUT} -eq 0 && test ${HAVE_ENABLE_DEBUG_OUTPUT} -eq 0; then # Test "./configure && make && make check" with verbose and debug output. run_configure_make_check "--enable-verbose-output --enable-debug-output"; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then exit ${EXIT_FAILURE}; fi fi if test ${HAVE_WITH_PTHREAD} -eq 0 && test ${PROJECT_NAME} != "libcthreads"; then # Test "./configure && make && make check" without multi-threading support. run_configure_make_check "--with-pthread=no"; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then exit ${EXIT_FAILURE}; fi fi if test ${HAVE_WITH_ZLIB} -eq 0; then # Test "./configure && make && make check" with fallback zlib implementation. run_configure_make_check "--with-zlib=no"; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then exit ${EXIT_FAILURE}; fi fi if test ${HAVE_WITH_OPENSSL} -eq 0; then # Test "./configure && make && make check" with fallback crypto implementation. run_configure_make_check "--with-openssl=no"; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then exit ${EXIT_FAILURE}; fi # Test "./configure && make && make check" with OpenSSL non-EVP implementation. run_configure_make_check "--enable-openssl-evp-cipher=no --enable-openssl-evp-md=no"; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then exit ${EXIT_FAILURE}; fi # Test "./configure && make && make check" with OpenSSL EVP implementation. run_configure_make_check "--enable-openssl-evp-cipher=yes --enable-openssl-evp-md=yes"; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then exit ${EXIT_FAILURE}; fi fi if test ${HAVE_ENABLE_PYTHON} -eq 0 && test -n "${PYTHON_CONFIG}"; then run_configure_make_check_python "--enable-python"; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then exit ${EXIT_FAILURE}; fi PYTHON=`which python 2> /dev/null`; if test -f "setup.py" && ! run_setup_py_tests ${PYTHON}; then exit ${EXIT_FAILURE}; fi fi if test ${HAVE_ENABLE_STATIC_EXECUTABLES} -eq 0; then CONFIGURE_OPTIONS="--enable-static-executables --enable-multi-threading-support=no"; if test ${HAVE_WITH_BZIP2} -eq 0; then CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS} --with-bzip2=no"; fi if test ${HAVE_WITH_LIBFUSE} -eq 0; then CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS} --with-libfuse=no"; fi if test ${HAVE_WITH_LZMA} -eq 0; then CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS} --with-lzma=no"; fi if test ${HAVE_WITH_OPENSSL} -eq 0; then CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS} --with-openssl=no"; fi if test ${HAVE_WITH_ZLIB} -eq 0; then CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS} --with-zlib=no"; fi run_configure_make_check ${CONFIGURE_OPTIONS}; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then exit ${EXIT_FAILURE}; fi fi # Run tests with asan. CONFIGURE_OPTIONS=""; if test ${HAVE_ENABLE_WIDE_CHARACTER_TYPE} -eq 0; then CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS} --enable-wide-character-type"; fi if test ${HAVE_WITH_BZIP2} -eq 0; then CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS} --with-bzip2=no"; fi if test ${HAVE_WITH_LZMA} -eq 0; then CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS} --with-lzma=no"; fi if test ${HAVE_WITH_OPENSSL} -eq 0; then CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS} --with-openssl=no"; fi if test ${HAVE_WITH_ZLIB} -eq 0; then CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS} --with-zlib=no"; fi if test ${HAVE_ENABLE_PYTHON} -eq 0 && test -n "${PYTHON_CONFIG}"; then # Issue with running the python bindings with asan disabled for now. # CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS} --enable-python"; CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS}"; fi run_configure_make_check_with_asan ${CONFIGURE_OPTIONS}; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then exit ${EXIT_FAILURE}; fi # Run tests with coverage. CONFIGURE_OPTIONS="--enable-shared=no"; if test ${HAVE_ENABLE_WIDE_CHARACTER_TYPE} -eq 0; then CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS} --enable-wide-character-type"; fi if test ${HAVE_WITH_BZIP2} -eq 0; then CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS} --with-bzip2=no"; fi if test ${HAVE_WITH_LZMA} -eq 0; then CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS} --with-lzma=no"; fi if test ${HAVE_WITH_OPENSSL} -eq 0; then CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS} --with-openssl=no"; fi if test ${HAVE_WITH_ZLIB} -eq 0; then CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS} --with-zlib=no"; fi run_configure_make_check_with_coverage ${CONFIGURE_OPTIONS}; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then exit ${EXIT_FAILURE}; fi exit ${EXIT_SUCCESS}; ================================================ FILE: setup.cfg.in ================================================ [metadata] name = libfsntfs-python version = @VERSION@ description = Python bindings module for libfsntfs long_description = Python bindings module for libfsntfs long_description_content_type = text/plain author = Joachim Metz author_email = joachim.metz@gmail.com license = GNU Lesser General Public License v3 or later (LGPLv3+) license_files = COPYING* classifiers = Development Status :: 2 - Pre-Alpha Programming Language :: Python [options] python_requires = >=3.10 ================================================ FILE: setup.py ================================================ #!/usr/bin/env python # # Script to build and install Python-bindings. # Version: 20251125 import copy import datetime import glob import gzip import platform import os import shlex import shutil import subprocess import sys import tarfile import zipfile from setuptools import Extension from setuptools import setup from setuptools._distutils.ccompiler import new_compiler from setuptools.command.build_ext import build_ext from setuptools.command.sdist import sdist if (sys.version_info[0], sys.version_info[1]) < (3, 7): print(("Unsupported Python version: {0:s}, version 3.7 or higher " "required.").format(sys.version)) sys.exit(1) class custom_build_ext(build_ext): """Custom handler for the build_ext command.""" def _RunCommand(self, command): """Runs the command.""" arguments = shlex.split(command) process = subprocess.Popen( arguments, stderr=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True) if not process: raise RuntimeError("Running: {0:s} failed.".format(command)) output, error = process.communicate() if process.returncode != 0: error = "\n".join(error.split("\n")[-5:]) raise RuntimeError("Running: {0:s} failed with error:\n{1:s}.".format( command, error)) return output def build_extensions(self): """Set up the build extensions.""" # TODO: move build customization here? build_ext.build_extensions(self) def run(self): """Runs the build extension.""" compiler = new_compiler(compiler=self.compiler) if compiler.compiler_type == "msvc": self.define = [ ("_CRT_SECURE_NO_WARNINGS", ""), ("UNICODE", ""), ] else: command = "sh configure --disable-nls --disable-shared-libs" output = self._RunCommand(command) print_line = False for line in output.split("\n"): line = line.rstrip() if line == "configure:": print_line = True if print_line: print(line) self.define = [ ("HAVE_CONFIG_H", ""), ] build_ext.run(self) class custom_sdist(sdist): """Custom handler for the sdist command.""" def run(self): """Builds a source distribution (sdist) package.""" if self.formats != ["gztar"] and self.formats != ["zip"]: print("'setup.py sdist' unsupported format.") sys.exit(1) if glob.glob("*.tar.gz"): print("'setup.py sdist' remove existing *.tar.gz files from " "source directory.") sys.exit(1) command = "make dist" exit_code = subprocess.call(command, shell=True) if exit_code != 0: raise RuntimeError("Running: {0:s} failed.".format(command)) if not os.path.exists(self.dist_dir): os.mkdir(self.dist_dir) source_package_file = glob.glob("*.tar.gz")[0] source_package_prefix, _, source_package_suffix = ( source_package_file.partition("-")) sdist_package_file = "{0:s}_python-{1:s}".format( source_package_prefix, source_package_suffix) sdist_package_file = os.path.join(self.dist_dir, sdist_package_file) os.rename(source_package_file, sdist_package_file) # Create and add the PKG-INFO file to the source package. with gzip.open(sdist_package_file, "rb") as input_file: with open(sdist_package_file[:-3], "wb") as output_file: shutil.copyfileobj(input_file, output_file) os.remove(sdist_package_file) self.distribution.metadata.write_pkg_info(".") pkg_info_path = "{0:s}-{1:s}/PKG-INFO".format( source_package_prefix, source_package_suffix[:-7]) with tarfile.open(sdist_package_file[:-3], "a:") as tar_file: tar_file.add("PKG-INFO", arcname=pkg_info_path) os.remove("PKG-INFO") with open(sdist_package_file[:-3], "rb") as input_file: with gzip.open(sdist_package_file, "wb") as output_file: shutil.copyfileobj(input_file, output_file) os.remove(sdist_package_file[:-3]) # Convert the .tar.gz into a .zip if self.formats == ["zip"]: zip_sdist_package_file = "{0:s}.zip".format(sdist_package_file[:-7]) with tarfile.open(sdist_package_file, "r|gz") as tar_file: with zipfile.ZipFile( zip_sdist_package_file, "w", zipfile.ZIP_DEFLATED) as zip_file: for tar_file_entry in tar_file: file_entry = tar_file.extractfile(tar_file_entry) if tar_file_entry.isfile(): modification_time = datetime.datetime.fromtimestamp( tar_file_entry.mtime) zip_modification_time = ( modification_time.year, modification_time.month, modification_time.day, modification_time.hour, modification_time.minute, modification_time.second) zip_info = zipfile.ZipInfo( date_time=zip_modification_time, filename=tar_file_entry.name) zip_info.external_attr = (tar_file_entry.mode & 0xff) << 16 file_data = file_entry.read() zip_file.writestr(zip_info, file_data) os.remove(sdist_package_file) sdist_package_file = zip_sdist_package_file # Inform setuptools what files were created. dist_files = getattr(self.distribution, "dist_files", []) dist_files.append(("sdist", "", sdist_package_file)) class ProjectInformation(object): """Project information.""" def __init__(self): """Initializes project information.""" super(ProjectInformation, self).__init__() self.include_directories = [] self.library_name = None self.library_names = [] self.library_version = None self._ReadConfigureAc() self._ReadMakefileAm() @property def module_name(self): """The Python module name.""" return "py{0:s}".format(self.library_name[3:]) def _ReadConfigureAc(self): """Reads configure.ac to initialize the project information.""" with open("configure.ac", "r", encoding="utf-8") as file_object: found_ac_init = False found_library_name = False for line in file_object.readlines(): line = line.strip() if found_library_name: library_version = line[1:-2] self.library_version = library_version break elif found_ac_init: library_name = line[1:-2] self.library_name = library_name found_library_name = True elif line.startswith("AC_INIT"): found_ac_init = True if not self.library_name or not self.library_version: raise RuntimeError( "Unable to find library name and version in: configure.ac") def _ReadMakefileAm(self): """Reads Makefile.am to initialize the project information.""" if not self.library_name: raise RuntimeError("Missing library name") with open("Makefile.am", "r", encoding="utf-8") as file_object: found_subdirs = False for line in file_object.readlines(): line = line.strip() if found_subdirs: library_name, _, _ = line.partition(" ") self.include_directories.append(library_name) if library_name.startswith("lib"): self.library_names.append(library_name) if library_name == self.library_name: break elif line.startswith("SUBDIRS"): found_subdirs = True if not self.include_directories or not self.library_names: raise RuntimeError( "Unable to find include directories and library names in: " "Makefile.am") project_information = ProjectInformation() CMDCLASS = { "build_ext": custom_build_ext, "sdist": custom_sdist} SOURCES = [] # TODO: replace by detection of MSC DEFINE_MACROS = [] if platform.system() == "Windows": DEFINE_MACROS.append(("WINVER", "0x0501")) # TODO: determine how to handle third party DLLs. for library_name in project_information.library_names: if library_name != project_information.library_name: definition = "HAVE_LOCAL_{0:s}".format(library_name.upper()) DEFINE_MACROS.append((definition, "")) # Put everything inside the Python module to prevent issues with finding # shared libaries since pip does not integrate well with the system package # management. for library_name in project_information.library_names: for source_file in glob.glob(os.path.join(library_name, "*.[ly]")): generated_source_file = "{0:s}.c".format(source_file[:-2]) if not os.path.exists(generated_source_file): raise RuntimeError("Missing generated source file: {0:s}".format( generated_source_file)) source_files = glob.glob(os.path.join(library_name, "*.c")) SOURCES.extend(source_files) source_files = glob.glob(os.path.join(project_information.module_name, "*.c")) SOURCES.extend(source_files) # TODO: find a way to detect missing python.h # e.g. on Ubuntu python-dev is not installed by python-pip setup_args = dict( cmdclass=CMDCLASS, ext_modules=[ Extension( project_information.module_name, define_macros=DEFINE_MACROS, include_dirs=project_information.include_directories, libraries=[], library_dirs=[], sources=SOURCES ) ] ) setup(**setup_args) ================================================ FILE: syncdokan.ps1 ================================================ # Script that synchronizes dokan # # Version: 20190810 Param ( [switch]$UseHead = $false, [switch]$UseLegacyVersion = $false ) $Git = "git" If (${UseLegacyVersion}) { # Patched version of dokan 0.6.0 $GitUrl = "https://github.com/joachimmetz/dokan.git" $Destination = "..\dokan" } Else { $GitUrl = "https://github.com/dokan-dev/dokany.git" $Destination = "..\dokany" } # PowerShell will raise NativeCommandError if git writes to stdout or stderr # therefore 2>&1 is added and the output is stored in a variable. $Output = Invoke-Expression -Command "${Git} clone ${GitUrl} ${Destination} 2>&1" Push-Location ${Destination} Try { $Output = Invoke-Expression -Command "${Git} fetch --quiet --all --tags --prune 2>&1" $LatestTag = Invoke-Expression -Command "${Git} describe --tags --abbrev=0 2>&1" If (${LatestTag} -and -not ${UseHead}) { Write-Host "Synchronizing: dokan from ${GitUrl} tag ${LatestTag}" $Output = Invoke-Expression -Command "${Git} checkout --quiet tags/${LatestTag} 2>&1" } Else { Write-Host "Synchronizing: dokan from ${GitUrl} HEAD" } If (-Not ${UseLegacyVersion}) { # AppVeyor does not come with platform toolset version 142 ((Get-Content -Path "..\dokany\dokan\dokan.vcxproj" -Raw) -Replace 'v142','v141') | Set-Content -Path "..\dokany\dokan\dokan.vcxproj" } } Finally { Pop-Location } ================================================ FILE: synclibs.ps1 ================================================ # Script that synchronizes the local library dependencies # # Version: 20180125 Param ( [switch]$UseHead = $false ) $GitUrlPrefix = "https://github.com/libyal" $LocalLibs = "libbfio libcdata libcerror libcfile libclocale libcnotify libcpath libcsplit libcthreads libfcache libfdata libfdatetime libfguid libfusn libfwnt libhmac libuna" $LocalLibs = ${LocalLibs} -split " " $Git = "git" $WinFlex = "..\win_flex_bison\win_flex.exe" $WinBison = "..\win_flex_bison\win_bison.exe" ForEach (${LocalLib} in ${LocalLibs}) { # Split will return an array of a single empty string when LocalLibs is empty. If (-Not (${LocalLib})) { Continue } $GitUrl = "${GitUrlPrefix}/${LocalLib}.git" # PowerShell will raise NativeCommandError if git writes to stdout or stderr # therefore 2>&1 is added and the output is stored in a variable. $Output = Invoke-Expression -Command "${Git} clone ${GitUrl} ${LocalLib}-${pid} 2>&1" Push-Location "${LocalLib}-${pid}" Try { $Output = Invoke-Expression -Command "${Git} fetch --quiet --all --tags --prune 2>&1" $LatestTag = Invoke-Expression -Command "${Git} describe --tags --abbrev=0 2>&1" If (${LatestTag} -and -not ${UseHead}) { Write-Host "Synchronizing: ${LocalLib} from ${GitUrl} tag ${LatestTag}" $Output = Invoke-Expression -Command "${Git} checkout --quiet tags/${LatestTag} 2>&1" } Else { Write-Host "Synchronizing: ${LocalLib} from ${GitUrl} HEAD" } } Finally { Pop-Location } If (Test-Path ${LocalLib}-${pid}) { $LocalLibVersion = Get-Content -Path ${LocalLib}-${pid}\configure.ac | select -skip 4 -first 1 | % { $_ -Replace " \[","" } | % { $_ -Replace "\],","" } If (Test-Path ${LocalLib}) { Remove-Item -Path ${LocalLib} -Force -Recurse } New-Item -ItemType directory -Path ${LocalLib} -Force | Out-Null If (Test-Path ${LocalLib}) { Copy-Item -Path ${LocalLib}-${pid}\${LocalLib}\*.[chly] -Destination ${LocalLib}\ Get-Content -Path ${LocalLib}-${pid}\${LocalLib}\${LocalLib}_definitions.h.in | % { $_ -Replace "@VERSION@",${LocalLibVersion} } > ${LocalLib}\${LocalLib}_definitions.h } Remove-Item -Path ${LocalLib}-${pid} -Force -Recurse $NamePrefix = "" ForEach (${DirectoryElement} in Get-ChildItem -Path "${LocalLib}\*.l") { $OutputFile = ${DirectoryElement} -Replace ".l$",".c" $NamePrefix = Split-Path -path ${DirectoryElement} -leaf $NamePrefix = ${NamePrefix} -Replace "^${LocalLib}_","" $NamePrefix = ${NamePrefix} -Replace ".l$","_" # PowerShell will raise NativeCommandError if win_flex writes to stdout or stderr # therefore 2>&1 is added and the output is stored in a variable. $Output = Invoke-Expression -Command "& '${WinFlex}' -Cf ${DirectoryElement} 2>&1" Write-Host ${Output} # Moving manually sicne win_flex -o does not provide the expected behavior. Move-Item "lex.yy.c" ${OutputFile} -force } ForEach (${DirectoryElement} in Get-ChildItem -Path "${LocalLib}\*.y") { $OutputFile = ${DirectoryElement} -Replace ".y$",".c" # PowerShell will raise NativeCommandError if win_bison writes to stdout or stderr # therefore 2>&1 is added and the output is stored in a variable. $Output = Invoke-Expression -Command "& '${WinBison}' -d -v -l -p ${NamePrefix} -o ${OutputFile} ${DirectoryElement} 2>&1" Write-Host ${Output} } } } ================================================ FILE: synclibs.sh ================================================ #!/bin/sh # Script that synchronizes the local library dependencies # # Version: 20240414 EXIT_SUCCESS=0; EXIT_FAILURE=1; GIT_URL_PREFIX="https://github.com/libyal"; LOCAL_LIBS="libbfio libcdata libcerror libcfile libclocale libcnotify libcpath libcsplit libcthreads libfcache libfdata libfdatetime libfguid libfusn libfwnt libhmac libuna"; OLDIFS=$IFS; IFS=" "; for LOCAL_LIB in ${LOCAL_LIBS}; do GIT_URL="${GIT_URL_PREFIX}/${LOCAL_LIB}.git"; git clone --quiet ${GIT_URL} ${LOCAL_LIB}-$$; if ! test -d ${LOCAL_LIB}-$$; then echo "Unable to git clone: ${GIT_URL}"; IFS=$OLDIFS; exit ${EXIT_FAILURE}; fi (cd ${LOCAL_LIB}-$$ && git fetch --quiet --all --tags --prune) LATEST_TAG=`cd ${LOCAL_LIB}-$$ && git describe --tags --abbrev=0`; if test -n ${LATEST_TAG} && test "$1" != "--use-head"; then echo "Synchronizing: ${LOCAL_LIB} from ${GIT_URL} tag ${LATEST_TAG}"; (cd ${LOCAL_LIB}-$$ && git checkout --quiet tags/${LATEST_TAG}); else echo "Synchronizing: ${LOCAL_LIB} from ${GIT_URL} HEAD"; fi rm -rf ${LOCAL_LIB}; mkdir ${LOCAL_LIB}; if ! test -d ${LOCAL_LIB}; then echo "Missing directory: ${LOCAL_LIB}"; IFS=$OLDIFS; exit ${EXIT_FAILURE}; fi LOCAL_LIB_UPPER=`echo "${LOCAL_LIB}" | tr "[a-z]" "[A-Z]"`; # Note that sed on FreeBSD does not support \s hence that we use [[:space:]] instead. LOCAL_LIB_VERSION=`grep -A 2 AC_INIT ${LOCAL_LIB}-$$/configure.ac | tail -n 1 | sed 's/^[[:space:]]*\[\([0-9]*\)\],[[:space:]]*$/\1/'`; LOCAL_LIB_MAKEFILE_AM="${LOCAL_LIB}/Makefile.am"; cp ${LOCAL_LIB}-$$/${LOCAL_LIB}/*.[chly] ${LOCAL_LIB}; cp ${LOCAL_LIB}-$$/${LOCAL_LIB_MAKEFILE_AM} ${LOCAL_LIB_MAKEFILE_AM}; # Make the necessary changes to libyal/Makefile.am SED_SCRIPT="/AM_CPPFLAGS = / { i\\ if HAVE_LOCAL_${LOCAL_LIB_UPPER} } /lib_LTLIBRARIES = / { s/lib_LTLIBRARIES/noinst_LTLIBRARIES/ } /${LOCAL_LIB}\.c/ { d } /${LOCAL_LIB}_la_LIBADD/ { :loop1 /${LOCAL_LIB}_la_LDFLAGS/ { N i\\ endif d } /${LOCAL_LIB}_la_LDFLAGS/ !{ N b loop1 } } /${LOCAL_LIB}_la_LDFLAGS/ { N i\\ endif d } /DISTCLEANFILES = / { n /${LOCAL_LIB}_definitions.h/ { d } }"; echo "${SED_SCRIPT}" >> ${LOCAL_LIB}-$$.sed; sed -i'~' -f ${LOCAL_LIB}-$$.sed ${LOCAL_LIB_MAKEFILE_AM}; rm -f ${LOCAL_LIB}-$$.sed; sed -i'~' "/AM_CPPFLAGS = /,/noinst_LTLIBRARIES = / { N; s/\\\\\\n.@${LOCAL_LIB_UPPER}_DLL_EXPORT@//; P; D; }" ${LOCAL_LIB_MAKEFILE_AM}; sed -i'~' "/${LOCAL_LIB}_definitions.h.in/d" ${LOCAL_LIB_MAKEFILE_AM}; sed -i'~' "/${LOCAL_LIB}\\.rc/d" ${LOCAL_LIB_MAKEFILE_AM}; if test ${LOCAL_LIB} = "libfplist"; then # TODO: make this more generic to strip the last \\ sed -i'~' '/EXTRA_DIST = /,/^$/s/libfplist_xml_scanner.c \\/libfplist_xml_scanner.c/' ${LOCAL_LIB_MAKEFILE_AM}; elif test ${LOCAL_LIB} = "libodraw"; then # TODO: make this more generic to strip the last \\ sed -i'~' '/EXTRA_DIST = /,/^$/s/libodraw_cue_scanner.c \\/libodraw_cue_scanner.c/' ${LOCAL_LIB_MAKEFILE_AM}; else sed -i'~' '/EXTRA_DIST = /,/^$/d' ${LOCAL_LIB_MAKEFILE_AM}; fi SED_SCRIPT="/^$/ { x N /endif$/ { a\\ D } }"; echo "${SED_SCRIPT}" >> ${LOCAL_LIB}-$$.sed; sed -i'~' -f ${LOCAL_LIB}-$$.sed ${LOCAL_LIB_MAKEFILE_AM}; rm -f ${LOCAL_LIB}-$$.sed; # Make the necessary changes to libcfile/Makefile.am if test ${LOCAL_LIB} = "libcfile"; then if ! test -f "m4/libuna.m4"; then sed -i'~' 's?@LIBUNA_CPPFLAGS@?-I../libuna -I$(top_srcdir)/libuna?' ${LOCAL_LIB_MAKEFILE_AM}; fi fi # Make the necessary changes to libfplist/Makefile.am if test ${LOCAL_LIB} = "libfplist"; then if test -f "m4/libfdatetime.m4"; then sed -i'~' '/@LIBFGUID_CPPFLAGS@/{h; s/FGUID/FDATETIME/; p; g;}' ${LOCAL_LIB_MAKEFILE_AM}; fi fi # Make the necessary changes to libfvalue/Makefile.am if test ${LOCAL_LIB} = "libfvalue"; then if ! test -f "m4/libfdatetime.m4"; then sed -i'~' '/@LIBFDATETIME_CPPFLAGS@/d' ${LOCAL_LIB_MAKEFILE_AM}; fi if ! test -f "m4/libfguid.m4"; then sed -i'~' '/@LIBFGUID_CPPFLAGS@/d' ${LOCAL_LIB_MAKEFILE_AM}; fi if ! test -f "m4/libfwnt.m4"; then sed -i'~' '/@LIBFWNT_CPPFLAGS@/d' ${LOCAL_LIB_MAKEFILE_AM}; fi if ! test -f "m4/libuna.m4"; then sed -i'~' '/@LIBUNA_CPPFLAGS@/d' ${LOCAL_LIB_MAKEFILE_AM}; fi fi # Make the necessary changes to libsmraw/Makefile.am if test ${LOCAL_LIB} = "libsmraw"; then if test -f "m4/libfdatetime.m4"; then sed -i'~' '/@LIBFVALUE_CPPFLAGS@/{h; s/FVALUE/FDATETIME/; p; g;}' ${LOCAL_LIB_MAKEFILE_AM}; fi if test -f "m4/libfguid.m4"; then sed -i'~' '/@LIBFVALUE_CPPFLAGS@/{h; s/FVALUE/FGUID/; p; g;}' ${LOCAL_LIB_MAKEFILE_AM}; fi fi # Remove libyal/libyal.c rm -f ${LOCAL_LIB}/${LOCAL_LIB}.c; # Make the necessary changes to libyal/libyal_defitions.h cp ${LOCAL_LIB}-$$/${LOCAL_LIB}/${LOCAL_LIB}_definitions.h.in ${LOCAL_LIB}/${LOCAL_LIB}_definitions.h; sed -i'~' "s/@VERSION@/${LOCAL_LIB_VERSION}/" ${LOCAL_LIB}/${LOCAL_LIB}_definitions.h; rm -rf ${LOCAL_LIB}-$$; done IFS=$OLDIFS; exit ${EXIT_SUCCESS}; ================================================ FILE: synctestdata.ps1 ================================================ # Script that synchronizes the local test data # # Version: 20251217 $Repository = "log2timeline/dfvfs" $TestDataPath = "test_data" $TestSet = "public" $TestInputDirectory = "tests/input" $TestFiles = "ntfs.raw" If (-Not (Test-Path ${TestInputDirectory})) { New-Item -Name ${TestInputDirectory} -ItemType "directory" | Out-Null } If (-Not (Test-Path "${TestInputDirectory}\${TestSet}")) { New-Item -Name "${TestInputDirectory}\${TestSet}" -ItemType "directory" | Out-Null } ForEach ($TestFile in ${TestFiles} -split " ") { $Url = "https://raw.githubusercontent.com/${Repository}/refs/heads/main/${TestDataPath}/${TestFile}" Invoke-WebRequest -Uri ${Url} -OutFile "${TestInputDirectory}\${TestSet}\${TestFile}" } ================================================ FILE: synctestdata.sh ================================================ #!/bin/sh # Script that synchronizes the local test data # # Version: 20251217 REPOSITORY="log2timeline/dfvfs"; TEST_DATA_PATH="test_data"; TEST_SET="public"; TEST_INPUT_DIRECTORY="tests/input"; TEST_FILES="ntfs.raw"; mkdir -p "${TEST_INPUT_DIRECTORY}/${TEST_SET}"; for TEST_FILE in ${TEST_FILES}; do URL="https://raw.githubusercontent.com/${REPOSITORY}/refs/heads/main/${TEST_DATA_PATH}/${TEST_FILE}"; curl -L -o "${TEST_INPUT_DIRECTORY}/${TEST_SET}/${TEST_FILE}" ${URL}; done ================================================ FILE: tests/Makefile.am ================================================ AUTOMAKE_OPTIONS = subdir-objects AM_CPPFLAGS = \ -I../include -I$(top_srcdir)/include \ -I../common -I$(top_srcdir)/common \ @LIBCERROR_CPPFLAGS@ \ @LIBCTHREADS_CPPFLAGS@ \ @LIBCDATA_CPPFLAGS@ \ @LIBCLOCALE_CPPFLAGS@ \ @LIBCNOTIFY_CPPFLAGS@ \ @LIBCSPLIT_CPPFLAGS@ \ @LIBUNA_CPPFLAGS@ \ @LIBCFILE_CPPFLAGS@ \ @LIBCPATH_CPPFLAGS@ \ @LIBBFIO_CPPFLAGS@ \ @LIBFCACHE_CPPFLAGS@ \ @LIBFDATA_CPPFLAGS@ \ @LIBFDATETIME_CPPFLAGS@ \ @LIBFGUID_CPPFLAGS@ \ @LIBFUSN_CPPFLAGS@ \ @LIBFWNT_CPPFLAGS@ \ @LIBHMAC_CPPFLAGS@ \ @LIBCRYPTO_CPPFLAGS@ \ @PTHREAD_CPPFLAGS@ \ @LIBFSNTFS_DLL_IMPORT@ if HAVE_PYTHON_TESTS TESTS_PYFSNTFS = \ test_python_module.sh endif TESTS = \ test_library.sh \ test_tools.sh \ test_fsntfsinfo.sh \ test_fsntfsinfo_bodyfile.sh \ $(TESTS_PYFSNTFS) check_SCRIPTS = \ pyfsntfs_test_attribute.py \ pyfsntfs_test_file_entry.py \ pyfsntfs_test_support.py \ pyfsntfs_test_volume.py \ test_fsntfsinfo.sh \ test_fsntfsinfo_bodyfile.sh \ test_library.sh \ test_manpage.sh \ test_python_module.sh \ test_runner.sh \ test_tools.sh EXTRA_DIST = \ $(check_SCRIPTS) check_PROGRAMS = \ fsntfs_test_attribute \ fsntfs_test_attribute_list_entry \ fsntfs_test_bitmap_values \ fsntfs_test_buffer_data_handle \ fsntfs_test_cluster_block \ fsntfs_test_cluster_block_data \ fsntfs_test_cluster_block_stream \ fsntfs_test_cluster_block_vector \ fsntfs_test_compressed_block \ fsntfs_test_compressed_block_data_handle \ fsntfs_test_compressed_block_vector \ fsntfs_test_compressed_data_handle \ fsntfs_test_compression \ fsntfs_test_compression_unit_data_handle \ fsntfs_test_compression_unit_descriptor \ fsntfs_test_data_run \ fsntfs_test_data_stream \ fsntfs_test_directory_entries_tree \ fsntfs_test_directory_entry \ fsntfs_test_error \ fsntfs_test_extent \ fsntfs_test_file_entry \ fsntfs_test_file_name_attribute \ fsntfs_test_file_name_values \ fsntfs_test_file_system \ fsntfs_test_fixup_values \ fsntfs_test_index \ fsntfs_test_index_entry \ fsntfs_test_index_entry_header \ fsntfs_test_index_entry_vector \ fsntfs_test_index_node \ fsntfs_test_index_node_header \ fsntfs_test_index_root_header \ fsntfs_test_index_value \ fsntfs_test_io_handle \ fsntfs_test_logged_utility_stream_values \ fsntfs_test_mft \ fsntfs_test_mft_attribute \ fsntfs_test_mft_attribute_list \ fsntfs_test_mft_attribute_list_entry \ fsntfs_test_mft_entry \ fsntfs_test_mft_entry_header \ fsntfs_test_mft_metadata_file \ fsntfs_test_name \ fsntfs_test_notify \ fsntfs_test_object_identifier_values \ fsntfs_test_path_hint \ fsntfs_test_profiler \ fsntfs_test_reparse_point_attribute \ fsntfs_test_reparse_point_values \ fsntfs_test_sds_index_value \ fsntfs_test_security_descriptor_index \ fsntfs_test_security_descriptor_index_value \ fsntfs_test_security_descriptor_values \ fsntfs_test_standard_information_values \ fsntfs_test_support \ fsntfs_test_tools_bodyfile \ fsntfs_test_tools_digest_hash \ fsntfs_test_tools_info_handle \ fsntfs_test_tools_mount_path_string \ fsntfs_test_tools_output \ fsntfs_test_tools_path_string \ fsntfs_test_tools_signal \ fsntfs_test_txf_data_values \ fsntfs_test_usn_change_journal \ fsntfs_test_volume \ fsntfs_test_volume_header \ fsntfs_test_volume_information_attribute \ fsntfs_test_volume_information_values \ fsntfs_test_volume_name_attribute \ fsntfs_test_volume_name_values fsntfs_test_attribute_SOURCES = \ fsntfs_test_attribute.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_rwlock.c fsntfs_test_rwlock.h \ fsntfs_test_unused.h fsntfs_test_attribute_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ \ @PTHREAD_LIBADD@ fsntfs_test_attribute_list_entry_SOURCES = \ fsntfs_test_attribute_list_entry.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_attribute_list_entry_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_bitmap_values_SOURCES = \ fsntfs_test_bitmap_values.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_bitmap_values_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_buffer_data_handle_SOURCES = \ fsntfs_test_buffer_data_handle.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_buffer_data_handle_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_cluster_block_SOURCES = \ fsntfs_test_cluster_block.c \ fsntfs_test_functions.c fsntfs_test_functions.h \ fsntfs_test_libbfio.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_cluster_block_LDADD = \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_cluster_block_data_SOURCES = \ fsntfs_test_cluster_block_data.c \ fsntfs_test_functions.c fsntfs_test_functions.h \ fsntfs_test_libbfio.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfdata.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_cluster_block_data_LDADD = \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_cluster_block_stream_SOURCES = \ fsntfs_test_cluster_block_stream.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfdata.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_cluster_block_stream_LDADD = \ @LIBFDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_cluster_block_vector_SOURCES = \ fsntfs_test_cluster_block_vector.c \ fsntfs_test_functions.c fsntfs_test_functions.h \ fsntfs_test_libbfio.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfcache.h \ fsntfs_test_libfdata.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_cluster_block_vector_LDADD = \ @LIBFDATA_LIBADD@ \ @LIBFCACHE_LIBADD@ \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_compressed_block_SOURCES = \ fsntfs_test_compressed_block.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_compressed_block_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_compressed_block_data_handle_SOURCES = \ fsntfs_test_compressed_block_data_handle.c \ fsntfs_test_functions.c fsntfs_test_functions.h \ fsntfs_test_libbfio.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_compressed_block_data_handle_LDADD = \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_compressed_block_vector_SOURCES = \ fsntfs_test_compressed_block_vector.c \ fsntfs_test_functions.c fsntfs_test_functions.h \ fsntfs_test_libbfio.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfcache.h \ fsntfs_test_libfdata.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_compressed_block_vector_LDADD = \ @LIBFDATA_LIBADD@ \ @LIBFCACHE_LIBADD@ \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_compressed_data_handle_SOURCES = \ fsntfs_test_compressed_data_handle.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfdata.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_compressed_data_handle_LDADD = \ @LIBFDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_compression_SOURCES = \ fsntfs_test_compression.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_unused.h fsntfs_test_compression_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_compression_unit_data_handle_SOURCES = \ fsntfs_test_compression_unit_data_handle.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_compression_unit_data_handle_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_compression_unit_descriptor_SOURCES = \ fsntfs_test_compression_unit_descriptor.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_compression_unit_descriptor_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_data_run_SOURCES = \ fsntfs_test_data_run.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfdata.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_data_run_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_data_stream_SOURCES = \ fsntfs_test_data_stream.c \ fsntfs_test_functions.c fsntfs_test_functions.h \ fsntfs_test_libbfio.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_rwlock.c fsntfs_test_rwlock.h \ fsntfs_test_unused.h fsntfs_test_data_stream_LDADD = \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ \ @PTHREAD_LIBADD@ fsntfs_test_directory_entries_tree_SOURCES = \ fsntfs_test_directory_entries_tree.c \ fsntfs_test_libbfio.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_directory_entries_tree_LDADD = \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_directory_entry_SOURCES = \ fsntfs_test_directory_entry.c \ fsntfs_test_libcdata.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_directory_entry_LDADD = \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_error_SOURCES = \ fsntfs_test_error.c \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_unused.h fsntfs_test_error_LDADD = \ ../libfsntfs/libfsntfs.la fsntfs_test_extent_SOURCES = \ fsntfs_test_extent.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_extent_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_file_entry_SOURCES = \ fsntfs_test_file_entry.c \ fsntfs_test_functions.c fsntfs_test_functions.h \ fsntfs_test_libbfio.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_rwlock.c fsntfs_test_rwlock.h \ fsntfs_test_unused.h fsntfs_test_file_entry_LDADD = \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ \ @PTHREAD_LIBADD@ fsntfs_test_file_name_attribute_SOURCES = \ fsntfs_test_file_name_attribute.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_file_name_attribute_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_file_name_values_SOURCES = \ fsntfs_test_file_name_values.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_file_name_values_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_file_system_SOURCES = \ fsntfs_test_file_system.c \ fsntfs_test_functions.c fsntfs_test_functions.h \ fsntfs_test_libbfio.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_rwlock.c fsntfs_test_rwlock.h \ fsntfs_test_unused.h fsntfs_test_file_system_LDADD = \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ \ @PTHREAD_LIBADD@ fsntfs_test_fixup_values_SOURCES = \ fsntfs_test_fixup_values.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_unused.h fsntfs_test_fixup_values_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_index_SOURCES = \ fsntfs_test_index.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_index_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_index_entry_SOURCES = \ fsntfs_test_functions.c fsntfs_test_functions.h \ fsntfs_test_index_entry.c \ fsntfs_test_libbfio.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_index_entry_LDADD = \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_index_entry_header_SOURCES = \ fsntfs_test_index_entry_header.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_index_entry_header_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_index_entry_vector_SOURCES = \ fsntfs_test_functions.c fsntfs_test_functions.h \ fsntfs_test_index_entry_vector.c \ fsntfs_test_libbfio.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfcache.h \ fsntfs_test_libfdata.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_index_entry_vector_LDADD = \ @LIBFDATA_LIBADD@ \ @LIBFCACHE_LIBADD@ \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_index_node_SOURCES = \ fsntfs_test_index_node.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_index_node_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_index_node_header_SOURCES = \ fsntfs_test_index_node_header.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_index_node_header_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_index_root_header_SOURCES = \ fsntfs_test_index_root_header.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_index_root_header_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_index_value_SOURCES = \ fsntfs_test_index_value.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_index_value_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_io_handle_SOURCES = \ fsntfs_test_io_handle.c \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_io_handle_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_logged_utility_stream_values_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_logged_utility_stream_values.c \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h fsntfs_test_logged_utility_stream_values_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_mft_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_mft.c \ fsntfs_test_unused.h fsntfs_test_mft_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_mft_attribute_SOURCES = \ fsntfs_test_libcdata.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_mft_attribute.c \ fsntfs_test_unused.h fsntfs_test_mft_attribute_LDADD = \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_mft_attribute_list_SOURCES = \ fsntfs_test_libcdata.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_mft_attribute_list.c \ fsntfs_test_unused.h fsntfs_test_mft_attribute_list_LDADD = \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_mft_attribute_list_entry_SOURCES = \ fsntfs_test_libcdata.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_mft_attribute_list_entry.c \ fsntfs_test_unused.h fsntfs_test_mft_attribute_list_entry_LDADD = \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_mft_entry_SOURCES = \ fsntfs_test_functions.c fsntfs_test_functions.h \ fsntfs_test_libbfio.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_mft_entry.c \ fsntfs_test_unused.h fsntfs_test_mft_entry_LDADD = \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_mft_entry_header_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_mft_entry_header.c \ fsntfs_test_unused.h fsntfs_test_mft_entry_header_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_mft_metadata_file_SOURCES = \ fsntfs_test_functions.c fsntfs_test_functions.h \ fsntfs_test_getopt.c fsntfs_test_getopt.h \ fsntfs_test_libbfio.h \ fsntfs_test_libcerror.h \ fsntfs_test_libclocale.h \ fsntfs_test_libcnotify.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_libuna.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_mft_metadata_file.c \ fsntfs_test_rwlock.c fsntfs_test_rwlock.h fsntfs_test_mft_metadata_file_LDADD = \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ \ @PTHREAD_LIBADD@ fsntfs_test_name_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_libuna.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_name.c \ fsntfs_test_unused.h fsntfs_test_name_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_notify_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_notify.c \ fsntfs_test_unused.h fsntfs_test_notify_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_object_identifier_values_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_object_identifier_values.c \ fsntfs_test_unused.h fsntfs_test_object_identifier_values_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_path_hint_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_path_hint.c \ fsntfs_test_unused.h fsntfs_test_path_hint_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_profiler_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_profiler.c \ fsntfs_test_unused.h fsntfs_test_profiler_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_reparse_point_attribute_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_reparse_point_attribute.c \ fsntfs_test_unused.h fsntfs_test_reparse_point_attribute_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_reparse_point_values_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_reparse_point_values.c \ fsntfs_test_unused.h fsntfs_test_reparse_point_values_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_sds_index_value_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_sds_index_value.c \ fsntfs_test_unused.h fsntfs_test_sds_index_value_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_security_descriptor_index_SOURCES = \ fsntfs_test_libbfio.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_security_descriptor_index.c \ fsntfs_test_unused.h fsntfs_test_security_descriptor_index_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_security_descriptor_index_value_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_security_descriptor_index_value.c \ fsntfs_test_unused.h fsntfs_test_security_descriptor_index_value_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_security_descriptor_values_SOURCES = \ fsntfs_test_functions.c fsntfs_test_functions.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfdata.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_security_descriptor_values.c \ fsntfs_test_unused.h fsntfs_test_security_descriptor_values_LDADD = \ @LIBFDATA_LIBADD@ \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_standard_information_values_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_standard_information_values.c \ fsntfs_test_unused.h fsntfs_test_standard_information_values_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_support_SOURCES = \ fsntfs_test_getopt.c fsntfs_test_getopt.h \ fsntfs_test_functions.c fsntfs_test_functions.h \ fsntfs_test_libbfio.h \ fsntfs_test_libcerror.h \ fsntfs_test_libclocale.h \ fsntfs_test_libcnotify.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_libuna.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_support.c \ fsntfs_test_unused.h fsntfs_test_support_LDADD = \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_tools_bodyfile_SOURCES = \ ../fsntfstools/bodyfile.c ../fsntfstools/bodyfile.h \ fsntfs_test_libcerror.h \ fsntfs_test_libcpath.h \ fsntfs_test_macros.h \ fsntfs_test_tools_bodyfile.c \ fsntfs_test_unused.h fsntfs_test_tools_bodyfile_LDADD = \ @LIBUNA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_tools_digest_hash_SOURCES = \ ../fsntfstools/digest_hash.c ../fsntfstools/digest_hash.h \ fsntfs_test_libcerror.h \ fsntfs_test_macros.h \ fsntfs_test_tools_digest_hash.c \ fsntfs_test_unused.h fsntfs_test_tools_digest_hash_LDADD = \ @LIBCERROR_LIBADD@ fsntfs_test_tools_info_handle_SOURCES = \ ../fsntfstools/bodyfile.c ../fsntfstools/bodyfile.h \ ../fsntfstools/digest_hash.c ../fsntfstools/digest_hash.h \ ../fsntfstools/info_handle.c ../fsntfstools/info_handle.h \ ../fsntfstools/path_string.c ../fsntfstools/path_string.h \ fsntfs_test_libcerror.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_tools_info_handle.c \ fsntfs_test_unused.h fsntfs_test_tools_info_handle_LDADD = \ @LIBHMAC_LIBADD@ \ @LIBCRYPTO_LIBADD@ \ @LIBDL_LIBADD@ \ @LIBFWNT_LIBADD@ \ @LIBFUSN_LIBADD@ \ @LIBFGUID_LIBADD@ \ @LIBFDATETIME_LIBADD@ \ @LIBBFIO_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_tools_mount_path_string_SOURCES = \ ../fsntfstools/mount_path_string.c ../fsntfstools/mount_path_string.h \ fsntfs_test_libcerror.h \ fsntfs_test_macros.h \ fsntfs_test_tools_mount_path_string.c \ fsntfs_test_unused.h fsntfs_test_tools_mount_path_string_LDADD = \ @LIBUNA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_tools_output_SOURCES = \ ../fsntfstools/fsntfstools_output.c ../fsntfstools/fsntfstools_output.h \ fsntfs_test_libcerror.h \ fsntfs_test_macros.h \ fsntfs_test_tools_output.c \ fsntfs_test_unused.h fsntfs_test_tools_output_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_tools_path_string_SOURCES = \ ../fsntfstools/path_string.c ../fsntfstools/path_string.h \ fsntfs_test_libcerror.h \ fsntfs_test_libcpath.h \ fsntfs_test_macros.h \ fsntfs_test_tools_path_string.c \ fsntfs_test_unused.h fsntfs_test_tools_path_string_LDADD = \ @LIBUNA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_tools_signal_SOURCES = \ ../fsntfstools/fsntfstools_signal.c ../fsntfstools/fsntfstools_signal.h \ fsntfs_test_libcerror.h \ fsntfs_test_macros.h \ fsntfs_test_tools_signal.c \ fsntfs_test_unused.h fsntfs_test_tools_signal_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_txf_data_values_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_txf_data_values.c \ fsntfs_test_unused.h fsntfs_test_txf_data_values_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_usn_change_journal_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_rwlock.c fsntfs_test_rwlock.h \ fsntfs_test_unused.h \ fsntfs_test_usn_change_journal.c fsntfs_test_usn_change_journal_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ \ @PTHREAD_LIBADD@ fsntfs_test_volume_SOURCES = \ fsntfs_test_getopt.c fsntfs_test_getopt.h \ fsntfs_test_functions.c fsntfs_test_functions.h \ fsntfs_test_libbfio.h \ fsntfs_test_libcerror.h \ fsntfs_test_libclocale.h \ fsntfs_test_libcnotify.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_libuna.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_rwlock.c fsntfs_test_rwlock.h \ fsntfs_test_volume.c \ fsntfs_test_unused.h fsntfs_test_volume_LDADD = \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ \ @PTHREAD_LIBADD@ fsntfs_test_volume_header_SOURCES = \ fsntfs_test_functions.c fsntfs_test_functions.h \ fsntfs_test_libbfio.h \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h \ fsntfs_test_volume_header.c fsntfs_test_volume_header_LDADD = \ @LIBBFIO_LIBADD@ \ @LIBCPATH_LIBADD@ \ @LIBCFILE_LIBADD@ \ @LIBUNA_LIBADD@ \ @LIBCSPLIT_LIBADD@ \ @LIBCNOTIFY_LIBADD@ \ @LIBCLOCALE_LIBADD@ \ @LIBCDATA_LIBADD@ \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_volume_information_attribute_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h \ fsntfs_test_volume_information_attribute.c fsntfs_test_volume_information_attribute_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_volume_information_values_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h \ fsntfs_test_volume_information_values.c fsntfs_test_volume_information_values_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_volume_name_attribute_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h \ fsntfs_test_volume_name_attribute.c fsntfs_test_volume_name_attribute_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ fsntfs_test_volume_name_values_SOURCES = \ fsntfs_test_libcerror.h \ fsntfs_test_libfsntfs.h \ fsntfs_test_macros.h \ fsntfs_test_memory.c fsntfs_test_memory.h \ fsntfs_test_unused.h \ fsntfs_test_volume_name_values.c fsntfs_test_volume_name_values_LDADD = \ ../libfsntfs/libfsntfs.la \ @LIBCERROR_LIBADD@ DISTCLEANFILES = \ Makefile \ Makefile.in \ notify_stream.log ================================================ FILE: tests/build.sh ================================================ #!/bin/sh # Script to build from source # # Version: 20201121 set -e ./synclibs.sh --use-head ./autogen.sh ./configure "$@" make > /dev/null ================================================ FILE: tests/fsntfs_test_attribute.c ================================================ /* * Library attribute type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_rwlock.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_attribute.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" /* $BITMAP attribute */ uint8_t fsntfs_test_attribute_data1[ 40 ] = { 0xb0, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x49, 0x00, 0x33, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_attribute_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_attribute_t *attribute = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 2; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Initialize test */ result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_attribute_initialize( &attribute, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_attribute_initialize( NULL, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); attribute = (libfsntfs_attribute_t *) 0x12345678UL; result = libfsntfs_attribute_initialize( &attribute, mft_attribute, &error ); attribute = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_initialize( &attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_attribute_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_attribute_initialize( &attribute, mft_attribute, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( attribute != NULL ) { libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &attribute, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_attribute_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_attribute_initialize( &attribute, mft_attribute, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( attribute != NULL ) { libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &attribute, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( attribute != NULL ) { libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &attribute, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* Tests the libfsntfs_attribute_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_free( void ) { libfsntfs_attribute_t *attribute = NULL; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ attribute = (libfsntfs_attribute_t *) 0x12345678UL; result = libfsntfs_attribute_free( &attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_attribute_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_internal_attribute_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_internal_attribute_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_internal_attribute_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_internal_attribute_read_value function * Returns 1 if successful or 0 if not */ int fsntfs_test_internal_attribute_read_value( void ) { libcerror_error_t *error = NULL; libfsntfs_attribute_t *attribute = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_attribute_data1, 40, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_attribute_initialize( &attribute, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_internal_attribute_read_value( (libfsntfs_internal_attribute_t *) attribute, io_handle, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_internal_attribute_read_value( (libfsntfs_internal_attribute_t *) attribute, io_handle, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ result = libfsntfs_attribute_initialize( &attribute, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_internal_attribute_read_value( NULL, io_handle, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( attribute != NULL ) { libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &attribute, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_internal_attribute_get_type function * Returns 1 if successful or 0 if not */ int fsntfs_test_internal_attribute_get_type( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; uint32_t type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_internal_attribute_get_type( (libfsntfs_internal_attribute_t *) attribute, &type, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_internal_attribute_get_type( NULL, &type, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_internal_attribute_get_type( (libfsntfs_internal_attribute_t *) attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_attribute_get_type function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_get_type( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; uint32_t type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_attribute_get_type( attribute, &type, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_attribute_get_type( NULL, &type, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_get_type( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_attribute_get_type with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_attribute_get_type( attribute, &type, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_attribute_get_type with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_attribute_get_type( attribute, &type, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_attribute_get_data_flags function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_get_data_flags( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; uint16_t data_flags = 0; int result = 0; /* Test regular cases */ result = libfsntfs_attribute_get_data_flags( attribute, &data_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_attribute_get_data_flags( NULL, &data_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_get_data_flags( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_attribute_get_data_flags with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_attribute_get_data_flags( attribute, &data_flags, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_attribute_get_data_flags with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_attribute_get_data_flags( attribute, &data_flags, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_internal_attribute_get_value function * Returns 1 if successful or 0 if not */ int fsntfs_test_internal_attribute_get_value( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; intptr_t *value = 0; int result = 0; /* Test regular cases */ result = libfsntfs_internal_attribute_get_value( (libfsntfs_internal_attribute_t *) attribute, &value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_internal_attribute_get_value( NULL, &value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_internal_attribute_get_value( (libfsntfs_internal_attribute_t *) attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_attribute_get_utf8_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_get_utf8_name_size( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; size_t utf8_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_attribute_get_utf8_name_size( attribute, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_attribute_get_utf8_name_size( NULL, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_get_utf8_name_size( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_attribute_get_utf8_name_size with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_attribute_get_utf8_name_size( attribute, &utf8_name_size, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_attribute_get_utf8_name_size with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_attribute_get_utf8_name_size( attribute, &utf8_name_size, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_attribute_get_utf8_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_get_utf8_name( libfsntfs_attribute_t *attribute ) { uint8_t utf8_name[ 64 ]; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_attribute_get_utf8_name( attribute, utf8_name, 64, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_attribute_get_utf8_name( NULL, utf8_name, 64, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_get_utf8_name( attribute, NULL, 64, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_get_utf8_name( attribute, utf8_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_get_utf8_name( attribute, utf8_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_attribute_get_utf8_name with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_attribute_get_utf8_name( attribute, utf8_name, 64, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_attribute_get_utf8_name with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_attribute_get_utf8_name( attribute, utf8_name, 64, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_attribute_get_utf16_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_get_utf16_name_size( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; size_t utf16_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_attribute_get_utf16_name_size( attribute, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_attribute_get_utf16_name_size( NULL, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_get_utf16_name_size( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_attribute_get_utf16_name_size with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_attribute_get_utf16_name_size( attribute, &utf16_name_size, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_attribute_get_utf16_name_size with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_attribute_get_utf16_name_size( attribute, &utf16_name_size, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_attribute_get_utf16_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_get_utf16_name( libfsntfs_attribute_t *attribute ) { uint16_t utf16_name[ 64 ]; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_attribute_get_utf16_name( attribute, utf16_name, 64, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_attribute_get_utf16_name( NULL, utf16_name, 64, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_get_utf16_name( attribute, NULL, 64, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_get_utf16_name( attribute, utf16_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_get_utf16_name( attribute, utf16_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_attribute_get_utf16_name with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_attribute_get_utf16_name( attribute, utf16_name, 64, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_attribute_get_utf16_name with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_attribute_get_utf16_name( attribute, utf16_name, 64, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_attribute_get_data_vcn_range function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_get_data_vcn_range( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; uint64_t data_first_vcn = 0; uint64_t data_last_vcn = 0; int result = 0; /* Test regular cases */ result = libfsntfs_attribute_get_data_vcn_range( attribute, &data_first_vcn, &data_last_vcn, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_attribute_get_data_vcn_range( NULL, &data_first_vcn, &data_last_vcn, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_get_data_vcn_range( attribute, NULL, &data_last_vcn, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_get_data_vcn_range( attribute, &data_first_vcn, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_attribute_get_data_vcn_range with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_attribute_get_data_vcn_range( attribute, &data_first_vcn, &data_last_vcn, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_attribute_get_data_vcn_range with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_attribute_get_data_vcn_range( attribute, &data_first_vcn, &data_last_vcn, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_internal_attribute_get_data_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_internal_attribute_get_data_size( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; size64_t data_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_internal_attribute_get_data_size( (libfsntfs_internal_attribute_t *) attribute, &data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_internal_attribute_get_data_size( NULL, &data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_internal_attribute_get_data_size( (libfsntfs_internal_attribute_t *) attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_attribute_get_data_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_get_data_size( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; size64_t data_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_attribute_get_data_size( attribute, &data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_attribute_get_data_size( NULL, &data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_get_data_size( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_attribute_get_data_size with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_attribute_get_data_size( attribute, &data_size, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_attribute_get_data_size with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_attribute_get_data_size( attribute, &data_size, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_attribute_get_valid_data_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_get_valid_data_size( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; size64_t valid_data_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_attribute_get_valid_data_size( attribute, &valid_data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_attribute_get_valid_data_size( NULL, &valid_data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_get_valid_data_size( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_attribute_get_valid_data_size with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_attribute_get_valid_data_size( attribute, &valid_data_size, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_attribute_get_valid_data_size with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_attribute_get_valid_data_size( attribute, &valid_data_size, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_attribute_t *attribute = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_attribute_initialize", fsntfs_test_attribute_initialize ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_RUN( "libfsntfs_attribute_free", fsntfs_test_attribute_free ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_internal_attribute_free", fsntfs_test_internal_attribute_free ); FSNTFS_TEST_RUN( "libfsntfs_internal_attribute_read_value", fsntfs_test_internal_attribute_read_value ); #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_attribute_data1, 40, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_attribute_initialize( &attribute, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Run tests */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_internal_attribute_get_type", fsntfs_test_internal_attribute_get_type, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_attribute_get_type", fsntfs_test_attribute_get_type, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_attribute_get_data_flags", fsntfs_test_attribute_get_data_flags, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_internal_attribute_get_value", fsntfs_test_internal_attribute_get_value, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_attribute_get_utf8_name_size", fsntfs_test_attribute_get_utf8_name_size, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_attribute_get_utf8_name", fsntfs_test_attribute_get_utf8_name, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_attribute_get_utf16_name_size", fsntfs_test_attribute_get_utf16_name_size, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_attribute_get_utf16_name", fsntfs_test_attribute_get_utf16_name, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_attribute_get_data_vcn_range", fsntfs_test_attribute_get_data_vcn_range, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_internal_attribute_get_data_size", fsntfs_test_internal_attribute_get_data_size, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_attribute_get_data_size", fsntfs_test_attribute_get_data_size, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_attribute_get_valid_data_size", fsntfs_test_attribute_get_valid_data_size, attribute ); /* Clean up */ result = libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); on_error: #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) if( error != NULL ) { libcerror_error_free( &error ); } if( attribute != NULL ) { libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &attribute, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_FAILURE ); } ================================================ FILE: tests/fsntfs_test_attribute_list_entry.c ================================================ /* * Library attribute_list_entry type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_attribute_list_entry.h" uint8_t fsntfs_test_attribute_list_entry_data1[ 40 ] = { 0x80, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x53, 0x00, 0x44, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_attribute_list_entry_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_list_entry_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_attribute_list_entry_t *attribute_list_entry = NULL; libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Initialize test */ result = libfsntfs_mft_attribute_list_entry_initialize( &mft_attribute_list_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute_list_entry", mft_attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_attribute_list_entry_initialize( &attribute_list_entry, mft_attribute_list_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "attribute_list_entry", attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_attribute_list_entry_free( &attribute_list_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute_list_entry", attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_attribute_list_entry_initialize( NULL, mft_attribute_list_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); attribute_list_entry = (libfsntfs_attribute_list_entry_t *) 0x12345678UL; result = libfsntfs_attribute_list_entry_initialize( &attribute_list_entry, mft_attribute_list_entry, &error ); attribute_list_entry = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_list_entry_initialize( &attribute_list_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_attribute_list_entry_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_attribute_list_entry_initialize( &attribute_list_entry, mft_attribute_list_entry, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( attribute_list_entry != NULL ) { libfsntfs_attribute_list_entry_free( &attribute_list_entry, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute_list_entry", attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_attribute_list_entry_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_attribute_list_entry_initialize( &attribute_list_entry, mft_attribute_list_entry, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( attribute_list_entry != NULL ) { libfsntfs_attribute_list_entry_free( &attribute_list_entry, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute_list_entry", attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute_list_entry", mft_attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( attribute_list_entry != NULL ) { libfsntfs_attribute_list_entry_free( &attribute_list_entry, NULL ); } if( mft_attribute_list_entry != NULL ) { libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* Tests the libfsntfs_attribute_list_entry_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_list_entry_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_attribute_list_entry_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_attribute_list_entry_get_attribute_type function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_list_entry_get_attribute_type( libfsntfs_attribute_list_entry_t *attribute_list_entry ) { libcerror_error_t *error = NULL; libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry = NULL; uint32_t attribute_type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_attribute_list_entry_get_attribute_type( attribute_list_entry, &attribute_type, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_attribute_list_entry_get_attribute_type( NULL, &attribute_type, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_list_entry_get_attribute_type( attribute_list_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_attribute_list_entry != NULL ) { libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, NULL ); } return( 0 ); } /* Tests the libfsntfs_attribute_list_entry_get_file_reference function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_list_entry_get_file_reference( libfsntfs_attribute_list_entry_t *attribute_list_entry ) { libcerror_error_t *error = NULL; libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry = NULL; uint64_t file_reference = 0; int result = 0; /* Test regular cases */ result = libfsntfs_attribute_list_entry_get_file_reference( attribute_list_entry, &file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_attribute_list_entry_get_file_reference( NULL, &file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_list_entry_get_file_reference( attribute_list_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_attribute_list_entry != NULL ) { libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, NULL ); } return( 0 ); } /* Tests the libfsntfs_attribute_list_entry_get_utf8_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_list_entry_get_utf8_name_size( libfsntfs_attribute_list_entry_t *attribute_list_entry ) { libcerror_error_t *error = NULL; libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry = NULL; size_t utf8_string_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_attribute_list_entry_get_utf8_name_size( attribute_list_entry, &utf8_string_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_attribute_list_entry_get_utf8_name_size( NULL, &utf8_string_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_list_entry_get_utf8_name_size( attribute_list_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_attribute_list_entry != NULL ) { libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, NULL ); } return( 0 ); } /* Tests the libfsntfs_attribute_list_entry_get_utf8_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_list_entry_get_utf8_name( libfsntfs_attribute_list_entry_t *attribute_list_entry ) { uint8_t utf8_string[ 512 ]; libcerror_error_t *error = NULL; libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_attribute_list_entry_get_utf8_name( attribute_list_entry, utf8_string, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_attribute_list_entry_get_utf8_name( NULL, utf8_string, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_list_entry_get_utf8_name( attribute_list_entry, NULL, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_list_entry_get_utf8_name( attribute_list_entry, utf8_string, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_list_entry_get_utf8_name( attribute_list_entry, utf8_string, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_attribute_list_entry != NULL ) { libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, NULL ); } return( 0 ); } /* Tests the libfsntfs_attribute_list_entry_get_utf16_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_list_entry_get_utf16_name_size( libfsntfs_attribute_list_entry_t *attribute_list_entry ) { libcerror_error_t *error = NULL; libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry = NULL; size_t utf16_string_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_attribute_list_entry_get_utf16_name_size( attribute_list_entry, &utf16_string_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_attribute_list_entry_get_utf16_name_size( NULL, &utf16_string_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_list_entry_get_utf16_name_size( attribute_list_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_attribute_list_entry != NULL ) { libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, NULL ); } return( 0 ); } /* Tests the libfsntfs_attribute_list_entry_get_utf16_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_attribute_list_entry_get_utf16_name( libfsntfs_attribute_list_entry_t *attribute_list_entry ) { uint16_t utf16_string[ 512 ]; libcerror_error_t *error = NULL; libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_attribute_list_entry_get_utf16_name( attribute_list_entry, utf16_string, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_attribute_list_entry_get_utf16_name( NULL, utf16_string, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_list_entry_get_utf16_name( attribute_list_entry, NULL, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_list_entry_get_utf16_name( attribute_list_entry, utf16_string, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_attribute_list_entry_get_utf16_name( attribute_list_entry, utf16_string, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_attribute_list_entry != NULL ) { libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_attribute_list_entry_t *attribute_list_entry = NULL; libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry = NULL; int result = 0; #endif FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_attribute_list_entry_initialize", fsntfs_test_attribute_list_entry_initialize ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_RUN( "libfsntfs_attribute_list_entry_free", fsntfs_test_attribute_list_entry_free ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize attribute_list_entry for tests */ result = libfsntfs_mft_attribute_list_entry_initialize( &mft_attribute_list_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute_list_entry", mft_attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_list_entry_read_data( mft_attribute_list_entry, fsntfs_test_attribute_list_entry_data1, 40, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_attribute_list_entry_initialize( &attribute_list_entry, mft_attribute_list_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "attribute_list_entry", attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Run tests */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_attribute_list_entry_get_attribute_type", fsntfs_test_attribute_list_entry_get_attribute_type, attribute_list_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_attribute_list_entry_get_file_reference", fsntfs_test_attribute_list_entry_get_file_reference, attribute_list_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_attribute_list_entry_get_utf8_name_size", fsntfs_test_attribute_list_entry_get_utf8_name_size, attribute_list_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_attribute_list_entry_get_utf8_name", fsntfs_test_attribute_list_entry_get_utf8_name, attribute_list_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_attribute_list_entry_get_utf16_name_size", fsntfs_test_attribute_list_entry_get_utf16_name_size, attribute_list_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_attribute_list_entry_get_utf16_name", fsntfs_test_attribute_list_entry_get_utf16_name, attribute_list_entry ); /* Clean up */ result = libfsntfs_attribute_list_entry_free( &attribute_list_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute_list_entry", attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute_list_entry", mft_attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); on_error: #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) if( error != NULL ) { libcerror_error_free( &error ); } if( attribute_list_entry != NULL ) { libfsntfs_attribute_list_entry_free( &attribute_list_entry, NULL ); } if( mft_attribute_list_entry != NULL ) { libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, NULL ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_FAILURE ); } ================================================ FILE: tests/fsntfs_test_bitmap_values.c ================================================ /* * Library bitmap_values type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_bitmap_values.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" uint8_t fsntfs_test_bitmap_values_data1[ 40 ] = { 0xb0, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x49, 0x00, 0x33, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_bitmap_values_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_bitmap_values_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_bitmap_values_t *bitmap_values = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_bitmap_values_initialize( &bitmap_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "bitmap_values", bitmap_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_bitmap_values_free( &bitmap_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "bitmap_values", bitmap_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_bitmap_values_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); bitmap_values = (libfsntfs_bitmap_values_t *) 0x12345678UL; result = libfsntfs_bitmap_values_initialize( &bitmap_values, &error ); bitmap_values = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_bitmap_values_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_bitmap_values_initialize( &bitmap_values, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( bitmap_values != NULL ) { libfsntfs_bitmap_values_free( &bitmap_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "bitmap_values", bitmap_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_bitmap_values_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_bitmap_values_initialize( &bitmap_values, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( bitmap_values != NULL ) { libfsntfs_bitmap_values_free( &bitmap_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "bitmap_values", bitmap_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( bitmap_values != NULL ) { libfsntfs_bitmap_values_free( &bitmap_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_bitmap_values_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_bitmap_values_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_bitmap_values_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_bitmap_values_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_bitmap_values_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_bitmap_values_t *bitmap_values = NULL; libfsntfs_io_handle_t *io_handle = NULL; off64_t base_offset = 0; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_bitmap_values_initialize( &bitmap_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "bitmap_values", bitmap_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_bitmap_values_read_data( bitmap_values, &( fsntfs_test_bitmap_values_data1[ 32 ] ), 8, 512, &base_offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_bitmap_values_read_data( NULL, &( fsntfs_test_bitmap_values_data1[ 32 ] ), 8, 512, &base_offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_bitmap_values_read_data( bitmap_values, NULL, 8, 512, &base_offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_bitmap_values_read_data( bitmap_values, &( fsntfs_test_bitmap_values_data1[ 32 ] ), (size_t) SSIZE_MAX + 1, 512, &base_offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_bitmap_values_read_data( bitmap_values, &( fsntfs_test_bitmap_values_data1[ 32 ] ), 8, 512, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_bitmap_values_free( &bitmap_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "bitmap_values", bitmap_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( bitmap_values != NULL ) { libfsntfs_bitmap_values_free( &bitmap_values, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_bitmap_values_read_from_mft_attribute function * Returns 1 if successful or 0 if not */ int fsntfs_test_bitmap_values_read_from_mft_attribute( void ) { libcerror_error_t *error = NULL; libfsntfs_bitmap_values_t *bitmap_values = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_bitmap_values_data1, 40, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_bitmap_values_initialize( &bitmap_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "bitmap_values", bitmap_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_bitmap_values_read_from_mft_attribute( bitmap_values, mft_attribute, io_handle, NULL, 512, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_bitmap_values_read_from_mft_attribute( NULL, mft_attribute, io_handle, NULL, 512, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_bitmap_values_read_from_mft_attribute( bitmap_values, NULL, io_handle, NULL, 512, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_bitmap_values_free( &bitmap_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "bitmap_values", bitmap_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( bitmap_values != NULL ) { libfsntfs_bitmap_values_free( &bitmap_values, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_bitmap_values_initialize", fsntfs_test_bitmap_values_initialize ); FSNTFS_TEST_RUN( "libfsntfs_bitmap_values_free", fsntfs_test_bitmap_values_free ); FSNTFS_TEST_RUN( "libfsntfs_bitmap_values_read_data", fsntfs_test_bitmap_values_read_data ); FSNTFS_TEST_RUN( "libfsntfs_bitmap_values_read_from_mft_attribute", fsntfs_test_bitmap_values_read_from_mft_attribute ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_buffer_data_handle.c ================================================ /* * Library buffer_data_handle type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_buffer_data_handle.h" uint8_t fsntfs_test_buffer_data_handle_data1[ 16 ] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_buffer_data_handle_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_buffer_data_handle_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_buffer_data_handle_t *buffer_data_handle = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_buffer_data_handle_initialize( &buffer_data_handle, fsntfs_test_buffer_data_handle_data1, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "buffer_data_handle", buffer_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_buffer_data_handle_free( &buffer_data_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "buffer_data_handle", buffer_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_buffer_data_handle_initialize( &buffer_data_handle, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "buffer_data_handle", buffer_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_buffer_data_handle_free( &buffer_data_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "buffer_data_handle", buffer_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_buffer_data_handle_initialize( NULL, fsntfs_test_buffer_data_handle_data1, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); buffer_data_handle = (libfsntfs_buffer_data_handle_t *) 0x12345678UL; result = libfsntfs_buffer_data_handle_initialize( &buffer_data_handle, fsntfs_test_buffer_data_handle_data1, 16, &error ); buffer_data_handle = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_buffer_data_handle_initialize( &buffer_data_handle, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_buffer_data_handle_initialize( &buffer_data_handle, fsntfs_test_buffer_data_handle_data1, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_buffer_data_handle_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_buffer_data_handle_initialize( &buffer_data_handle, fsntfs_test_buffer_data_handle_data1, 16, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( buffer_data_handle != NULL ) { libfsntfs_buffer_data_handle_free( &buffer_data_handle, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "buffer_data_handle", buffer_data_handle ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_buffer_data_handle_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_buffer_data_handle_initialize( &buffer_data_handle, fsntfs_test_buffer_data_handle_data1, 16, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( buffer_data_handle != NULL ) { libfsntfs_buffer_data_handle_free( &buffer_data_handle, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "buffer_data_handle", buffer_data_handle ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( buffer_data_handle != NULL ) { libfsntfs_buffer_data_handle_free( &buffer_data_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_buffer_data_handle_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_buffer_data_handle_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_buffer_data_handle_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_buffer_data_handle_read_segment_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_buffer_data_handle_read_segment_data( void ) { uint8_t segment_data[ 16 ]; libcerror_error_t *error = NULL; libfsntfs_buffer_data_handle_t *buffer_data_handle = NULL; ssize_t read_count = 0; off64_t offset = 0; int result = 0; /* Initialize test */ result = libfsntfs_buffer_data_handle_initialize( &buffer_data_handle, fsntfs_test_buffer_data_handle_data1, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "buffer_data_handle", buffer_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ read_count = libfsntfs_buffer_data_handle_read_segment_data( buffer_data_handle, NULL, 0, 0, segment_data, 12, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) 12 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( segment_data, fsntfs_test_buffer_data_handle_data1, 12 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); /* Read buffer on last segment boundary */ read_count = libfsntfs_buffer_data_handle_read_segment_data( buffer_data_handle, NULL, 0, 0, segment_data, 8, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) 4 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( segment_data, &( fsntfs_test_buffer_data_handle_data1[ 12 ] ), 4 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); /* Read buffer beyond last segment */ read_count = libfsntfs_buffer_data_handle_read_segment_data( buffer_data_handle, NULL, 0, 0, segment_data, 16, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ offset = libfsntfs_buffer_data_handle_seek_segment_offset( buffer_data_handle, NULL, 0, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ read_count = libfsntfs_buffer_data_handle_read_segment_data( NULL, NULL, 0, 0, segment_data, 16, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); buffer_data_handle->current_offset = -1; read_count = libfsntfs_buffer_data_handle_read_segment_data( buffer_data_handle, NULL, 0, 0, segment_data, 16, 0, 0, &error ); buffer_data_handle->current_offset = 0; FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_buffer_data_handle_read_segment_data( buffer_data_handle, NULL, -1, 0, segment_data, 16, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_buffer_data_handle_read_segment_data( buffer_data_handle, NULL, 0, 0, NULL, 16, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_buffer_data_handle_read_segment_data( buffer_data_handle, NULL, 0, 0, segment_data, (size_t) SSIZE_MAX + 1, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) && defined( OPTIMIZATION_DISABLED ) /* Test libfsntfs_buffer_data_handle_read_segment_data with memcpy failing */ fsntfs_test_memcpy_attempts_before_fail = 0; read_count = libfsntfs_buffer_data_handle_read_segment_data( buffer_data_handle, NULL, 0, 0, segment_data, 12, 0, 0, &error ); if( fsntfs_test_memcpy_attempts_before_fail != -1 ) { fsntfs_test_memcpy_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) && defined( OPTIMIZATION_DISABLED ) */ /* Clean up */ result = libfsntfs_buffer_data_handle_free( &buffer_data_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "buffer_data_handle", buffer_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( buffer_data_handle != NULL ) { libfsntfs_buffer_data_handle_free( &buffer_data_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_buffer_data_handle_seek_segment_offset function * Returns 1 if successful or 0 if not */ int fsntfs_test_buffer_data_handle_seek_segment_offset( void ) { libcerror_error_t *error = NULL; libfsntfs_buffer_data_handle_t *buffer_data_handle = NULL; off64_t offset = 0; int result = 0; /* Initialize test */ result = libfsntfs_buffer_data_handle_initialize( &buffer_data_handle, fsntfs_test_buffer_data_handle_data1, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "buffer_data_handle", buffer_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ offset = libfsntfs_buffer_data_handle_seek_segment_offset( buffer_data_handle, NULL, 0, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ offset = libfsntfs_buffer_data_handle_seek_segment_offset( NULL, NULL, 0, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); offset = libfsntfs_buffer_data_handle_seek_segment_offset( buffer_data_handle, NULL, -1, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); offset = libfsntfs_buffer_data_handle_seek_segment_offset( buffer_data_handle, NULL, 0, 0, -1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_buffer_data_handle_free( &buffer_data_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "buffer_data_handle", buffer_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( buffer_data_handle != NULL ) { libfsntfs_buffer_data_handle_free( &buffer_data_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_buffer_data_handle_initialize", fsntfs_test_buffer_data_handle_initialize ); FSNTFS_TEST_RUN( "libfsntfs_buffer_data_handle_free", fsntfs_test_buffer_data_handle_free ); FSNTFS_TEST_RUN( "libfsntfs_buffer_data_handle_read_segment_data", fsntfs_test_buffer_data_handle_read_segment_data ); FSNTFS_TEST_RUN( "libfsntfs_buffer_data_handle_seek_segment_offset", fsntfs_test_buffer_data_handle_seek_segment_offset ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_cluster_block.c ================================================ /* * Library cluster_block type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_functions.h" #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_cluster_block.h" uint8_t fsntfs_test_cluster_block_data1[ 1024 ] = { 0x52, 0x21, 0x00, 0x00, 0x53, 0x21, 0x00, 0x00, 0x54, 0x21, 0x00, 0x00, 0x55, 0x21, 0x00, 0x00, 0x56, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_cluster_block_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_cluster_block_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_cluster_block_t *cluster_block = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 2; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_cluster_block_initialize( &cluster_block, 1024, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "cluster_block", cluster_block ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_cluster_block_free( &cluster_block, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block", cluster_block ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_cluster_block_initialize( NULL, 1024, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); cluster_block = (libfsntfs_cluster_block_t *) 0x12345678UL; result = libfsntfs_cluster_block_initialize( &cluster_block, 1024, &error ); cluster_block = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_cluster_block_initialize( &cluster_block, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_cluster_block_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_cluster_block_initialize( &cluster_block, 1024, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( cluster_block != NULL ) { libfsntfs_cluster_block_free( &cluster_block, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block", cluster_block ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_cluster_block_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_cluster_block_initialize( &cluster_block, 1024, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( cluster_block != NULL ) { libfsntfs_cluster_block_free( &cluster_block, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block", cluster_block ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( cluster_block != NULL ) { libfsntfs_cluster_block_free( &cluster_block, NULL ); } return( 0 ); } /* Tests the libfsntfs_cluster_block_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_cluster_block_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_cluster_block_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_cluster_block_clear function * Returns 1 if successful or 0 if not */ int fsntfs_test_cluster_block_clear( void ) { libcerror_error_t *error = NULL; libfsntfs_cluster_block_t *cluster_block = NULL; int result = 0; /* Initialize test */ result = libfsntfs_cluster_block_initialize( &cluster_block, 1024, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "cluster_block", cluster_block ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_cluster_block_clear( cluster_block, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_cluster_block_clear( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) && defined( OPTIMIZATION_DISABLED ) /* Test libfsntfs_cluster_block_clear with memset failing */ fsntfs_test_memset_attempts_before_fail = 0; result = libfsntfs_cluster_block_clear( cluster_block, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) && defined( OPTIMIZATION_DISABLED ) */ /* Clean up */ result = libfsntfs_cluster_block_free( &cluster_block, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block", cluster_block ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( cluster_block != NULL ) { libfsntfs_cluster_block_free( &cluster_block, NULL ); } return( 0 ); } /* Tests the libfsntfs_cluster_block_read_file_io_handle function * Returns 1 if successful or 0 if not */ int fsntfs_test_cluster_block_read_file_io_handle( void ) { libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_cluster_block_t *cluster_block = NULL; int result = 0; /* Initialize test */ result = libfsntfs_cluster_block_initialize( &cluster_block, 1024, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "cluster_block", cluster_block ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize file IO handle */ result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_cluster_block_data1, 1024, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_cluster_block_read_file_io_handle( cluster_block, file_io_handle, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_cluster_block_read_file_io_handle( NULL, file_io_handle, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_cluster_block_read_file_io_handle( cluster_block, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_cluster_block_read_file_io_handle( cluster_block, file_io_handle, -1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up file IO handle */ result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test data too small */ result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_cluster_block_data1, 8, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_cluster_block_read_file_io_handle( cluster_block, file_io_handle, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfsntfs_cluster_block_free( &cluster_block, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block", cluster_block ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } if( cluster_block != NULL ) { libfsntfs_cluster_block_free( &cluster_block, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_cluster_block_initialize", fsntfs_test_cluster_block_initialize ); FSNTFS_TEST_RUN( "libfsntfs_cluster_block_free", fsntfs_test_cluster_block_free ); FSNTFS_TEST_RUN( "libfsntfs_cluster_block_clear", fsntfs_test_cluster_block_clear ); FSNTFS_TEST_RUN( "libfsntfs_cluster_block_read_file_io_handle", fsntfs_test_cluster_block_read_file_io_handle ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_cluster_block_data.c ================================================ /* * Library cluster_block_data type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_functions.h" #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_libfdata.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_cluster_block_data.h" uint8_t fsntfs_test_cluster_block_data1[ 16384 ] = { 0x09, 0x09, 0x20, 0x20, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x45, 0x53, 0x53, 0x45, 0x52, 0x20, 0x47, 0x45, 0x4e, 0x45, 0x52, 0x41, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x2c, 0x20, 0x32, 0x39, 0x20, 0x4a, 0x75, 0x6e, 0x65, 0x20, 0x32, 0x30, 0x30, 0x37, 0x0a, 0x0a, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x43, 0x29, 0x20, 0x32, 0x30, 0x30, 0x37, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x20, 0x3c, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x66, 0x73, 0x66, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x45, 0x76, 0x65, 0x72, 0x79, 0x6f, 0x6e, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x72, 0x62, 0x61, 0x74, 0x69, 0x6d, 0x20, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x0a, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x73, 0x0a, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x0a, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x64, 0x20, 0x62, 0x65, 0x6c, 0x6f, 0x77, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x30, 0x2e, 0x20, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x41, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x2c, 0x20, 0x22, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x0a, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x22, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x22, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x0a, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x22, 0x54, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x22, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x0a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x61, 0x73, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x65, 0x6c, 0x6f, 0x77, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x41, 0x6e, 0x20, 0x22, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x73, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x0a, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x20, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x0a, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x73, 0x75, 0x62, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x69, 0x73, 0x20, 0x64, 0x65, 0x65, 0x6d, 0x65, 0x64, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x0a, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x41, 0x20, 0x22, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x22, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x22, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x0a, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x22, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x2c, 0x20, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x0a, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x72, 0x65, 0x0a, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x22, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x74, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x73, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x31, 0x2e, 0x20, 0x45, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x33, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x34, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x62, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x32, 0x2e, 0x20, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x49, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x0a, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x74, 0x68, 0x61, 0x74, 0x20, 0x75, 0x73, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x28, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x29, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x0a, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x29, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x61, 0x69, 0x74, 0x68, 0x20, 0x65, 0x66, 0x66, 0x6f, 0x72, 0x74, 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x77, 0x68, 0x61, 0x74, 0x65, 0x76, 0x65, 0x72, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x73, 0x20, 0x70, 0x75, 0x72, 0x70, 0x6f, 0x73, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x69, 0x6e, 0x67, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x6f, 0x72, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x29, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x33, 0x2e, 0x20, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x0a, 0x61, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x20, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x0a, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x64, 0x0a, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x0a, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x73, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x0a, 0x28, 0x74, 0x65, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x66, 0x65, 0x77, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x29, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x29, 0x20, 0x47, 0x69, 0x76, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x73, 0x20, 0x75, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x29, 0x20, 0x41, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x34, 0x2e, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x0a, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x20, 0x64, 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x0a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x64, 0x6f, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x0a, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x29, 0x20, 0x47, 0x69, 0x76, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x73, 0x20, 0x75, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x29, 0x20, 0x41, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x29, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x73, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x73, 0x20, 0x64, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x64, 0x29, 0x20, 0x44, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x29, 0x20, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x75, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x36, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x29, 0x20, 0x55, 0x73, 0x65, 0x20, 0x61, 0x20, 0x73, 0x75, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x20, 0x20, 0x41, 0x20, 0x73, 0x75, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x20, 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x28, 0x61, 0x29, 0x20, 0x75, 0x73, 0x65, 0x73, 0x20, 0x61, 0x74, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x27, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x28, 0x62, 0x29, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x6c, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x65, 0x29, 0x20, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x36, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x6e, 0x65, 0x63, 0x65, 0x73, 0x73, 0x61, 0x72, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x28, 0x49, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x34, 0x64, 0x30, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x0a, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x34, 0x64, 0x31, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x36, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x35, 0x2e, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x73, 0x69, 0x64, 0x65, 0x20, 0x62, 0x79, 0x20, 0x73, 0x69, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x0a, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x0a, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x0a, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x29, 0x20, 0x41, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x62, 0x61, 0x73, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x29, 0x20, 0x47, 0x69, 0x76, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x36, 0x2e, 0x20, 0x52, 0x65, 0x76, 0x69, 0x73, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20, 0x72, 0x65, 0x76, 0x69, 0x73, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, 0x6e, 0x65, 0x77, 0x0a, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x69, 0x6d, 0x69, 0x6c, 0x61, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x70, 0x69, 0x72, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6d, 0x61, 0x79, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x20, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x45, 0x61, 0x63, 0x68, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x20, 0x64, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x63, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x22, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x0a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x79, 0x20, 0x61, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x0a, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x68, 0x6f, 0x6f, 0x73, 0x65, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x0a, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x65, 0x76, 0x65, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x0a, 0x77, 0x68, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x27, 0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x0a, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x68, 0x6f, 0x6f, 0x73, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_cluster_block_data_read_segment_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_cluster_block_data_read_segment_data( void ) { uint8_t segment_data[ 16 ]; uint8_t expected_segment_data1[ 12 ] = { 0x09, 0x09, 0x20, 0x20, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x45, 0x53 }; uint8_t expected_segment_data2[ 4 ] = { 0x00, 0x00, 0x00, 0x00 }; libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; ssize_t read_count = 0; off64_t offset = 0; int result = 0; /* Initialize file IO handle */ result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_cluster_block_data1, 16384, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ read_count = libfsntfs_cluster_block_data_read_segment_data( NULL, file_io_handle, 0, 0, segment_data, 12, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) 12 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( segment_data, expected_segment_data1, 12 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); /* Read buffer on last segment boundary */ offset = libfsntfs_cluster_block_data_seek_segment_offset( NULL, file_io_handle, 0, 0, 16384 - 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 16384 - 4 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); read_count = libfsntfs_cluster_block_data_read_segment_data( NULL, file_io_handle, 0, 0, segment_data, 8, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) 4 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( segment_data, expected_segment_data2, 4 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); /* Read buffer beyond last segment */ read_count = libfsntfs_cluster_block_data_read_segment_data( NULL, file_io_handle, 0, 0, segment_data, 16, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ offset = libfsntfs_cluster_block_data_seek_segment_offset( NULL, file_io_handle, 0, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ read_count = libfsntfs_cluster_block_data_read_segment_data( NULL, file_io_handle, 0, 0, segment_data, 12, 0, LIBFDATA_RANGE_FLAG_IS_SPARSE, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) 12 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ offset = libfsntfs_cluster_block_data_seek_segment_offset( NULL, file_io_handle, 0, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ read_count = libfsntfs_cluster_block_data_read_segment_data( NULL, NULL, 0, 0, segment_data, 16, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_cluster_block_data_read_segment_data( NULL, file_io_handle, 0, 0, NULL, 16, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_cluster_block_data_read_segment_data( NULL, file_io_handle, 0, 0, segment_data, (size_t) SSIZE_MAX + 1, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) /* Test libfsntfs_cluster_block_data_read_segment_data with memset failing */ fsntfs_test_memset_attempts_before_fail = 0; read_count = libfsntfs_cluster_block_data_read_segment_data( NULL, file_io_handle, 0, 0, segment_data, 12, 0, LIBFDATA_RANGE_FLAG_IS_SPARSE, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) 12 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up file IO handle */ result = libbfio_handle_free( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_cluster_block_data_seek_segment_offset function * Returns 1 if successful or 0 if not */ int fsntfs_test_cluster_block_data_seek_segment_offset( void ) { libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; off64_t offset = 0; int result = 0; /* Initialize file IO handle */ result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_cluster_block_data1, 16384, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ offset = libfsntfs_cluster_block_data_seek_segment_offset( NULL, file_io_handle, 0, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ offset = libfsntfs_cluster_block_data_seek_segment_offset( NULL, NULL, 0, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); offset = libfsntfs_cluster_block_data_seek_segment_offset( NULL, file_io_handle, 0, 0, -1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up file IO handle */ result = libbfio_handle_free( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_cluster_block_data_read_segment_data", fsntfs_test_cluster_block_data_read_segment_data ); FSNTFS_TEST_RUN( "libfsntfs_cluster_block_data_seek_segment_offset", fsntfs_test_cluster_block_data_seek_segment_offset ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_cluster_block_stream.c ================================================ /* * Library cluster_block_stream type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfdata.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_cluster_block_stream.h" #include "../libfsntfs/libfsntfs_definitions.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" uint8_t fsntfs_test_cluster_block_stream_data1[ 72 ] = { 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t fsntfs_test_cluster_block_stream_data2[ 80 ] = { 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x01, 0x01, 0x0e, 0x00, 0x00, 0x00 }; uint8_t fsntfs_test_cluster_block_stream_data3[ 112 ] = { 0x80, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x01, 0x11, 0x40, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x65, 0x00, 0x64, 0x00, 0x44, 0x00, 0x61, 0x00, 0x74, 0x00, 0x61, 0x00, 0x11, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_cluster_block_stream_initialize_from_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_cluster_block_stream_initialize_from_data( void ) { uint8_t buffer[ 64 ]; libcerror_error_t *error = NULL; libfdata_stream_t *cluster_block_stream = NULL; void *memset_result = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 2; int test_number = 0; #endif /* Initialize test */ memset_result = memory_set( buffer, 0, 64 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "memset_result", memset_result ); /* Test regular cases */ result = libfsntfs_cluster_block_stream_initialize_from_data( &cluster_block_stream, buffer, 64, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfdata_stream_free( &cluster_block_stream, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block_stream", cluster_block_stream ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_cluster_block_stream_initialize_from_data( NULL, buffer, 64, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_cluster_block_stream_initialize_from_data( &cluster_block_stream, NULL, 64, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_cluster_block_stream_initialize_from_data( &cluster_block_stream, buffer, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_cluster_block_stream_initialize_from_data with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_cluster_block_stream_initialize_from_data( &cluster_block_stream, buffer, 64, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( cluster_block_stream != NULL ) { libfdata_stream_free( &cluster_block_stream, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block_stream", cluster_block_stream ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( cluster_block_stream != NULL ) { libfdata_stream_free( &cluster_block_stream, NULL ); } return( 0 ); } /* Tests the libfsntfs_cluster_block_stream_initialize_from_data_runs function * Returns 1 if successful or 0 if not */ int fsntfs_test_cluster_block_stream_initialize_from_data_runs( void ) { libcerror_error_t *error = NULL; libfdata_stream_t *cluster_block_stream = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int test_number = 0; #endif /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_cluster_block_stream_data1, 72, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_cluster_block_stream_initialize_from_data_runs( &cluster_block_stream, io_handle, mft_attribute, 4096, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfdata_stream_free( &cluster_block_stream, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block_stream", cluster_block_stream ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_cluster_block_stream_initialize_from_data_runs( NULL, io_handle, mft_attribute, 4096, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_cluster_block_stream_initialize_from_data_runs( &cluster_block_stream, NULL, mft_attribute, 4096, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); io_handle->cluster_block_size = 0; result = libfsntfs_cluster_block_stream_initialize_from_data_runs( &cluster_block_stream, io_handle, mft_attribute, 4096, &error ); io_handle->cluster_block_size = 4096; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_cluster_block_stream_initialize_from_data_runs( &cluster_block_stream, io_handle, NULL, 4096, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_cluster_block_stream_initialize_from_data_runs with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_cluster_block_stream_initialize_from_data_runs( &cluster_block_stream, io_handle, mft_attribute, 4096, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( cluster_block_stream != NULL ) { libfdata_stream_free( &cluster_block_stream, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block_stream", cluster_block_stream ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( cluster_block_stream != NULL ) { libfdata_stream_free( &cluster_block_stream, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_cluster_block_stream_initialize_from_compressed_data_runs function * Returns 1 if successful or 0 if not */ int fsntfs_test_cluster_block_stream_initialize_from_compressed_data_runs( void ) { libcerror_error_t *error = NULL; libfdata_stream_t *cluster_block_stream = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 2; int test_number = 0; #endif /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_cluster_block_stream_data2, 80, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_cluster_block_stream_initialize_from_compressed_data_runs( &cluster_block_stream, io_handle, mft_attribute, 4096, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfdata_stream_free( &cluster_block_stream, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block_stream", cluster_block_stream ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_cluster_block_stream_initialize_from_compressed_data_runs( NULL, io_handle, mft_attribute, 4096, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_cluster_block_stream_initialize_from_compressed_data_runs( &cluster_block_stream, NULL, mft_attribute, 4096, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_cluster_block_stream_initialize_from_compressed_data_runs( &cluster_block_stream, io_handle, NULL, 4096, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_cluster_block_stream_initialize_from_compressed_data_runs with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_cluster_block_stream_initialize_from_compressed_data_runs( &cluster_block_stream, io_handle, mft_attribute, 4096, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( cluster_block_stream != NULL ) { libfdata_stream_free( &cluster_block_stream, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block_stream", cluster_block_stream ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( cluster_block_stream != NULL ) { libfdata_stream_free( &cluster_block_stream, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_cluster_block_stream_initialize_from_compressed_stream function * Returns 1 if successful or 0 if not */ int fsntfs_test_cluster_block_stream_initialize_from_compressed_stream( void ) { uint8_t buffer[ 64 ]; libcerror_error_t *error = NULL; libfdata_stream_t *cluster_block_stream = NULL; libfdata_stream_t *compressed_data_stream = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 2; int test_number = 0; #endif /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_cluster_block_stream_data2, 80, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_cluster_block_stream_initialize_from_data( &compressed_data_stream, buffer, 64, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_cluster_block_stream_initialize_from_compressed_stream( &cluster_block_stream, compressed_data_stream, mft_attribute, LIBFSNTFS_COMPRESSION_METHOD_LZXPRESS_HUFFMAN, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); compressed_data_stream = NULL; /* Clean up */ result = libfdata_stream_free( &cluster_block_stream, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block_stream", cluster_block_stream ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ result = libfsntfs_cluster_block_stream_initialize_from_data( &compressed_data_stream, buffer, 64, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_cluster_block_stream_initialize_from_compressed_stream( NULL, compressed_data_stream, mft_attribute, LIBFSNTFS_COMPRESSION_METHOD_LZXPRESS_HUFFMAN, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_cluster_block_stream_initialize_from_compressed_stream( &cluster_block_stream, NULL, mft_attribute, LIBFSNTFS_COMPRESSION_METHOD_LZXPRESS_HUFFMAN, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_cluster_block_stream_initialize_from_compressed_stream( &cluster_block_stream, compressed_data_stream, NULL, LIBFSNTFS_COMPRESSION_METHOD_LZXPRESS_HUFFMAN, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_cluster_block_stream_initialize_from_compressed_stream with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_cluster_block_stream_initialize_from_compressed_stream( &cluster_block_stream, compressed_data_stream, mft_attribute, LIBFSNTFS_COMPRESSION_METHOD_LZXPRESS_HUFFMAN, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( cluster_block_stream != NULL ) { libfdata_stream_free( &cluster_block_stream, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block_stream", cluster_block_stream ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfdata_stream_free( &compressed_data_stream, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_data_stream", compressed_data_stream ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( cluster_block_stream != NULL ) { libfdata_stream_free( &cluster_block_stream, NULL ); } if( compressed_data_stream != NULL ) { libfdata_stream_free( &compressed_data_stream, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_cluster_block_stream_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_cluster_block_stream_initialize( void ) { libcerror_error_t *error = NULL; libfdata_stream_t *cluster_block_stream = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int test_number = 0; #endif /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_cluster_block_stream_data2, 80, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_cluster_block_stream_initialize( &cluster_block_stream, io_handle, mft_attribute, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfdata_stream_free( &cluster_block_stream, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block_stream", cluster_block_stream ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_cluster_block_stream_initialize( NULL, io_handle, mft_attribute, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_cluster_block_stream_initialize( &cluster_block_stream, NULL, mft_attribute, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_cluster_block_stream_initialize( &cluster_block_stream, io_handle, NULL, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_cluster_block_stream_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_cluster_block_stream_initialize( &cluster_block_stream, io_handle, mft_attribute, NULL, 0, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( cluster_block_stream != NULL ) { libfdata_stream_free( &cluster_block_stream, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block_stream", cluster_block_stream ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( cluster_block_stream != NULL ) { libfdata_stream_free( &cluster_block_stream, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_cluster_block_stream_initialize_from_data", fsntfs_test_cluster_block_stream_initialize_from_data ); FSNTFS_TEST_RUN( "libfsntfs_cluster_block_stream_initialize_from_data_runs", fsntfs_test_cluster_block_stream_initialize_from_data_runs ); FSNTFS_TEST_RUN( "libfsntfs_cluster_block_stream_initialize_from_compressed_data_runs", fsntfs_test_cluster_block_stream_initialize_from_compressed_data_runs ); FSNTFS_TEST_RUN( "libfsntfs_cluster_block_stream_initialize_from_compressed_stream", fsntfs_test_cluster_block_stream_initialize_from_compressed_stream ); FSNTFS_TEST_RUN( "libfsntfs_cluster_block_stream_initialize", fsntfs_test_cluster_block_stream_initialize ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_cluster_block_vector.c ================================================ /* * Library cluster_block_vector type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_functions.h" #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfcache.h" #include "fsntfs_test_libfdata.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_cluster_block_vector.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" uint8_t fsntfs_test_cluster_block_vector_data1[ 72 ] = { 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t fsntfs_test_cluster_block_vector_data2[ 24576 ] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x20, 0x20, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x45, 0x53, 0x53, 0x45, 0x52, 0x20, 0x47, 0x45, 0x4e, 0x45, 0x52, 0x41, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x2c, 0x20, 0x32, 0x39, 0x20, 0x4a, 0x75, 0x6e, 0x65, 0x20, 0x32, 0x30, 0x30, 0x37, 0x0a, 0x0a, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x43, 0x29, 0x20, 0x32, 0x30, 0x30, 0x37, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x20, 0x3c, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x66, 0x73, 0x66, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x45, 0x76, 0x65, 0x72, 0x79, 0x6f, 0x6e, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x72, 0x62, 0x61, 0x74, 0x69, 0x6d, 0x20, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x0a, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x73, 0x0a, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x0a, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x64, 0x20, 0x62, 0x65, 0x6c, 0x6f, 0x77, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x30, 0x2e, 0x20, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x41, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x2c, 0x20, 0x22, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x0a, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x22, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x22, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x0a, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x22, 0x54, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x22, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x0a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x61, 0x73, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x65, 0x6c, 0x6f, 0x77, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x41, 0x6e, 0x20, 0x22, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x73, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x0a, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x20, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x0a, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x73, 0x75, 0x62, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x69, 0x73, 0x20, 0x64, 0x65, 0x65, 0x6d, 0x65, 0x64, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x0a, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x41, 0x20, 0x22, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x22, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x22, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x0a, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x22, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x2c, 0x20, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x0a, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x72, 0x65, 0x0a, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x22, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x74, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x73, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x31, 0x2e, 0x20, 0x45, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x33, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x34, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x62, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x32, 0x2e, 0x20, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x49, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x0a, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x74, 0x68, 0x61, 0x74, 0x20, 0x75, 0x73, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x28, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x29, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x0a, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x29, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x61, 0x69, 0x74, 0x68, 0x20, 0x65, 0x66, 0x66, 0x6f, 0x72, 0x74, 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x77, 0x68, 0x61, 0x74, 0x65, 0x76, 0x65, 0x72, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x73, 0x20, 0x70, 0x75, 0x72, 0x70, 0x6f, 0x73, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x69, 0x6e, 0x67, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x6f, 0x72, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x29, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x33, 0x2e, 0x20, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x0a, 0x61, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x20, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x0a, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x64, 0x0a, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x0a, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x73, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x0a, 0x28, 0x74, 0x65, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x66, 0x65, 0x77, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x29, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x29, 0x20, 0x47, 0x69, 0x76, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x73, 0x20, 0x75, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x29, 0x20, 0x41, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x34, 0x2e, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x0a, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x20, 0x64, 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x0a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x64, 0x6f, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x0a, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x29, 0x20, 0x47, 0x69, 0x76, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x73, 0x20, 0x75, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x29, 0x20, 0x41, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x29, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x73, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x73, 0x20, 0x64, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x64, 0x29, 0x20, 0x44, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x29, 0x20, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x75, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x36, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x29, 0x20, 0x55, 0x73, 0x65, 0x20, 0x61, 0x20, 0x73, 0x75, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x20, 0x20, 0x41, 0x20, 0x73, 0x75, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x20, 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x28, 0x61, 0x29, 0x20, 0x75, 0x73, 0x65, 0x73, 0x20, 0x61, 0x74, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x27, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x28, 0x62, 0x29, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x6c, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x65, 0x29, 0x20, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x36, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x6e, 0x65, 0x63, 0x65, 0x73, 0x73, 0x61, 0x72, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x28, 0x49, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x34, 0x64, 0x30, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x0a, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x34, 0x64, 0x31, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x36, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x35, 0x2e, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x73, 0x69, 0x64, 0x65, 0x20, 0x62, 0x79, 0x20, 0x73, 0x69, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x0a, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x0a, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x0a, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x29, 0x20, 0x41, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x62, 0x61, 0x73, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x29, 0x20, 0x47, 0x69, 0x76, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x36, 0x2e, 0x20, 0x52, 0x65, 0x76, 0x69, 0x73, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20, 0x72, 0x65, 0x76, 0x69, 0x73, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, 0x6e, 0x65, 0x77, 0x0a, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x69, 0x6d, 0x69, 0x6c, 0x61, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x70, 0x69, 0x72, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6d, 0x61, 0x79, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x20, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x45, 0x61, 0x63, 0x68, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x20, 0x64, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x63, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x22, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x0a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x79, 0x20, 0x61, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x0a, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x68, 0x6f, 0x6f, 0x73, 0x65, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x0a, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x65, 0x76, 0x65, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x0a, 0x77, 0x68, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x27, 0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x0a, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x68, 0x6f, 0x6f, 0x73, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_cluster_block_vector_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_cluster_block_vector_initialize( void ) { libcerror_error_t *error = NULL; libfdata_vector_t *cluster_block_vector = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_cluster_block_vector_data1, 72, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_cluster_block_vector_initialize( &cluster_block_vector, io_handle, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "cluster_block_vector", cluster_block_vector ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfdata_vector_free( &cluster_block_vector, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block_vector", cluster_block_vector ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_cluster_block_vector_initialize( NULL, io_handle, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); cluster_block_vector = (libfdata_vector_t *) 0x12345678UL; result = libfsntfs_cluster_block_vector_initialize( &cluster_block_vector, io_handle, mft_attribute, &error ); cluster_block_vector = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); io_handle->cluster_block_size = 0; result = libfsntfs_cluster_block_vector_initialize( &cluster_block_vector, io_handle, mft_attribute, &error ); io_handle->cluster_block_size = 4096; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_cluster_block_vector_initialize( &cluster_block_vector, NULL, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_cluster_block_vector_initialize( &cluster_block_vector, io_handle, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* TODO test with LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK set */ #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_cluster_block_vector_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_cluster_block_vector_initialize( &cluster_block_vector, io_handle, mft_attribute, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( cluster_block_vector != NULL ) { libfdata_vector_free( &cluster_block_vector, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block_vector", cluster_block_vector ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_cluster_block_vector_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_cluster_block_vector_initialize( &cluster_block_vector, io_handle, mft_attribute, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( cluster_block_vector != NULL ) { libfdata_vector_free( &cluster_block_vector, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block_vector", cluster_block_vector ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( cluster_block_vector != NULL ) { libfdata_vector_free( &cluster_block_vector, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_cluster_block_vector_read_element_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_cluster_block_vector_read_element_data( void ) { libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfcache_cache_t *cache = NULL; libfdata_vector_t *cluster_block_vector = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_cluster_block_vector_data1, 72, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_cluster_block_vector_initialize( &cluster_block_vector, io_handle, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "cluster_block_vector", cluster_block_vector ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfcache_cache_initialize( &cache, 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "cache", cache ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize file IO handle */ result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_cluster_block_vector_data2, 24576, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_cluster_block_vector_read_element_data( NULL, file_io_handle, cluster_block_vector, (libfdata_cache_t *) cache, 0, 0, 0, 4096, LIBFDATA_RANGE_FLAG_IS_SPARSE, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_cluster_block_vector_read_element_data( NULL, file_io_handle, cluster_block_vector, (libfdata_cache_t *) cache, 0, 0, 0, 4096, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_cluster_block_vector_read_element_data( NULL, file_io_handle, cluster_block_vector, (libfdata_cache_t *) cache, 0, 0, 0, 0, LIBFDATA_RANGE_FLAG_IS_SPARSE, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_cluster_block_vector_read_element_data( NULL, file_io_handle, cluster_block_vector, (libfdata_cache_t *) cache, 0, 0, 0, (size64_t) SSIZE_MAX + 1, LIBFDATA_RANGE_FLAG_IS_SPARSE, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_cluster_block_vector_read_element_data( NULL, file_io_handle, NULL, (libfdata_cache_t *) cache, 0, 0, 0, 4096, LIBFDATA_RANGE_FLAG_IS_SPARSE, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* TODO implement read from file IO handle failing */ #if defined( HAVE_FSNTFS_TEST_MEMORY ) /* Test libfsntfs_cluster_block_vector_read_element_data with malloc failing in libfsntfs_cluster_block_initialize */ fsntfs_test_malloc_attempts_before_fail = 0; result = libfsntfs_cluster_block_vector_read_element_data( NULL, file_io_handle, cluster_block_vector, (libfdata_cache_t *) cache, 0, 0, 0, 4096, LIBFDATA_RANGE_FLAG_IS_SPARSE, 0, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #if defined( OPTIMIZATION_DISABLED ) /* Test libfsntfs_cluster_block_vector_read_element_data with memset failing in libfsntfs_cluster_block_clear */ fsntfs_test_memset_attempts_before_fail = 0; result = libfsntfs_cluster_block_vector_read_element_data( NULL, file_io_handle, cluster_block_vector, (libfdata_cache_t *) cache, 0, 0, 0, 4096, LIBFDATA_RANGE_FLAG_IS_SPARSE, 0, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( OPTIMIZATION_DISABLED ) */ #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up file IO handle */ result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfcache_cache_free( &cache, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cache", cache ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfdata_vector_free( &cluster_block_vector, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cluster_block_vector", cluster_block_vector ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } if( cache != NULL ) { libfcache_cache_free( &cache, NULL ); } if( cluster_block_vector != NULL ) { libfdata_vector_free( &cluster_block_vector, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_cluster_block_vector_initialize", fsntfs_test_cluster_block_vector_initialize ); FSNTFS_TEST_RUN( "libfsntfs_cluster_block_vector_read_element_data", fsntfs_test_cluster_block_vector_read_element_data ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_compressed_block.c ================================================ /* * Library compressed_block type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_compressed_block.h" #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_compressed_block_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_compressed_block_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_compressed_block_t *compressed_block = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 2; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_compressed_block_initialize( &compressed_block, 1024, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "compressed_block", compressed_block ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_compressed_block_free( &compressed_block, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_block", compressed_block ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_compressed_block_initialize( NULL, 1024, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); compressed_block = (libfsntfs_compressed_block_t *) 0x12345678UL; result = libfsntfs_compressed_block_initialize( &compressed_block, 1024, &error ); compressed_block = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_compressed_block_initialize( &compressed_block, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_compressed_block_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_compressed_block_initialize( &compressed_block, 1024, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( compressed_block != NULL ) { libfsntfs_compressed_block_free( &compressed_block, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_block", compressed_block ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_compressed_block_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_compressed_block_initialize( &compressed_block, 1024, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( compressed_block != NULL ) { libfsntfs_compressed_block_free( &compressed_block, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_block", compressed_block ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( compressed_block != NULL ) { libfsntfs_compressed_block_free( &compressed_block, NULL ); } return( 0 ); } /* Tests the libfsntfs_compressed_block_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_compressed_block_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_compressed_block_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_compressed_block_initialize", fsntfs_test_compressed_block_initialize ); FSNTFS_TEST_RUN( "libfsntfs_compressed_block_free", fsntfs_test_compressed_block_free ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_compressed_block_data_handle.c ================================================ /* * Library compressed_block_data_handle type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_functions.h" #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_compressed_block_data_handle.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" uint8_t fsntfs_test_compressed_block_data_handle_data1[ 80 ] = { 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x01, 0x01, 0x0e, 0x00, 0x00, 0x00 }; uint8_t fsntfs_test_compressed_block_data_handle_lznt1_compressed_data1[ 24576 ] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0xb8, 0x00, 0x09, 0x09, 0x20, 0x20, 0x20, 0x47, 0x4e, 0x55, 0x00, 0x20, 0x4c, 0x45, 0x53, 0x53, 0x45, 0x52, 0x20, 0x00, 0x47, 0x45, 0x4e, 0x45, 0x52, 0x41, 0x4c, 0x20, 0x80, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x00, 0x18, 0x60, 0x45, 0x4e, 0x53, 0x45, 0x0a, 0x00, 0x90, 0x11, 0x08, 0x56, 0x00, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x00, 0x2c, 0x20, 0x32, 0x39, 0x20, 0x4a, 0x75, 0x6e, 0x00, 0x65, 0x20, 0x32, 0x30, 0x30, 0x37, 0x0a, 0x0a, 0x00, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x40, 0x68, 0x74, 0x20, 0x28, 0x43, 0x29, 0x02, 0x28, 0x20, 0x00, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x00, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x20, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x00, 0x7a, 0x2c, 0x20, 0x00, 0x49, 0x6e, 0x63, 0x2e, 0x20, 0x3c, 0x68, 0x74, 0x00, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x66, 0x73, 0x66, 0x00, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x40, 0x45, 0x76, 0x65, 0x72, 0x79, 0x6f, 0x00, 0x54, 0x69, 0x00, 0x73, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x00, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x01, 0x00, 0x5d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x00, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2a, 0x20, 0x00, 0x2b, 0x62, 0x00, 0x4f, 0x6d, 0x01, 0x1c, 0x69, 0x65, 0x00, 0x73, 0x0a, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x01, 0x00, 0x39, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x00, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x08, 0x74, 0x2c, 0x20, 0x00, 0x2f, 0x20, 0x63, 0x68, 0x61, 0x00, 0x6e, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, 0x02, 0x20, 0x00, 0x12, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x6c, 0x80, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x2e, 0x0a, 0x80, 0x5f, 0xbc, 0x20, 0x54, 0x01, 0x1d, 0x80, 0x29, 0x82, 0x6f, 0x02, 0x25, 0x65, 0x83, 0x93, 0x00, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x00, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x12, 0x62, 0x80, 0x2f, 0x20, 0x4c, 0x84, 0x31, 0x69, 0x6e, 0x63, 0x80, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x80, 0x40, 0xa0, 0x74, 0x68, 0x65, 0x20, 0x74, 0x00, 0x5b, 0x73, 0x02, 0x55, 0xa0, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x81, 0x77, 0x73, 0x81, 0x4c, 0x5d, 0x85, 0x2c, 0x33, 0x03, 0x53, 0x83, 0x2d, 0x0b, 0x2a, 0x0a, 0x04, 0x2a, 0x2c, 0x80, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x65, 0x81, 0x5d, 0x09, 0x00, 0x7f, 0x62, 0x79, 0x00, 0x6b, 0x65, 0x20, 0x61, 0x64, 0x17, 0x83, 0x26, 0x80, 0x41, 0x02, 0x8d, 0x73, 0x01, 0x54, 0x73, 0x20, 0x6c, 0x1b, 0x00, 0x88, 0x01, 0x12, 0x65, 0x00, 0x65, 0x00, 0x64, 0x20, 0x20, 0x30, 0x08, 0x2e, 0x20, 0x41, 0x07, 0x15, 0x44, 0x65, 0x66, 0x69, 0x06, 0x6e, 0x83, 0x42, 0x82, 0x0e, 0x41, 0x73, 0x20, 0x75, 0x73, 0x01, 0xc0, 0x0b, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x2c, 0x0c, 0x20, 0x22, 0x42, 0x4c, 0x04, 0x1e, 0x22, 0x20, 0x72, 0x65, 0xae, 0x66, 0x40, 0x78, 0x41, 0x5c, 0xd2, 0x2b, 0x4c, 0xc2, 0x42, 0x0a, 0xd3, 0x42, 0x16, 0x2c, 0x42, 0x3d, 0xc1, 0x40, 0x22, 0xc1, 0x97, 0x47, 0x50, 0x4c, 0x27, 0xdd, 0x13, 0x14, 0x12, 0x02, 0x2a, 0x22, 0x54, 0x00, 0x53, 0x4c, 0x69, 0xa0, 0x62, 0x72, 0x61, 0x72, 0x79, 0xc9, 0x11, 0x61, 0x80, 0x7b, 0x03, 0xc0, 0x26, 0x80, 0x30, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x67, 0x7a, 0x6f, 0x00, 0x03, 0x6e, 0x40, 0x03, 0x42, 0x49, 0xc0, 0x75, 0xc5, 0x50, 0x0a, 0x4a, 0x6f, 0x40, 0x22, 0x72, 0x40, 0x4e, 0x61, 0x6e, 0xc0, 0x25, 0x20, 0x12, 0x41, 0x00, 0x54, 0x69, 0x63, 0x82, 0x9f, 0x20, 0x6f, 0x72, 0x44, 0x20, 0x61, 0xc0, 0xab, 0x6d, 0x62, 0x69, 0x01, 0x0e, 0x57, 0xe1, 0x81, 0x11, 0x61, 0x73, 0x20, 0x64, 0x41, 0x4a, 0x01, 0x12, 0x46, 0x52, 0x50, 0x41, 0x6e, 0x20, 0x22, 0xc8, 0x0d, 0x22, 0x81, 0x8d, 0x61, 0x08, 0x6e, 0x79, 0x20, 0x02, 0x1e, 0x74, 0x68, 0x61, 0x74, 0xe0, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x02, 0x54, 0x01, 0x75, 0x00, 0x1a, 0x04, 0x69, 0x6e, 0x80, 0x7f, 0x66, 0x61, 0x63, 0x65, 0x20, 0x00, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x0e, 0x0a, 0x44, 0x6f, 0x44, 0x32, 0x83, 0xa2, 0x77, 0x68, 0x69, 0x63, 0x26, 0x68, 0x05, 0xa1, 0xc2, 0x29, 0x77, 0x69, 0xc0, 0xab, 0x62, 0x61, 0x4f, 0x41, 0x66, 0x40, 0xd7, 0xc1, 0x50, 0x04, 0x0c, 0x2e, 0x0a, 0x43, 0x70, 0x6e, 0x02, 0x67, 0xc0, 0x2c, 0x73, 0x75, 0x62, 0x63, 0x6c, 0x61, 0xfe, 0x73, 0xc2, 0x93, 0xc0, 0x41, 0x82, 0x02, 0x86, 0x2d, 0x43, 0x89, 0x84, 0x0d, 0x01, 0x17, 0x14, 0x64, 0x65, 0x40, 0x90, 0x64, 0x80, 0x0d, 0x6d, 0x6f, 0x64, 0x64, 0x65, 0x0a, 0x40, 0xb4, 0x75, 0x73, 0x81, 0xbf, 0xd2, 0x14, 0x20, 0xc3, 0xcb, 0x14, 0x43, 0x45, 0x20, 0x22, 0x43, 0x6f, 0x88, 0x24, 0xe3, 0x1f, 0xa3, 0xa3, 0x1f, 0xc0, 0x1b, 0x64, 0x75, 0x63, 0xc3, 0x2e, 0x63, 0x82, 0x04, 0x43, 0x41, 0x0b, 0x00, 0x2b, 0x6c, 0x69, 0x6e, 0x6b, 0xa3, 0x0c, 0x0a, 0xa1, 0x49, 0x2e, 0x77, 0x69, 0x74, 0x68, 0x60, 0x31, 0x65, 0xe0, 0x66, 0x19, 0x22, 0x3a, 0x2e, 0x20, 0xe0, 0x6d, 0xa0, 0x24, 0x61, 0x72, 0x74, 0xc0, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, 0xa1, 0x79, 0x29, 0x6f, 0x3d, 0xe4, 0x18, 0x0a, 0x02, 0x07, 0xe3, 0x25, 0xa1, 0x22, 0x0a, 0x12, 0x20, 0x77, 0x21, 0xc0, 0x36, 0x6d, 0x61, 0x64, 0x65, 0xa1, 0x1d, 0x61, 0x6c, 0x9e, 0x73, 0xc0, 0x84, 0x20, 0x7a, 0x80, 0x12, 0x21, 0x05, 0x22, 0x4c, 0x20, 0x11, 0x9b, 0xe0, 0x2f, 0x24, 0x96, 0x22, 0x42, 0x1a, 0x61, 0x4a, 0x22, 0x4d, 0x00, 0x62, 0x02, 0x6d, 0xa0, 0x68, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x06, 0x70, 0xa1, 0x74, 0xa0, 0x2b, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x10, 0x65, 0x22, 0x20, 0x66, 0xb0, 0x43, 0x6d, 0x65, 0x61, 0x74, 0x6e, 0x73, 0xc1, 0x17, 0x0a, 0x71, 0x06, 0x42, 0x06, 0x8e, 0x13, 0x2c, 0x80, 0x20, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x83, 0x21, 0xf8, 0x79, 0x20, 0x73, 0xe2, 0x0b, 0x80, 0x57, 0x60, 0x31, 0x61, 0x0c, 0x60, 0x86, 0xb7, 0x66, 0x83, 0x8e, 0x07, 0x60, 0x0d, 0x61, 0xc0, 0x96, 0x20, 0x88, 0x73, 0x80, 0x48, 0x92, 0x72, 0x40, 0x1a, 0x69, 0x6e, 0x80, 0x1c, 0x6f, 0x6c, 0x02, 0x58, 0xf1, 0x00, 0x6d, 0x72, 0x65, 0x0a, 0xaa, 0x45, 0x68, 0x2d, 0xc3, 0x70, 0xc1, 0x9b, 0xf9, 0x26, 0x49, 0x6e, 0x6b, 0x20, 0x08, 0x04, 0x21, 0xe7, 0x20, 0x6b, 0x19, 0xa9, 0x35, 0x06, 0x43, 0x00, 0x46, 0x3d, 0x21, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0xf6, 0x74, 0xe2, 0x19, 0xe1, 0x7e, 0x2f, 0xc0, 0x26, 0x48, 0x1c, 0x66, 0x22, 0x0a, 0x13, 0x27, 0x80, 0xa5, 0x28, 0x22, 0x80, 0xc1, 0x61, 0x0a, 0x61, 0xba, 0x75, 0x74, 0x20, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x61, 0x66, 0x67, 0x72, 0x80, 0x61, 0x6d, 0x73, 0x20, 0x6e, 0x65, 0x65, 0x40, 0x67, 0x39, 0x62, 0x08, 0x72, 0x65, 0x43, 0x4d, 0xc1, 0x28, 0xcf, 0x24, 0x66, 0x72, 0x7c, 0x6f, 0x6d, 0xe2, 0x32, 0xca, 0x0c, 0xa1, 0xbd, 0x87, 0x2f, 0xa1, 0x06, 0x53, 0xe0, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x84, 0x4f, 0x60, 0xc5, 0x65, 0xb0, 0x03, 0xca, 0x49, 0x22, 0x23, 0x31, 0x2e, 0x20, 0x45, 0x78, 0x63, 0xec, 0x65, 0x70, 0x61, 0x33, 0xc1, 0xa0, 0x53, 0x80, 0x1c, 0x02, 0xde, 0x45, 0x06, 0xa3, 0x44, 0x9b, 0x82, 0x05, 0x59, 0x6f, 0x75, 0x40, 0x80, 0x79, 0x80, 0x20, 0xd0, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x6d, 0x63, 0xa1, 0x91, 0x60, 0x2d, 0x17, 0x22, 0x84, 0xc0, 0xdd, 0xe0, 0xc6, 0x73, 0x03, 0x08, 0x73, 0x20, 0x33, 0x39, 0xc1, 0x24, 0x20, 0x34, 0xe3, 0x08, 0x07, 0x95, 0x22, 0x5c, 0x6f, 0x75, 0xd0, 0x74, 0x20, 0x62, 0x65, 0x61, 0x1c, 0x62, 0xa1, 0xe4, 0xa1, 0x71, 0x9f, 0xe4, 0x06, 0xc0, 0x06, 0x68, 0xd1, 0x60, 0xaa, 0x02, 0x0f, 0x32, 0x2e, 0xe0, 0x97, 0x03, 0x61, 0x0e, 0x41, 0x06, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x85, 0x27, 0x3c, 0x73, 0x42, 0x04, 0x49, 0x66, 0x20, 0x79, 0xc1, 0x13, 0x73, 0x81, 0x03, 0x43, 0x13, 0x70, 0x79, 0x65, 0x18, 0xc4, 0x35, 0x92, 0x22, 0x2c, 0xe6, 0x20, 0xa0, 0x25, 0x90, 0x02, 0x72, 0x20, 0x60, 0x42, 0x70, 0x04, 0x33, 0x52, 0x3a, 0x73, 0xb0, 0x01, 0x0a, 0x80, 0x4c, 0x83, 0x19, 0x57, 0x61, 0x61, 0x20, 0xf0, 0x66, 0x75, 0x6e, 0x63, 0xc2, 0x11, 0x00, 0x1f, 0x11, 0x1c, 0x41, 0x12, 0x7c, 0x62, 0x65, 0x13, 0x6b, 0x41, 0x08, 0x80, 0x44, 0x10, 0x46, 0xf8, 0x18, 0x0a, 0xd7, 0x92, 0x52, 0x40, 0x67, 0x12, 0x34, 0x20, 0x46, 0x05, 0x28, 0x09, 0x5a, 0x11, 0x73, 0x90, 0x20, 0x61, 0x72, 0x67, 0xf2, 0x7a, 0x20, 0x70, 0x30, 0x4e, 0x71, 0x51, 0x14, 0x68, 0x65, 0x6e, 0xd2, 0x1d, 0x36, 0x03, 0x60, 0x13, 0x69, 0x48, 0x6e, 0x76, 0x6f, 0xe0, 0x2c, 0x29, 0x2c, 0x91, 0x01, 0x6e, 0xfd, 0x33, 0x0e, 0x61, 0x2a, 0x18, 0x77, 0x0e, 0x13, 0x0d, 0x40, 0x40, 0x30, 0x62, 0xc1, 0x45, 0xc2, 0x3a, 0x71, 0x7e, 0x20, 0x61, 0x29, 0x20, 0xa3, 0x19, 0xa9, 0x6f, 0x7e, 0x2c, 0x16, 0x5b, 0x70, 0x05, 0x90, 0x5d, 0xb2, 0x13, 0xd0, 0x5d, 0x40, 0x1d, 0x67, 0x98, 0x6f, 0x6f, 0x64, 0x60, 0x0b, 0x11, 0x4c, 0x65, 0x66, 0xa0, 0x3b, 0xee, 0x74, 0x20, 0x0f, 0xf1, 0x91, 0x30, 0x86, 0x75, 0x70, 0x8d, 0xe1, 0x0d, 0x42, 0x14, 0x39, 0x81, 0x26, 0x65, 0x76, 0xf0, 0x86, 0x80, 0x1e, 0xfa, 0x66, 0x64, 0x6f, 0xff, 0x40, 0x62, 0x01, 0x39, 0x62, 0x7d, 0x72, 0x5a, 0xf1, 0x03, 0x9d, 0x14, 0x12, 0x0d, 0xf7, 0x11, 0xa2, 0x73, 0x50, 0x31, 0x6c, 0x20, 0x6f, 0xb0, 0x7e, 0x61, 0xb0, 0x85, 0x17, 0xb2, 0x1a, 0x31, 0x91, 0x00, 0x08, 0x6d, 0xb0, 0x8e, 0x20, 0x20, 0x77, 0x4b, 0x00, 0x68, 0xe0, 0x06, 0x72, 0xd0, 0x12, 0x72, 0x74, 0x91, 0x1d, 0x69, 0x1a, 0x74, 0x40, 0x93, 0x75, 0xc0, 0x88, 0xa0, 0x64, 0x72, 0x65, 0x6d, 0x1c, 0x61, 0x69, 0x30, 0x4b, 0x91, 0x4b, 0x30, 0x22, 0x66, 0x75, 0x6c, 0x36, 0x2c, 0x60, 0x6f, 0xe2, 0x0f, 0x62, 0xe7, 0x0f, 0x44, 0x88, 0x50, 0x4c, 0xf4, 0x2c, 0x20, 0x72, 0x56, 0x6e, 0xa1, 0x97, 0xe4, 0x26, 0xef, 0x86, 0x60, 0x30, 0x27, 0x91, 0x67, 0xa1, 0x0b, 0x99, 0x13, 0x20, 0x61, 0xa3, 0x75, 0x62, 0x6c, 0x1d, 0xc0, 0x8f, 0x6f, 0xd3, 0x13, 0xe1, 0x9a, 0x52, 0x28, 0x33, 0x2e, 0x20, 0xee, 0x4f, 0x83, 0x42, 0x31, 0x45, 0x71, 0x9f, 0x6f, 0xd3, 0x92, 0x82, 0x2b, 0x80, 0x0d, 0x1c, 0x72, 0x69, 0x90, 0x58, 0x62, 0x3c, 0x44, 0x29, 0x20, 0x48, 0x65, 0x81, 0x10, 0x5d, 0x72, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x93, 0x2c, 0xff, 0x41, 0x5b, 0xd9, 0x46, 0x11, 0x10, 0xf1, 0x0e, 0x6b, 0x26, 0x82, 0x38, 0xd8, 0x98, 0xf0, 0x00, 0x43, 0xb0, 0x78, 0xd5, 0x05, 0x0a, 0x61, 0x20, 0x68, 0x73, 0x05, 0x66, 0xf7, 0x70, 0x05, 0x43, 0x0a, 0xc0, 0x24, 0x70, 0xf0, 0x67, 0xa1, 0x04, 0xa1, 0x1b, 0xf4, 0x07, 0x33, 0x90, 0x69, 0x6c, 0x3d, 0x73, 0x75, 0xc0, 0x7a, 0x03, 0x08, 0x0a, 0x63, 0x1f, 0x90, 0x51, 0xd5, 0x23, 0x82, 0x9e, 0xd0, 0x12, 0xc2, 0x33, 0x63, 0x68, 0x6f, 0x3f, 0x10, 0xa1, 0x5c, 0x24, 0x60, 0x21, 0x21, 0xa9, 0xf0, 0x69, 0x57, 0xa2, 0x64, 0x0a, 0xce, 0x6d, 0x65, 0x0f, 0x00, 0x08, 0x51, 0x21, 0x6c, 0x69, 0x70, 0xae, 0xe0, 0x2e, 0x55, 0x60, 0xae, 0x6e, 0xf0, 0x2f, 0x72, 0x60, 0x8a, 0x6c, 0x41, 0x1d, 0x61, 0x3c, 0x6d, 0x65, 0x10, 0x0c, 0x90, 0x38, 0x62, 0x36, 0x60, 0xaf, 0x75, 0x63, 0xe2, 0x74, 0x00, 0x27, 0x0a, 0x6c, 0x61, 0x10, 0x07, 0xb0, 0x1e, 0xa1, 0x53, 0xc8, 0x61, 0x63, 0x63, 0x20, 0x99, 0x6f, 0x72, 0x50, 0x02, 0x01, 0x58, 0x45, 0x60, 0x6d, 0x6c, 0x80, 0x0f, 0x63, 0x72, 0x6f, 0x00, 0x01, 0x69, 0xba, 0x6e, 0xc0, 0x78, 0x65, 0x06, 0x3b, 0x43, 0xa9, 0x60, 0x50, 0x70, 0x50, 0x64, 0x19, 0xc0, 0xaa, 0x28, 0x74, 0xd0, 0x35, 0x40, 0x03, 0x66, 0x65, 0x77, 0x0b, 0x60, 0x4a, 0xa1, 0x02, 0x73, 0xa1, 0x40, 0x6c, 0x65, 0x6e, 0x67, 0x9c, 0x74, 0x68, 0xe0, 0x35, 0x40, 0x06, 0x10, 0xb4, 0x20, 0x62, 0x60, 0x3a, 0x39, 0x25, 0x12, 0x66, 0x6f, 0x01, 0xb3, 0xa0, 0x1b, 0x86, 0x34, 0x47, 0x69, 0x8a, 0x76, 0xb2, 0x8e, 0x6d, 0xa0, 0x94, 0x6e, 0x74, 0x20, 0xe0, 0x0c, 0xf3, 0x50, 0x10, 0xc3, 0x24, 0x65, 0x61, 0x60, 0x13, 0x72, 0xbb, 0x14, 0x25, 0x39, 0x1c, 0xff, 0x32, 0x41, 0x50, 0x17, 0xc1, 0x24, 0x85, 0x1f, 0xe0, 0x10, 0xa2, 0xa9, 0xa1, 0x6e, 0xb0, 0xb9, 0x7f, 0xc0, 0xbe, 0x55, 0x02, 0x55, 0x83, 0x12, 0x54, 0x61, 0x2e, 0x70, 0x02, 0xd0, 0x42, 0x65, 0xbf, 0xd1, 0x03, 0x25, 0x57, 0x02, 0x8c, 0x20, 0x04, 0xf4, 0x9f, 0xd2, 0x27, 0x20, 0xb0, 0x2e, 0xf4, 0x41, 0x63, 0xf0, 0x89, 0x70, 0x61, 0x9b, 0x41, 0x1e, 0x39, 0x08, 0x22, 0x2f, 0xff, 0xe1, 0xa4, 0x07, 0x43, 0xc4, 0x5d, 0x72, 0x06, 0x32, 0x2e, 0xa4, 0xc4, 0x81, 0x06, 0xd5, 0xc4, 0xfd, 0x92, 0x05, 0x34, 0x01, 0x58, 0xb8, 0x91, 0x93, 0x2a, 0xfe, 0x60, 0xeb, 0x8a, 0x54, 0x47, 0xc7, 0x7f, 0x23, 0x80, 0x33, 0xc0, 0x3c, 0x2c, 0x0a, 0x74, 0x00, 0x47, 0x10, 0x4f, 0x28, 0x6f, 0x67, 0x65, 0xb0, 0x0a, 0x72, 0x10, 0x84, 0x66, 0x66, 0xe1, 0xd1, 0x63, 0x76, 0x65, 0x6c, 0x79, 0xa1, 0x18, 0xc1, 0x22, 0x10, 0x8b, 0x6f, 0xf0, 0xcf, 0x80, 0x77, 0xd9, 0x5a, 0xf4, 0x19, 0x0a, 0x3d, 0x85, 0x95, 0x15, 0x63, 0xf8, 0x6f, 0x6e, 0x74, 0xe0, 0x40, 0x30, 0x26, 0xb0, 0x15, 0x61, 0x10, 0x7b, 0x09, 0xc5, 0x81, 0x24, 0x72, 0xa1, 0x44, 0x73, 0x65, 0x0a, 0xd0, 0x1f, 0xa0, 0x1c, 0x1c, 0x65, 0x72, 0xf1, 0x39, 0x80, 0x36, 0x50, 0xb1, 0x62, 0x75, 0x67, 0x7e, 0x67, 0xd1, 0x00, 0x62, 0x30, 0x59, 0x07, 0x21, 0x26, 0x43, 0x66, 0xb2, 0x97, 0x64, 0xe4, 0x6f, 0x20, 0x22, 0x1f, 0x6f, 0x66, 0x10, 0x5f, 0x60, 0x27, 0xbf, 0x22, 0xff, 0xbf, 0x22, 0x80, 0xb2, 0x52, 0x18, 0xbe, 0x22, 0x0b, 0x0a, 0x71, 0x20, 0x21, 0x18, 0xa1, 0x0b, 0x7f, 0xdf, 0x22, 0x01, 0xdd, 0x21, 0x0c, 0xdf, 0x22, 0x20, 0x24, 0xdf, 0x22, 0x80, 0xcf, 0x64, 0xfb, 0xe3, 0xae, 0xdf, 0x22, 0x20, 0xdb, 0x22, 0x5b, 0x08, 0xff, 0x22, 0xf2, 0xe1, 0x30, 0x79, 0xc7, 0xff, 0x22, 0xb0, 0xf3, 0xfa, 0x22, 0x20, 0x63, 0x29, 0x00, 0xf0, 0x7f, 0xc7, 0x91, 0x32, 0x0b, 0x64, 0x69, 0x73, 0x30, 0x39, 0x79, 0x73, 0x70, 0x84, 0x37, 0x35, 0xf4, 0x83, 0x34, 0x40, 0xc9, 0x75, 0x91, 0x18, 0xb1, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x63, 0x80, 0x92, 0x6f, 0x30, 0xdb, 0x63, 0x94, 0x41, 0x23, 0x65, 0x07, 0x2e, 0x03, 0x86, 0x97, 0x75, 0x12, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x03, 0xc4, 0x13, 0x80, 0x61, 0x6e, 0x73, 0xb7, 0x00, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x73, 0x2c, 0x20, 0x80, 0x61, 0x73, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x01, 0x70, 0x00, 0x61, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x00, 0x6e, 0x63, 0x65, 0x20, 0x64, 0x69, 0x72, 0x65, 0x00, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x00, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x02, 0x6f, 0x01, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x80, 0x70, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x02, 0x38, 0x00, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x08, 0x61, 0x6e, 0x64, 0x00, 0x1e, 0x69, 0x73, 0x20, 0x6c, 0x09, 0x00, 0xb2, 0x6e, 0x73, 0x00, 0x86, 0x6f, 0x63, 0x75, 0x6d, 0x20, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x01, 0x68, 0x64, 0x29, 0x80, 0x20, 0x44, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x05, 0x6e, 0x40, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x00, 0x62, 0x3a, 0x03, 0x02, 0x1f, 0x00, 0x57, 0x20, 0x30, 0x29, 0x20, 0x43, 0x6f, 0x10, 0x6e, 0x76, 0x65, 0x79, 0x02, 0x58, 0x4d, 0x69, 0x6e, 0x10, 0x69, 0x6d, 0x61, 0x6c, 0x00, 0x12, 0x72, 0x72, 0x65, 0x20, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x01, 0x8f, 0x53, 0x6f, 0xc4, 0x75, 0x72, 0x00, 0xa0, 0x75, 0x6e, 0x64, 0x01, 0x93, 0x00, 0x9c, 0x90, 0x74, 0x65, 0x72, 0x6d, 0x04, 0x8c, 0x69, 0x73, 0x01, 0x69, 0x5d, 0x01, 0x49, 0x4c, 0x03, 0x83, 0x00, 0xdf, 0x02, 0x95, 0x65, 0x0c, 0x44, 0x41, 0x04, 0x70, 0x70, 0x80, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x01, 0x80, 0x0c, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x05, 0x20, 0x73, 0x75, 0xc0, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x01, 0x0a, 0x83, 0x22, 0x03, 0x84, 0x38, 0x82, 0x36, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0xf1, 0x00, 0x05, 0x69, 0x74, 0x2c, 0x82, 0x55, 0x84, 0x90, 0x85, 0x1e, 0x00, 0x9e, 0x50, 0x6f, 0x6d, 0x62, 0x69, 0x01, 0x76, 0x72, 0x80, 0xaa, 0x6c, 0x18, 0x69, 0x6e, 0x6b, 0x02, 0x13, 0x89, 0x3b, 0x77, 0x69, 0x74, 0x02, 0x68, 0x00, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x80, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x81, 0x47, 0x6c, 0x6f, 0x66, 0x85, 0x22, 0x01, 0xbd, 0x4c, 0x00, 0x1d, 0x00, 0x0e, 0x56, 0x83, 0x04, 0x0e, 0x00, 0xc2, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x80, 0x80, 0x14, 0x61, 0x20, 0x06, 0x1d, 0x43, 0x03, 0x36, 0x64, 0x20, 0x57, 0x70, 0x6f, 0x72, 0x6b, 0x2c, 0x01, 0x66, 0x00, 0x1d, 0x85, 0x22, 0x6d, 0x08, 0x61, 0x6e, 0x6e, 0x00, 0x95, 0x73, 0x70, 0x65, 0x63, 0x61, 0x03, 0x34, 0x62, 0x79, 0x20, 0x73, 0x01, 0xee, 0xc0, 0x3e, 0x36, 0x3f, 0x0d, 0x71, 0x80, 0x40, 0x80, 0x77, 0x81, 0x60, 0xc0, 0x5a, 0x45, 0x10, 0x43, 0x6f, 0x87, 0x0f, 0x60, 0x03, 0x75, 0x81, 0x5a, 0x31, 0x29, 0x20, 0x55, 0x40, 0x7b, 0x84, 0x61, 0x20, 0x86, 0x4c, 0x73, 0x68, 0x61, 0x72, 0xc0, 0x2c, 0x00, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x00, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0xe6, 0x6d, 0xc1, 0x52, 0x40, 0x87, 0x6e, 0x6b, 0xc1, 0x71, 0x82, 0x3f, 0x88, 0x29, 0xc2, 0x4c, 0x43, 0x0b, 0x2e, 0x20, 0x20, 0x41, 0x47, 0x12, 0x87, 0x0e, 0x47, 0xc0, 0x95, 0xc1, 0x8e, 0x02, 0x5e, 0x28, 0x61, 0x29, 0x81, 0xa4, 0x73, 0x02, 0x20, 0x00, 0x61, 0x72, 0x75, 0x6e, 0x20, 0x74, 0x69, 0xd4, 0x6d, 0x65, 0xc5, 0x2a, 0x61, 0x41, 0xa7, 0x79, 0x85, 0x35, 0x04, 0x15, 0x00, 0x20, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x3c, 0x20, 0x70, 0x00, 0x92, 0x40, 0xa4, 0x80, 0xa1, 0x46, 0x6d, 0x27, 0x73, 0x31, 0x40, 0x0c, 0x6d, 0x70, 0x75, 0x80, 0x91, 0xc5, 0x10, 0x73, 0x79, 0x10, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x7d, 0x28, 0x62, 0x29, 0x28, 0x20, 0x77, 0x69, 0x00, 0xc8, 0x6f, 0x80, 0x7b, 0x61, 0x74, 0xe6, 0x65, 0x80, 0x10, 0x41, 0x02, 0x6c, 0x79, 0x40, 0x05, 0xd2, 0x6f, 0x05, 0x11, 0x4f, 0x44, 0xc7, 0x45, 0x20, 0x02, 0x2e, 0x00, 0x31, 0x69, 0x6e, 0x00, 0x1a, 0x66, 0x00, 0x61, 0x63, 0x65, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0xf7, 0x40, 0xa0, 0xc1, 0x98, 0xc5, 0x42, 0x20, 0x43, 0x7b, 0x85, 0x10, 0x04, 0x7d, 0x83, 0x5a, 0x00, 0x65, 0x29, 0x20, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x01, 0x00, 0xab, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x19, 0x83, 0xaf, 0x49, 0x6e, 0x81, 0xad, 0xc2, 0x02, 0x2c, 0x20, 0x62, 0x0c, 0x75, 0x74, 0xc0, 0x36, 0x00, 0x27, 0x69, 0x66, 0x20, 0x79, 0x00, 0x6f, 0x75, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x84, 0x20, 0x6f, 0x80, 0x59, 0x72, 0x77, 0x69, 0x73, 0x02, 0x49, 0x80, 0x62, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0xc0, 0xf7, 0x0d, 0xc0, 0x75, 0x6f, 0xc1, 0x19, 0x62, 0x0a, 0x73, 0x75, 0x63, 0x68, 0xfb, 0x00, 0x47, 0x66, 0x09, 0x20, 0xc3, 0x5d, 0x0d, 0x45, 0x41, 0x13, 0x04, 0x7e, 0xe3, 0x23, 0x0c, 0x6f, 0x6e, 0xa0, 0x0d, 0x43, 0x83, 0x20, 0x65, 0x78, 0x74, 0x4f, 0x81, 0x2b, 0x42, 0x1d, 0xee, 0x09, 0x63, 0x73, 0x6e, 0x65, 0xa0, 0x8e, 0x73, 0x1b, 0xa1, 0x42, 0x60, 0x06, 0x69, 0xe3, 0x18, 0x22, 0x87, 0x65, 0x78, 0x65, 0xfe, 0x63, 0x60, 0x30, 0x13, 0x62, 0x81, 0x35, 0x21, 0x0f, 0xea, 0x5c, 0x41, 0x17, 0x01, 0x61, 0xe4, 0x64, 0x20, 0x00, 0x5a, 0x72, 0x65, 0xc0, 0x29, 0x00, 0x6e, 0x21, 0x4b, 0x5e, 0x6f, 0x45, 0x6e, 0x81, 0x01, 0x24, 0x4c, 0x1f, 0x6f, 0x6e, 0x67, 0x46, 0x6e, 0xc2, 0x6b, 0x27, 0x6e, 0x2e, 0x20, 0x28, 0x49, 0x02, 0x72, 0xc1, 0x29, 0x11, 0xa0, 0x7c, 0x20, 0x6f, 0x70, 0xa2, 0x86, 0x34, 0x64, 0x30, 0x03, 0x23, 0x7f, 0x95, 0x31, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x64, 0x61, 0x63, 0xc2, 0x3c, 0x6e, 0x79, 0xc1, 0x17, 0x60, 0x11, 0x20, 0x1f, 0x9a, 0x9a, 0x41, 0xa8, 0x8b, 0x6d, 0xe8, 0x16, 0x03, 0x20, 0x64, 0x65, 0x2e, 0xcc, 0x20, 0x49, 0x83, 0x3b, 0xaa, 0x11, 0x31, 0x2c, 0x02, 0x3e, 0x82, 0x0e, 0x7f, 0x20, 0x84, 0x62, 0x3a, 0xe1, 0x0d, 0xc9, 0x13, 0x21, 0x08, 0xc8, 0x45, 0xe4, 0x84, 0x20, 0xff, 0x1f, 0x84, 0xa0, 0xac, 0x84, 0x3e, 0x41, 0x08, 0x60, 0x44, 0x40, 0x66, 0x64, 0x84, 0x0c, 0xab, 0xc9, 0xa3, 0xb3, 0x2e, 0x29, 0x41, 0xba, 0x35, 0x2e, 0x80, 0x03, 0xa2, 0xa0, 0x5e, 0x64, 0x00, 0x5b, 0x61, 0x81, 0xa0, 0xc6, 0x82, 0x59, 0x59, 0x40, 0x53, 0x6d, 0x7a, 0x61, 0xc0, 0x71, 0x6c, 0x00, 0x61, 0x20, 0x82, 0xe3, 0x84, 0xa0, 0x62, 0x69, 0x78, 0x6c, 0x69, 0x74, 0x41, 0xcb, 0x42, 0x48, 0x80, 0x88, 0xc0, 0x41, 0x77, 0xe1, 0x40, 0x9a, 0x20, 0x62, 0x61, 0x73, 0x40, 0x32, 0x00, 0x96, 0x40, 0x1a, 0x7a, 0x0a, 0x45, 0x6a, 0x73, 0x61, 0x61, 0x81, 0x99, 0xe1, 0x00, 0x02, 0xb8, 0x73, 0x87, 0x20, 0x3e, 0x40, 0xb6, 0x05, 0x8f, 0x74, 0x6f, 0x67, 0x65, 0x00, 0x06, 0x2e, 0x72, 0x43, 0x75, 0xa2, 0x60, 0x85, 0x0d, 0x0a, 0x91, 0x0d, 0x6e, 0x6f, 0x7c, 0x74, 0x20, 0x08, 0x2e, 0xe0, 0x8b, 0x80, 0xc7, 0xa1, 0x10, 0x01, 0x03, 0x63, 0xce, 0x6f, 0x00, 0xb4, 0x80, 0x10, 0x00, 0x0e, 0x74, 0x68, 0x80, 0x59, 0x2a, 0xcc, 0xfe, 0x63, 0xa3, 0xd6, 0x82, 0x5e, 0x21, 0x90, 0xa4, 0x1e, 0x05, 0x11, 0x49, 0xc7, 0xe0, 0x82, 0xc1, 0x40, 0x49, 0x72, 0x0a, 0x63, 0x68, 0x6f, 0x60, 0xd4, 0x80, 0xb5, 0xe1, 0x83, 0x39, 0x64, 0x6f, 0x20, 0x62, 0x20, 0x14, 0x85, 0x50, 0x8c, 0xe3, 0xfd, 0x00, 0x9e, 0x41, 0x25, 0x49, 0x22, 0x97, 0xa3, 0x5d, 0xc0, 0x11, 0x45, 0x0c, 0x42, 0x88, 0x21, 0x8b, 0x9f, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x80, 0x72, 0x6b, 0xcf, 0xc3, 0x27, 0x41, 0x37, 0x23, 0x28, 0xa4, 0x31, 0x79, 0x2c, 0x40, 0x3e, 0x86, 0x04, 0xbd, 0x03, 0x04, 0x6e, 0xa0, 0x53, 0x22, 0x13, 0x75, 0x05, 0x77, 0x12, 0x2c, 0x01, 0x04, 0x9f, 0x83, 0x0e, 0x70, 0x07, 0x24, 0x0d, 0xfd, 0x77, 0xa0, 0x05, 0x63, 0x65, 0xc0, 0x7f, 0xa3, 0x33, 0x4b, 0xb0, 0x53, 0x47, 0x69, 0x76, 0x32, 0x53, 0x6d, 0xc0, 0x70, 0xf8, 0x6e, 0x74, 0x20, 0x90, 0x14, 0x50, 0x0f, 0x03, 0x19, 0x70, 0x06, 0xa1, 0x57, 0x8d, 0x61, 0x72, 0x64, 0x46, 0x20, 0x92, 0x1f, 0x70, 0x61, 0x72, 0x70, 0x4c, 0xb0, 0x66, 0x20, 0x69, 0x74, 0x31, 0x07, 0x50, 0x53, 0x61, 0x78, 0x0c, 0x07, 0xc5, 0x5b, 0x64, 0x20, 0x63, 0x48, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x33, 0xf0, 0x82, 0x00, 0x8b, 0x77, 0x68, 0x30, 0x8c, 0xd1, 0x8a, 0x66, 0x69, 0x9f, 0xe0, 0x1b, 0x40, 0x06, 0x31, 0x04, 0x76, 0x38, 0x31, 0x41, 0x75, 0x6e, 0x56, 0x0f, 0x0f, 0xf1, 0x4e, 0x35, 0x17, 0xf6, 0x12, 0xc2, 0x0b, 0x36, 0x2e, 0x20, 0x52, 0x64, 0x65, 0x76, 0x40, 0x53, 0x64, 0x20, 0x74, 0x58, 0x1a, 0x8f, 0x4c, 0x64, 0x65, 0x73, 0x41, 0x91, 0x47, 0x65, 0xb0, 0x75, 0x30, 0x8a, 0x50, 0x2c, 0x75, 0x62, 0x00, 0x85, 0xda, 0x0f, 0x54, 0xb0, 0x11, 0x46, 0x72, 0x00, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x79, 0x61, 0x24, 0x46, 0x6f, 0x50, 0x13, 0x53, 0x5b, 0xd2, 0x2f, 0x31, 0x03, 0x73, 0x2e, 0x68, 0xe0, 0x58, 0x63, 0x06, 0xd0, 0x3f, 0x2f, 0xb0, 0x4b, 0x6e, 0x65, 0xf2, 0x77, 0xb5, 0x80, 0x73, 0x0a, 0x54, 0x64, 0xd1, 0x37, 0x1f, 0x07, 0x18, 0x07, 0xe0, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x82, 0x70, 0x72, 0x9a, 0x00, 0x71, 0xd8, 0x2e, 0x20, 0x53, 0x21, 0x5d, 0xd0, 0x04, 0x0a, 0x94, 0x85, 0x90, 0x9e, 0x03, 0x81, 0x6c, 0x00, 0x60, 0x73, 0x69, 0x6d, 0x69, 0x6c, 0x61, 0x02, 0x72, 0x01, 0x40, 0x73, 0x70, 0x69, 0x72, 0x69, 0x74, 0xbf, 0x42, 0x03, 0xf0, 0x0a, 0xf5, 0x71, 0x14, 0x03, 0x03, 0x65, 0xb0, 0x0a, 0x0a, 0x30, 0x8a, 0x03, 0xa0, 0xa1, 0x01, 0x03, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x91, 0x01, 0x03, 0x61, 0x64, 0x64, 0xe0, 0x74, 0x73, 0x20, 0x01, 0x0b, 0x17, 0x20, 0x47, 0x80, 0x6c, 0x71, 0x98, 0x72, 0xb1, 0x41, 0x63, 0x65, 0x72, 0x64, 0x6e, 0x73, 0x62, 0x14, 0x45, 0x61, 0x70, 0x65, 0xe4, 0x04, 0x20, 0x8d, 0x90, 0x1c, 0x67, 0xf0, 0x20, 0xb1, 0x96, 0x64, 0x69, 0x73, 0xe1, 0xa5, 0x30, 0x75, 0x69, 0x73, 0x68, 0x21, 0x19, 0x15, 0x02, 0x6e, 0x75, 0xf0, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x4e, 0x91, 0x1b, 0xa5, 0x3e, 0x50, 0xaa, 0x53, 0x40, 0x33, 0x90, 0x12, 0x63, 0x65, 0xf0, 0x03, 0x64, 0x80, 0x21, 0x20, 0x9d, 0xf5, 0x8c, 0x73, 0xf0, 0x30, 0x70, 0x80, 0xa0, 0x2f, 0x65, 0x72, 0x90, 0x09, 0xbc, 0x6e, 0x20, 0x23, 0x04, 0x20, 0x2a, 0x34, 0x05, 0x3f, 0x14, 0x20, 0x5f, 0x1b, 0xe9, 0x31, 0x2b, 0x20, 0x22, 0xd0, 0x17, 0x61, 0x10, 0x30, 0x90, 0x75, 0x00, 0x93, 0xf1, 0xe4, 0x03, 0x22, 0x0a, 0x61, 0xc1, 0xa2, 0xf0, 0xae, 0x11, 0x6b, 0xe0, 0x9e, 0xf9, 0x81, 0x08, 0x68, 0x61, 0x50, 0x2d, 0x00, 0x0a, 0xd5, 0x60, 0x60, 0x1a, 0x16, 0x3b, 0xaf, 0xf2, 0x39, 0x40, 0x7e, 0xc0, 0x10, 0x10, 0x1d, 0x0a, 0x10, 0x33, 0x64, 0x40, 0x4d, 0x40, 0x6f, 0x6e, 0x73, 0x20, 0x65, 0x69, 0x20, 0x03, 0x72, 0xdb, 0xe3, 0x26, 0x20, 0x0b, 0x70, 0xf3, 0x1f, 0x97, 0x0a, 0x20, 0xf0, 0x07, 0x90, 0x04, 0x4d, 0x2e, 0x08, 0x0a, 0x97, 0x02, 0xd2, 0x47, 0x65, 0x20, 0x7f, 0x25, 0x64, 0xdf, 0x72, 0x25, 0x85, 0x13, 0x80, 0x28, 0x33, 0x55, 0x83, 0x13, 0x0a, 0xe0, 0x71, 0x86, 0x13, 0xdc, 0x64, 0x6f, 0xb0, 0x0c, 0x11, 0x4d, 0x13, 0x14, 0x79, 0x30, 0x56, 0xa4, 0x0e, 0xf7, 0xa4, 0x13, 0xf5, 0x30, 0x47, 0x27, 0x0a, 0x0f, 0x13, 0x01, 0x13, 0x24, 0x67, 0x80, 0x5c, 0xfd, 0xc0, 0x4c, 0x6f, 0x31, 0xa0, 0xc0, 0x13, 0xb5, 0x04, 0x80, 0x0c, 0x01, 0x12, 0x4f, 0x04, 0xd2, 0x20, 0xbb, 0x32, 0x20, 0x65, 0x10, 0x03, 0x20, 0x1f, 0x0e, 0x9f, 0x33, 0xff, 0x13, 0x0e, 0x91, 0x65, 0x00, 0x70, 0xb1, 0x05, 0xdf, 0x21, 0xdf, 0x21, 0xd5, 0x21, 0x00, 0x2a, 0x00, 0x78, 0x79, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x64, 0x31, 0x70, 0xb0, 0x64, 0x65, 0x0a, 0x60, 0x42, 0x30, 0x04, 0x72, 0x20, 0xc0, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x16, 0x37, 0xcf, 0x0f, 0xcb, 0xdf, 0x22, 0x12, 0x4e, 0x20, 0x50, 0xae, 0x6c, 0x6c, 0xc2, 0x21, 0x80, 0x54, 0x61, 0x63, 0x4b, 0x72, 0x6f, 0x78, 0x79, 0xf0, 0xa4, 0xc2, 0x0c, 0x63, 0x2e, 0x20, 0x40, 0x9a, 0x60, 0xa4, 0xe2, 0xa6, 0x66, 0x81, 0x80, 0x65, 0x70, 0x7c, 0x74, 0x61, 0xb1, 0xd5, 0x24, 0x1e, 0x85, 0x12, 0xb0, 0x64, 0x91, 0xc4, 0x61, 0x02, 0x6e, 0x91, 0x02, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0xfc, 0x69, 0x7a, 0xb2, 0x0e, 0xf2, 0xb2, 0xe1, 0x26, 0x90, 0x27, 0x14, 0x16, 0x72, 0x06, 0xdf, 0x95, 0x03, 0x81, 0x78, 0x30, 0x0c, 0x05, 0x71, 0xf0, 0x36, 0x00, 0x0f, 0x00, 0x1f, 0x01, 0xff, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0xff, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0xff, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1a, 0x01, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_compressed_block_data_handle_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_compressed_block_data_handle_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_compressed_block_data_handle_t *compressed_block_data_handle = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 5; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_compressed_block_data_handle_data1, 80, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_compressed_block_data_handle_initialize( &compressed_block_data_handle, io_handle, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "compressed_block_data_handle", compressed_block_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_compressed_block_data_handle_free( &compressed_block_data_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_block_data_handle", compressed_block_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_compressed_block_data_handle_initialize( NULL, io_handle, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); compressed_block_data_handle = (libfsntfs_compressed_block_data_handle_t *) 0x12345678UL; result = libfsntfs_compressed_block_data_handle_initialize( &compressed_block_data_handle, io_handle, mft_attribute, &error ); compressed_block_data_handle = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_compressed_block_data_handle_initialize( &compressed_block_data_handle, NULL, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_compressed_block_data_handle_initialize( &compressed_block_data_handle, io_handle, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_compressed_block_data_handle_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_compressed_block_data_handle_initialize( &compressed_block_data_handle, io_handle, mft_attribute, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( compressed_block_data_handle != NULL ) { libfsntfs_compressed_block_data_handle_free( &compressed_block_data_handle, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_block_data_handle", compressed_block_data_handle ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_compressed_block_data_handle_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_compressed_block_data_handle_initialize( &compressed_block_data_handle, io_handle, mft_attribute, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( compressed_block_data_handle != NULL ) { libfsntfs_compressed_block_data_handle_free( &compressed_block_data_handle, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_block_data_handle", compressed_block_data_handle ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( compressed_block_data_handle != NULL ) { libfsntfs_compressed_block_data_handle_free( &compressed_block_data_handle, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_compressed_block_data_handle_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_compressed_block_data_handle_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_compressed_block_data_handle_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_compressed_block_data_handle_read_segment_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_compressed_block_data_handle_read_segment_data( void ) { uint8_t segment_data[ 16 ]; uint8_t expected_segment_data1[ 12 ] = { 0x09, 0x09, 0x20, 0x20, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x45, 0x53 }; uint8_t expected_segment_data2[ 4 ] = { 0x00, 0x00, 0x00, 0x00 }; libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_compressed_block_data_handle_t *compressed_block_data_handle = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; ssize_t read_count = 0; off64_t offset = 0; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_compressed_block_data_handle_data1, 80, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_compressed_block_data_handle_initialize( &compressed_block_data_handle, io_handle, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "compressed_block_data_handle", compressed_block_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize file IO handle */ result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_compressed_block_data_handle_lznt1_compressed_data1, 24576, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ read_count = libfsntfs_compressed_block_data_handle_read_segment_data( compressed_block_data_handle, file_io_handle, 0, 0, segment_data, 12, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) 12 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( segment_data, expected_segment_data1, 12 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); /* Read buffer on last segment boundary */ offset = libfsntfs_compressed_block_data_handle_seek_segment_offset( compressed_block_data_handle, NULL, 0, 0, 65536 - 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 65536 - 4 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); read_count = libfsntfs_compressed_block_data_handle_read_segment_data( compressed_block_data_handle, file_io_handle, 0, 0, segment_data, 8, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) 4 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( segment_data, expected_segment_data2, 4 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); /* Read buffer beyond last segment */ read_count = libfsntfs_compressed_block_data_handle_read_segment_data( compressed_block_data_handle, file_io_handle, 0, 0, segment_data, 16, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfsntfs_compressed_block_data_handle_free( &compressed_block_data_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_block_data_handle", compressed_block_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Create a new compressed block data handle to prevent the compressed block cache * affecting the tests. */ result = libfsntfs_compressed_block_data_handle_initialize( &compressed_block_data_handle, io_handle, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "compressed_block_data_handle", compressed_block_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ read_count = libfsntfs_compressed_block_data_handle_read_segment_data( NULL, file_io_handle, 0, 0, segment_data, 16, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); compressed_block_data_handle->current_offset = -1; read_count = libfsntfs_compressed_block_data_handle_read_segment_data( compressed_block_data_handle, file_io_handle, 0, 0, segment_data, 16, 0, 0, &error ); compressed_block_data_handle->current_offset = 0; FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_compressed_block_data_handle_read_segment_data( compressed_block_data_handle, NULL, 0, 0, segment_data, 16, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_compressed_block_data_handle_read_segment_data( compressed_block_data_handle, file_io_handle, 0, 0, NULL, 16, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_compressed_block_data_handle_read_segment_data( compressed_block_data_handle, file_io_handle, 0, 0, segment_data, (size_t) SSIZE_MAX + 1, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) && defined( OPTIMIZATION_DISABLED ) /* Test libfsntfs_compressed_block_data_handle_read_segment_data with memcpy failing */ fsntfs_test_memcpy_attempts_before_fail = 0; read_count = libfsntfs_compressed_block_data_handle_read_segment_data( compressed_block_data_handle, file_io_handle, 0, 0, segment_data, 12, 0, 0, &error ); if( fsntfs_test_memcpy_attempts_before_fail != -1 ) { fsntfs_test_memcpy_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) && defined( OPTIMIZATION_DISABLED ) */ /* Clean up file IO handle */ result = libbfio_handle_free( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfsntfs_compressed_block_data_handle_free( &compressed_block_data_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_block_data_handle", compressed_block_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } if( compressed_block_data_handle != NULL ) { libfsntfs_compressed_block_data_handle_free( &compressed_block_data_handle, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_compressed_block_data_handle_seek_segment_offset function * Returns 1 if successful or 0 if not */ int fsntfs_test_compressed_block_data_handle_seek_segment_offset( void ) { libcerror_error_t *error = NULL; libfsntfs_compressed_block_data_handle_t *compressed_block_data_handle = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; off64_t offset = 0; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_compressed_block_data_handle_data1, 80, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_compressed_block_data_handle_initialize( &compressed_block_data_handle, io_handle, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "compressed_block_data_handle", compressed_block_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ offset = libfsntfs_compressed_block_data_handle_seek_segment_offset( compressed_block_data_handle, NULL, 0, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ offset = libfsntfs_compressed_block_data_handle_seek_segment_offset( NULL, NULL, 0, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); offset = libfsntfs_compressed_block_data_handle_seek_segment_offset( compressed_block_data_handle, NULL, 0, 0, -1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_compressed_block_data_handle_free( &compressed_block_data_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_block_data_handle", compressed_block_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( compressed_block_data_handle != NULL ) { libfsntfs_compressed_block_data_handle_free( &compressed_block_data_handle, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_compressed_block_data_handle_initialize", fsntfs_test_compressed_block_data_handle_initialize ); FSNTFS_TEST_RUN( "libfsntfs_compressed_block_data_handle_free", fsntfs_test_compressed_block_data_handle_free ); FSNTFS_TEST_RUN( "libfsntfs_compressed_block_data_handle_read_segment_data", fsntfs_test_compressed_block_data_handle_read_segment_data ); FSNTFS_TEST_RUN( "libfsntfs_compressed_block_data_handle_seek_segment_offset", fsntfs_test_compressed_block_data_handle_seek_segment_offset ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_compressed_block_vector.c ================================================ /* * Library compressed_block_vector type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_functions.h" #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfcache.h" #include "fsntfs_test_libfdata.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_compressed_block_vector.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" uint8_t fsntfs_test_compressed_block_vector_data1[ 80 ] = { 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x01, 0x01, 0x0e, 0x00, 0x00, 0x00 }; uint8_t fsntfs_test_compressed_block_vector_lznt1_compressed_data1[ 24576 ] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0xb8, 0x00, 0x09, 0x09, 0x20, 0x20, 0x20, 0x47, 0x4e, 0x55, 0x00, 0x20, 0x4c, 0x45, 0x53, 0x53, 0x45, 0x52, 0x20, 0x00, 0x47, 0x45, 0x4e, 0x45, 0x52, 0x41, 0x4c, 0x20, 0x80, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x00, 0x18, 0x60, 0x45, 0x4e, 0x53, 0x45, 0x0a, 0x00, 0x90, 0x11, 0x08, 0x56, 0x00, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x00, 0x2c, 0x20, 0x32, 0x39, 0x20, 0x4a, 0x75, 0x6e, 0x00, 0x65, 0x20, 0x32, 0x30, 0x30, 0x37, 0x0a, 0x0a, 0x00, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x40, 0x68, 0x74, 0x20, 0x28, 0x43, 0x29, 0x02, 0x28, 0x20, 0x00, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x00, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x20, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x00, 0x7a, 0x2c, 0x20, 0x00, 0x49, 0x6e, 0x63, 0x2e, 0x20, 0x3c, 0x68, 0x74, 0x00, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x66, 0x73, 0x66, 0x00, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x40, 0x45, 0x76, 0x65, 0x72, 0x79, 0x6f, 0x00, 0x54, 0x69, 0x00, 0x73, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x00, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x01, 0x00, 0x5d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x00, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2a, 0x20, 0x00, 0x2b, 0x62, 0x00, 0x4f, 0x6d, 0x01, 0x1c, 0x69, 0x65, 0x00, 0x73, 0x0a, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x01, 0x00, 0x39, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x00, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x08, 0x74, 0x2c, 0x20, 0x00, 0x2f, 0x20, 0x63, 0x68, 0x61, 0x00, 0x6e, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, 0x02, 0x20, 0x00, 0x12, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x6c, 0x80, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x2e, 0x0a, 0x80, 0x5f, 0xbc, 0x20, 0x54, 0x01, 0x1d, 0x80, 0x29, 0x82, 0x6f, 0x02, 0x25, 0x65, 0x83, 0x93, 0x00, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x00, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x12, 0x62, 0x80, 0x2f, 0x20, 0x4c, 0x84, 0x31, 0x69, 0x6e, 0x63, 0x80, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x80, 0x40, 0xa0, 0x74, 0x68, 0x65, 0x20, 0x74, 0x00, 0x5b, 0x73, 0x02, 0x55, 0xa0, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x81, 0x77, 0x73, 0x81, 0x4c, 0x5d, 0x85, 0x2c, 0x33, 0x03, 0x53, 0x83, 0x2d, 0x0b, 0x2a, 0x0a, 0x04, 0x2a, 0x2c, 0x80, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x65, 0x81, 0x5d, 0x09, 0x00, 0x7f, 0x62, 0x79, 0x00, 0x6b, 0x65, 0x20, 0x61, 0x64, 0x17, 0x83, 0x26, 0x80, 0x41, 0x02, 0x8d, 0x73, 0x01, 0x54, 0x73, 0x20, 0x6c, 0x1b, 0x00, 0x88, 0x01, 0x12, 0x65, 0x00, 0x65, 0x00, 0x64, 0x20, 0x20, 0x30, 0x08, 0x2e, 0x20, 0x41, 0x07, 0x15, 0x44, 0x65, 0x66, 0x69, 0x06, 0x6e, 0x83, 0x42, 0x82, 0x0e, 0x41, 0x73, 0x20, 0x75, 0x73, 0x01, 0xc0, 0x0b, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x2c, 0x0c, 0x20, 0x22, 0x42, 0x4c, 0x04, 0x1e, 0x22, 0x20, 0x72, 0x65, 0xae, 0x66, 0x40, 0x78, 0x41, 0x5c, 0xd2, 0x2b, 0x4c, 0xc2, 0x42, 0x0a, 0xd3, 0x42, 0x16, 0x2c, 0x42, 0x3d, 0xc1, 0x40, 0x22, 0xc1, 0x97, 0x47, 0x50, 0x4c, 0x27, 0xdd, 0x13, 0x14, 0x12, 0x02, 0x2a, 0x22, 0x54, 0x00, 0x53, 0x4c, 0x69, 0xa0, 0x62, 0x72, 0x61, 0x72, 0x79, 0xc9, 0x11, 0x61, 0x80, 0x7b, 0x03, 0xc0, 0x26, 0x80, 0x30, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x67, 0x7a, 0x6f, 0x00, 0x03, 0x6e, 0x40, 0x03, 0x42, 0x49, 0xc0, 0x75, 0xc5, 0x50, 0x0a, 0x4a, 0x6f, 0x40, 0x22, 0x72, 0x40, 0x4e, 0x61, 0x6e, 0xc0, 0x25, 0x20, 0x12, 0x41, 0x00, 0x54, 0x69, 0x63, 0x82, 0x9f, 0x20, 0x6f, 0x72, 0x44, 0x20, 0x61, 0xc0, 0xab, 0x6d, 0x62, 0x69, 0x01, 0x0e, 0x57, 0xe1, 0x81, 0x11, 0x61, 0x73, 0x20, 0x64, 0x41, 0x4a, 0x01, 0x12, 0x46, 0x52, 0x50, 0x41, 0x6e, 0x20, 0x22, 0xc8, 0x0d, 0x22, 0x81, 0x8d, 0x61, 0x08, 0x6e, 0x79, 0x20, 0x02, 0x1e, 0x74, 0x68, 0x61, 0x74, 0xe0, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x02, 0x54, 0x01, 0x75, 0x00, 0x1a, 0x04, 0x69, 0x6e, 0x80, 0x7f, 0x66, 0x61, 0x63, 0x65, 0x20, 0x00, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x0e, 0x0a, 0x44, 0x6f, 0x44, 0x32, 0x83, 0xa2, 0x77, 0x68, 0x69, 0x63, 0x26, 0x68, 0x05, 0xa1, 0xc2, 0x29, 0x77, 0x69, 0xc0, 0xab, 0x62, 0x61, 0x4f, 0x41, 0x66, 0x40, 0xd7, 0xc1, 0x50, 0x04, 0x0c, 0x2e, 0x0a, 0x43, 0x70, 0x6e, 0x02, 0x67, 0xc0, 0x2c, 0x73, 0x75, 0x62, 0x63, 0x6c, 0x61, 0xfe, 0x73, 0xc2, 0x93, 0xc0, 0x41, 0x82, 0x02, 0x86, 0x2d, 0x43, 0x89, 0x84, 0x0d, 0x01, 0x17, 0x14, 0x64, 0x65, 0x40, 0x90, 0x64, 0x80, 0x0d, 0x6d, 0x6f, 0x64, 0x64, 0x65, 0x0a, 0x40, 0xb4, 0x75, 0x73, 0x81, 0xbf, 0xd2, 0x14, 0x20, 0xc3, 0xcb, 0x14, 0x43, 0x45, 0x20, 0x22, 0x43, 0x6f, 0x88, 0x24, 0xe3, 0x1f, 0xa3, 0xa3, 0x1f, 0xc0, 0x1b, 0x64, 0x75, 0x63, 0xc3, 0x2e, 0x63, 0x82, 0x04, 0x43, 0x41, 0x0b, 0x00, 0x2b, 0x6c, 0x69, 0x6e, 0x6b, 0xa3, 0x0c, 0x0a, 0xa1, 0x49, 0x2e, 0x77, 0x69, 0x74, 0x68, 0x60, 0x31, 0x65, 0xe0, 0x66, 0x19, 0x22, 0x3a, 0x2e, 0x20, 0xe0, 0x6d, 0xa0, 0x24, 0x61, 0x72, 0x74, 0xc0, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, 0xa1, 0x79, 0x29, 0x6f, 0x3d, 0xe4, 0x18, 0x0a, 0x02, 0x07, 0xe3, 0x25, 0xa1, 0x22, 0x0a, 0x12, 0x20, 0x77, 0x21, 0xc0, 0x36, 0x6d, 0x61, 0x64, 0x65, 0xa1, 0x1d, 0x61, 0x6c, 0x9e, 0x73, 0xc0, 0x84, 0x20, 0x7a, 0x80, 0x12, 0x21, 0x05, 0x22, 0x4c, 0x20, 0x11, 0x9b, 0xe0, 0x2f, 0x24, 0x96, 0x22, 0x42, 0x1a, 0x61, 0x4a, 0x22, 0x4d, 0x00, 0x62, 0x02, 0x6d, 0xa0, 0x68, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x06, 0x70, 0xa1, 0x74, 0xa0, 0x2b, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x10, 0x65, 0x22, 0x20, 0x66, 0xb0, 0x43, 0x6d, 0x65, 0x61, 0x74, 0x6e, 0x73, 0xc1, 0x17, 0x0a, 0x71, 0x06, 0x42, 0x06, 0x8e, 0x13, 0x2c, 0x80, 0x20, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x83, 0x21, 0xf8, 0x79, 0x20, 0x73, 0xe2, 0x0b, 0x80, 0x57, 0x60, 0x31, 0x61, 0x0c, 0x60, 0x86, 0xb7, 0x66, 0x83, 0x8e, 0x07, 0x60, 0x0d, 0x61, 0xc0, 0x96, 0x20, 0x88, 0x73, 0x80, 0x48, 0x92, 0x72, 0x40, 0x1a, 0x69, 0x6e, 0x80, 0x1c, 0x6f, 0x6c, 0x02, 0x58, 0xf1, 0x00, 0x6d, 0x72, 0x65, 0x0a, 0xaa, 0x45, 0x68, 0x2d, 0xc3, 0x70, 0xc1, 0x9b, 0xf9, 0x26, 0x49, 0x6e, 0x6b, 0x20, 0x08, 0x04, 0x21, 0xe7, 0x20, 0x6b, 0x19, 0xa9, 0x35, 0x06, 0x43, 0x00, 0x46, 0x3d, 0x21, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0xf6, 0x74, 0xe2, 0x19, 0xe1, 0x7e, 0x2f, 0xc0, 0x26, 0x48, 0x1c, 0x66, 0x22, 0x0a, 0x13, 0x27, 0x80, 0xa5, 0x28, 0x22, 0x80, 0xc1, 0x61, 0x0a, 0x61, 0xba, 0x75, 0x74, 0x20, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x61, 0x66, 0x67, 0x72, 0x80, 0x61, 0x6d, 0x73, 0x20, 0x6e, 0x65, 0x65, 0x40, 0x67, 0x39, 0x62, 0x08, 0x72, 0x65, 0x43, 0x4d, 0xc1, 0x28, 0xcf, 0x24, 0x66, 0x72, 0x7c, 0x6f, 0x6d, 0xe2, 0x32, 0xca, 0x0c, 0xa1, 0xbd, 0x87, 0x2f, 0xa1, 0x06, 0x53, 0xe0, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x84, 0x4f, 0x60, 0xc5, 0x65, 0xb0, 0x03, 0xca, 0x49, 0x22, 0x23, 0x31, 0x2e, 0x20, 0x45, 0x78, 0x63, 0xec, 0x65, 0x70, 0x61, 0x33, 0xc1, 0xa0, 0x53, 0x80, 0x1c, 0x02, 0xde, 0x45, 0x06, 0xa3, 0x44, 0x9b, 0x82, 0x05, 0x59, 0x6f, 0x75, 0x40, 0x80, 0x79, 0x80, 0x20, 0xd0, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x6d, 0x63, 0xa1, 0x91, 0x60, 0x2d, 0x17, 0x22, 0x84, 0xc0, 0xdd, 0xe0, 0xc6, 0x73, 0x03, 0x08, 0x73, 0x20, 0x33, 0x39, 0xc1, 0x24, 0x20, 0x34, 0xe3, 0x08, 0x07, 0x95, 0x22, 0x5c, 0x6f, 0x75, 0xd0, 0x74, 0x20, 0x62, 0x65, 0x61, 0x1c, 0x62, 0xa1, 0xe4, 0xa1, 0x71, 0x9f, 0xe4, 0x06, 0xc0, 0x06, 0x68, 0xd1, 0x60, 0xaa, 0x02, 0x0f, 0x32, 0x2e, 0xe0, 0x97, 0x03, 0x61, 0x0e, 0x41, 0x06, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x85, 0x27, 0x3c, 0x73, 0x42, 0x04, 0x49, 0x66, 0x20, 0x79, 0xc1, 0x13, 0x73, 0x81, 0x03, 0x43, 0x13, 0x70, 0x79, 0x65, 0x18, 0xc4, 0x35, 0x92, 0x22, 0x2c, 0xe6, 0x20, 0xa0, 0x25, 0x90, 0x02, 0x72, 0x20, 0x60, 0x42, 0x70, 0x04, 0x33, 0x52, 0x3a, 0x73, 0xb0, 0x01, 0x0a, 0x80, 0x4c, 0x83, 0x19, 0x57, 0x61, 0x61, 0x20, 0xf0, 0x66, 0x75, 0x6e, 0x63, 0xc2, 0x11, 0x00, 0x1f, 0x11, 0x1c, 0x41, 0x12, 0x7c, 0x62, 0x65, 0x13, 0x6b, 0x41, 0x08, 0x80, 0x44, 0x10, 0x46, 0xf8, 0x18, 0x0a, 0xd7, 0x92, 0x52, 0x40, 0x67, 0x12, 0x34, 0x20, 0x46, 0x05, 0x28, 0x09, 0x5a, 0x11, 0x73, 0x90, 0x20, 0x61, 0x72, 0x67, 0xf2, 0x7a, 0x20, 0x70, 0x30, 0x4e, 0x71, 0x51, 0x14, 0x68, 0x65, 0x6e, 0xd2, 0x1d, 0x36, 0x03, 0x60, 0x13, 0x69, 0x48, 0x6e, 0x76, 0x6f, 0xe0, 0x2c, 0x29, 0x2c, 0x91, 0x01, 0x6e, 0xfd, 0x33, 0x0e, 0x61, 0x2a, 0x18, 0x77, 0x0e, 0x13, 0x0d, 0x40, 0x40, 0x30, 0x62, 0xc1, 0x45, 0xc2, 0x3a, 0x71, 0x7e, 0x20, 0x61, 0x29, 0x20, 0xa3, 0x19, 0xa9, 0x6f, 0x7e, 0x2c, 0x16, 0x5b, 0x70, 0x05, 0x90, 0x5d, 0xb2, 0x13, 0xd0, 0x5d, 0x40, 0x1d, 0x67, 0x98, 0x6f, 0x6f, 0x64, 0x60, 0x0b, 0x11, 0x4c, 0x65, 0x66, 0xa0, 0x3b, 0xee, 0x74, 0x20, 0x0f, 0xf1, 0x91, 0x30, 0x86, 0x75, 0x70, 0x8d, 0xe1, 0x0d, 0x42, 0x14, 0x39, 0x81, 0x26, 0x65, 0x76, 0xf0, 0x86, 0x80, 0x1e, 0xfa, 0x66, 0x64, 0x6f, 0xff, 0x40, 0x62, 0x01, 0x39, 0x62, 0x7d, 0x72, 0x5a, 0xf1, 0x03, 0x9d, 0x14, 0x12, 0x0d, 0xf7, 0x11, 0xa2, 0x73, 0x50, 0x31, 0x6c, 0x20, 0x6f, 0xb0, 0x7e, 0x61, 0xb0, 0x85, 0x17, 0xb2, 0x1a, 0x31, 0x91, 0x00, 0x08, 0x6d, 0xb0, 0x8e, 0x20, 0x20, 0x77, 0x4b, 0x00, 0x68, 0xe0, 0x06, 0x72, 0xd0, 0x12, 0x72, 0x74, 0x91, 0x1d, 0x69, 0x1a, 0x74, 0x40, 0x93, 0x75, 0xc0, 0x88, 0xa0, 0x64, 0x72, 0x65, 0x6d, 0x1c, 0x61, 0x69, 0x30, 0x4b, 0x91, 0x4b, 0x30, 0x22, 0x66, 0x75, 0x6c, 0x36, 0x2c, 0x60, 0x6f, 0xe2, 0x0f, 0x62, 0xe7, 0x0f, 0x44, 0x88, 0x50, 0x4c, 0xf4, 0x2c, 0x20, 0x72, 0x56, 0x6e, 0xa1, 0x97, 0xe4, 0x26, 0xef, 0x86, 0x60, 0x30, 0x27, 0x91, 0x67, 0xa1, 0x0b, 0x99, 0x13, 0x20, 0x61, 0xa3, 0x75, 0x62, 0x6c, 0x1d, 0xc0, 0x8f, 0x6f, 0xd3, 0x13, 0xe1, 0x9a, 0x52, 0x28, 0x33, 0x2e, 0x20, 0xee, 0x4f, 0x83, 0x42, 0x31, 0x45, 0x71, 0x9f, 0x6f, 0xd3, 0x92, 0x82, 0x2b, 0x80, 0x0d, 0x1c, 0x72, 0x69, 0x90, 0x58, 0x62, 0x3c, 0x44, 0x29, 0x20, 0x48, 0x65, 0x81, 0x10, 0x5d, 0x72, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x93, 0x2c, 0xff, 0x41, 0x5b, 0xd9, 0x46, 0x11, 0x10, 0xf1, 0x0e, 0x6b, 0x26, 0x82, 0x38, 0xd8, 0x98, 0xf0, 0x00, 0x43, 0xb0, 0x78, 0xd5, 0x05, 0x0a, 0x61, 0x20, 0x68, 0x73, 0x05, 0x66, 0xf7, 0x70, 0x05, 0x43, 0x0a, 0xc0, 0x24, 0x70, 0xf0, 0x67, 0xa1, 0x04, 0xa1, 0x1b, 0xf4, 0x07, 0x33, 0x90, 0x69, 0x6c, 0x3d, 0x73, 0x75, 0xc0, 0x7a, 0x03, 0x08, 0x0a, 0x63, 0x1f, 0x90, 0x51, 0xd5, 0x23, 0x82, 0x9e, 0xd0, 0x12, 0xc2, 0x33, 0x63, 0x68, 0x6f, 0x3f, 0x10, 0xa1, 0x5c, 0x24, 0x60, 0x21, 0x21, 0xa9, 0xf0, 0x69, 0x57, 0xa2, 0x64, 0x0a, 0xce, 0x6d, 0x65, 0x0f, 0x00, 0x08, 0x51, 0x21, 0x6c, 0x69, 0x70, 0xae, 0xe0, 0x2e, 0x55, 0x60, 0xae, 0x6e, 0xf0, 0x2f, 0x72, 0x60, 0x8a, 0x6c, 0x41, 0x1d, 0x61, 0x3c, 0x6d, 0x65, 0x10, 0x0c, 0x90, 0x38, 0x62, 0x36, 0x60, 0xaf, 0x75, 0x63, 0xe2, 0x74, 0x00, 0x27, 0x0a, 0x6c, 0x61, 0x10, 0x07, 0xb0, 0x1e, 0xa1, 0x53, 0xc8, 0x61, 0x63, 0x63, 0x20, 0x99, 0x6f, 0x72, 0x50, 0x02, 0x01, 0x58, 0x45, 0x60, 0x6d, 0x6c, 0x80, 0x0f, 0x63, 0x72, 0x6f, 0x00, 0x01, 0x69, 0xba, 0x6e, 0xc0, 0x78, 0x65, 0x06, 0x3b, 0x43, 0xa9, 0x60, 0x50, 0x70, 0x50, 0x64, 0x19, 0xc0, 0xaa, 0x28, 0x74, 0xd0, 0x35, 0x40, 0x03, 0x66, 0x65, 0x77, 0x0b, 0x60, 0x4a, 0xa1, 0x02, 0x73, 0xa1, 0x40, 0x6c, 0x65, 0x6e, 0x67, 0x9c, 0x74, 0x68, 0xe0, 0x35, 0x40, 0x06, 0x10, 0xb4, 0x20, 0x62, 0x60, 0x3a, 0x39, 0x25, 0x12, 0x66, 0x6f, 0x01, 0xb3, 0xa0, 0x1b, 0x86, 0x34, 0x47, 0x69, 0x8a, 0x76, 0xb2, 0x8e, 0x6d, 0xa0, 0x94, 0x6e, 0x74, 0x20, 0xe0, 0x0c, 0xf3, 0x50, 0x10, 0xc3, 0x24, 0x65, 0x61, 0x60, 0x13, 0x72, 0xbb, 0x14, 0x25, 0x39, 0x1c, 0xff, 0x32, 0x41, 0x50, 0x17, 0xc1, 0x24, 0x85, 0x1f, 0xe0, 0x10, 0xa2, 0xa9, 0xa1, 0x6e, 0xb0, 0xb9, 0x7f, 0xc0, 0xbe, 0x55, 0x02, 0x55, 0x83, 0x12, 0x54, 0x61, 0x2e, 0x70, 0x02, 0xd0, 0x42, 0x65, 0xbf, 0xd1, 0x03, 0x25, 0x57, 0x02, 0x8c, 0x20, 0x04, 0xf4, 0x9f, 0xd2, 0x27, 0x20, 0xb0, 0x2e, 0xf4, 0x41, 0x63, 0xf0, 0x89, 0x70, 0x61, 0x9b, 0x41, 0x1e, 0x39, 0x08, 0x22, 0x2f, 0xff, 0xe1, 0xa4, 0x07, 0x43, 0xc4, 0x5d, 0x72, 0x06, 0x32, 0x2e, 0xa4, 0xc4, 0x81, 0x06, 0xd5, 0xc4, 0xfd, 0x92, 0x05, 0x34, 0x01, 0x58, 0xb8, 0x91, 0x93, 0x2a, 0xfe, 0x60, 0xeb, 0x8a, 0x54, 0x47, 0xc7, 0x7f, 0x23, 0x80, 0x33, 0xc0, 0x3c, 0x2c, 0x0a, 0x74, 0x00, 0x47, 0x10, 0x4f, 0x28, 0x6f, 0x67, 0x65, 0xb0, 0x0a, 0x72, 0x10, 0x84, 0x66, 0x66, 0xe1, 0xd1, 0x63, 0x76, 0x65, 0x6c, 0x79, 0xa1, 0x18, 0xc1, 0x22, 0x10, 0x8b, 0x6f, 0xf0, 0xcf, 0x80, 0x77, 0xd9, 0x5a, 0xf4, 0x19, 0x0a, 0x3d, 0x85, 0x95, 0x15, 0x63, 0xf8, 0x6f, 0x6e, 0x74, 0xe0, 0x40, 0x30, 0x26, 0xb0, 0x15, 0x61, 0x10, 0x7b, 0x09, 0xc5, 0x81, 0x24, 0x72, 0xa1, 0x44, 0x73, 0x65, 0x0a, 0xd0, 0x1f, 0xa0, 0x1c, 0x1c, 0x65, 0x72, 0xf1, 0x39, 0x80, 0x36, 0x50, 0xb1, 0x62, 0x75, 0x67, 0x7e, 0x67, 0xd1, 0x00, 0x62, 0x30, 0x59, 0x07, 0x21, 0x26, 0x43, 0x66, 0xb2, 0x97, 0x64, 0xe4, 0x6f, 0x20, 0x22, 0x1f, 0x6f, 0x66, 0x10, 0x5f, 0x60, 0x27, 0xbf, 0x22, 0xff, 0xbf, 0x22, 0x80, 0xb2, 0x52, 0x18, 0xbe, 0x22, 0x0b, 0x0a, 0x71, 0x20, 0x21, 0x18, 0xa1, 0x0b, 0x7f, 0xdf, 0x22, 0x01, 0xdd, 0x21, 0x0c, 0xdf, 0x22, 0x20, 0x24, 0xdf, 0x22, 0x80, 0xcf, 0x64, 0xfb, 0xe3, 0xae, 0xdf, 0x22, 0x20, 0xdb, 0x22, 0x5b, 0x08, 0xff, 0x22, 0xf2, 0xe1, 0x30, 0x79, 0xc7, 0xff, 0x22, 0xb0, 0xf3, 0xfa, 0x22, 0x20, 0x63, 0x29, 0x00, 0xf0, 0x7f, 0xc7, 0x91, 0x32, 0x0b, 0x64, 0x69, 0x73, 0x30, 0x39, 0x79, 0x73, 0x70, 0x84, 0x37, 0x35, 0xf4, 0x83, 0x34, 0x40, 0xc9, 0x75, 0x91, 0x18, 0xb1, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x63, 0x80, 0x92, 0x6f, 0x30, 0xdb, 0x63, 0x94, 0x41, 0x23, 0x65, 0x07, 0x2e, 0x03, 0x86, 0x97, 0x75, 0x12, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x03, 0xc4, 0x13, 0x80, 0x61, 0x6e, 0x73, 0xb7, 0x00, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x73, 0x2c, 0x20, 0x80, 0x61, 0x73, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x01, 0x70, 0x00, 0x61, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x00, 0x6e, 0x63, 0x65, 0x20, 0x64, 0x69, 0x72, 0x65, 0x00, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x00, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x02, 0x6f, 0x01, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x80, 0x70, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x02, 0x38, 0x00, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x08, 0x61, 0x6e, 0x64, 0x00, 0x1e, 0x69, 0x73, 0x20, 0x6c, 0x09, 0x00, 0xb2, 0x6e, 0x73, 0x00, 0x86, 0x6f, 0x63, 0x75, 0x6d, 0x20, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x01, 0x68, 0x64, 0x29, 0x80, 0x20, 0x44, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x05, 0x6e, 0x40, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x00, 0x62, 0x3a, 0x03, 0x02, 0x1f, 0x00, 0x57, 0x20, 0x30, 0x29, 0x20, 0x43, 0x6f, 0x10, 0x6e, 0x76, 0x65, 0x79, 0x02, 0x58, 0x4d, 0x69, 0x6e, 0x10, 0x69, 0x6d, 0x61, 0x6c, 0x00, 0x12, 0x72, 0x72, 0x65, 0x20, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x01, 0x8f, 0x53, 0x6f, 0xc4, 0x75, 0x72, 0x00, 0xa0, 0x75, 0x6e, 0x64, 0x01, 0x93, 0x00, 0x9c, 0x90, 0x74, 0x65, 0x72, 0x6d, 0x04, 0x8c, 0x69, 0x73, 0x01, 0x69, 0x5d, 0x01, 0x49, 0x4c, 0x03, 0x83, 0x00, 0xdf, 0x02, 0x95, 0x65, 0x0c, 0x44, 0x41, 0x04, 0x70, 0x70, 0x80, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x01, 0x80, 0x0c, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x05, 0x20, 0x73, 0x75, 0xc0, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x01, 0x0a, 0x83, 0x22, 0x03, 0x84, 0x38, 0x82, 0x36, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0xf1, 0x00, 0x05, 0x69, 0x74, 0x2c, 0x82, 0x55, 0x84, 0x90, 0x85, 0x1e, 0x00, 0x9e, 0x50, 0x6f, 0x6d, 0x62, 0x69, 0x01, 0x76, 0x72, 0x80, 0xaa, 0x6c, 0x18, 0x69, 0x6e, 0x6b, 0x02, 0x13, 0x89, 0x3b, 0x77, 0x69, 0x74, 0x02, 0x68, 0x00, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x80, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x81, 0x47, 0x6c, 0x6f, 0x66, 0x85, 0x22, 0x01, 0xbd, 0x4c, 0x00, 0x1d, 0x00, 0x0e, 0x56, 0x83, 0x04, 0x0e, 0x00, 0xc2, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x80, 0x80, 0x14, 0x61, 0x20, 0x06, 0x1d, 0x43, 0x03, 0x36, 0x64, 0x20, 0x57, 0x70, 0x6f, 0x72, 0x6b, 0x2c, 0x01, 0x66, 0x00, 0x1d, 0x85, 0x22, 0x6d, 0x08, 0x61, 0x6e, 0x6e, 0x00, 0x95, 0x73, 0x70, 0x65, 0x63, 0x61, 0x03, 0x34, 0x62, 0x79, 0x20, 0x73, 0x01, 0xee, 0xc0, 0x3e, 0x36, 0x3f, 0x0d, 0x71, 0x80, 0x40, 0x80, 0x77, 0x81, 0x60, 0xc0, 0x5a, 0x45, 0x10, 0x43, 0x6f, 0x87, 0x0f, 0x60, 0x03, 0x75, 0x81, 0x5a, 0x31, 0x29, 0x20, 0x55, 0x40, 0x7b, 0x84, 0x61, 0x20, 0x86, 0x4c, 0x73, 0x68, 0x61, 0x72, 0xc0, 0x2c, 0x00, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x00, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0xe6, 0x6d, 0xc1, 0x52, 0x40, 0x87, 0x6e, 0x6b, 0xc1, 0x71, 0x82, 0x3f, 0x88, 0x29, 0xc2, 0x4c, 0x43, 0x0b, 0x2e, 0x20, 0x20, 0x41, 0x47, 0x12, 0x87, 0x0e, 0x47, 0xc0, 0x95, 0xc1, 0x8e, 0x02, 0x5e, 0x28, 0x61, 0x29, 0x81, 0xa4, 0x73, 0x02, 0x20, 0x00, 0x61, 0x72, 0x75, 0x6e, 0x20, 0x74, 0x69, 0xd4, 0x6d, 0x65, 0xc5, 0x2a, 0x61, 0x41, 0xa7, 0x79, 0x85, 0x35, 0x04, 0x15, 0x00, 0x20, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x3c, 0x20, 0x70, 0x00, 0x92, 0x40, 0xa4, 0x80, 0xa1, 0x46, 0x6d, 0x27, 0x73, 0x31, 0x40, 0x0c, 0x6d, 0x70, 0x75, 0x80, 0x91, 0xc5, 0x10, 0x73, 0x79, 0x10, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x7d, 0x28, 0x62, 0x29, 0x28, 0x20, 0x77, 0x69, 0x00, 0xc8, 0x6f, 0x80, 0x7b, 0x61, 0x74, 0xe6, 0x65, 0x80, 0x10, 0x41, 0x02, 0x6c, 0x79, 0x40, 0x05, 0xd2, 0x6f, 0x05, 0x11, 0x4f, 0x44, 0xc7, 0x45, 0x20, 0x02, 0x2e, 0x00, 0x31, 0x69, 0x6e, 0x00, 0x1a, 0x66, 0x00, 0x61, 0x63, 0x65, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0xf7, 0x40, 0xa0, 0xc1, 0x98, 0xc5, 0x42, 0x20, 0x43, 0x7b, 0x85, 0x10, 0x04, 0x7d, 0x83, 0x5a, 0x00, 0x65, 0x29, 0x20, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x01, 0x00, 0xab, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x19, 0x83, 0xaf, 0x49, 0x6e, 0x81, 0xad, 0xc2, 0x02, 0x2c, 0x20, 0x62, 0x0c, 0x75, 0x74, 0xc0, 0x36, 0x00, 0x27, 0x69, 0x66, 0x20, 0x79, 0x00, 0x6f, 0x75, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x84, 0x20, 0x6f, 0x80, 0x59, 0x72, 0x77, 0x69, 0x73, 0x02, 0x49, 0x80, 0x62, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0xc0, 0xf7, 0x0d, 0xc0, 0x75, 0x6f, 0xc1, 0x19, 0x62, 0x0a, 0x73, 0x75, 0x63, 0x68, 0xfb, 0x00, 0x47, 0x66, 0x09, 0x20, 0xc3, 0x5d, 0x0d, 0x45, 0x41, 0x13, 0x04, 0x7e, 0xe3, 0x23, 0x0c, 0x6f, 0x6e, 0xa0, 0x0d, 0x43, 0x83, 0x20, 0x65, 0x78, 0x74, 0x4f, 0x81, 0x2b, 0x42, 0x1d, 0xee, 0x09, 0x63, 0x73, 0x6e, 0x65, 0xa0, 0x8e, 0x73, 0x1b, 0xa1, 0x42, 0x60, 0x06, 0x69, 0xe3, 0x18, 0x22, 0x87, 0x65, 0x78, 0x65, 0xfe, 0x63, 0x60, 0x30, 0x13, 0x62, 0x81, 0x35, 0x21, 0x0f, 0xea, 0x5c, 0x41, 0x17, 0x01, 0x61, 0xe4, 0x64, 0x20, 0x00, 0x5a, 0x72, 0x65, 0xc0, 0x29, 0x00, 0x6e, 0x21, 0x4b, 0x5e, 0x6f, 0x45, 0x6e, 0x81, 0x01, 0x24, 0x4c, 0x1f, 0x6f, 0x6e, 0x67, 0x46, 0x6e, 0xc2, 0x6b, 0x27, 0x6e, 0x2e, 0x20, 0x28, 0x49, 0x02, 0x72, 0xc1, 0x29, 0x11, 0xa0, 0x7c, 0x20, 0x6f, 0x70, 0xa2, 0x86, 0x34, 0x64, 0x30, 0x03, 0x23, 0x7f, 0x95, 0x31, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x64, 0x61, 0x63, 0xc2, 0x3c, 0x6e, 0x79, 0xc1, 0x17, 0x60, 0x11, 0x20, 0x1f, 0x9a, 0x9a, 0x41, 0xa8, 0x8b, 0x6d, 0xe8, 0x16, 0x03, 0x20, 0x64, 0x65, 0x2e, 0xcc, 0x20, 0x49, 0x83, 0x3b, 0xaa, 0x11, 0x31, 0x2c, 0x02, 0x3e, 0x82, 0x0e, 0x7f, 0x20, 0x84, 0x62, 0x3a, 0xe1, 0x0d, 0xc9, 0x13, 0x21, 0x08, 0xc8, 0x45, 0xe4, 0x84, 0x20, 0xff, 0x1f, 0x84, 0xa0, 0xac, 0x84, 0x3e, 0x41, 0x08, 0x60, 0x44, 0x40, 0x66, 0x64, 0x84, 0x0c, 0xab, 0xc9, 0xa3, 0xb3, 0x2e, 0x29, 0x41, 0xba, 0x35, 0x2e, 0x80, 0x03, 0xa2, 0xa0, 0x5e, 0x64, 0x00, 0x5b, 0x61, 0x81, 0xa0, 0xc6, 0x82, 0x59, 0x59, 0x40, 0x53, 0x6d, 0x7a, 0x61, 0xc0, 0x71, 0x6c, 0x00, 0x61, 0x20, 0x82, 0xe3, 0x84, 0xa0, 0x62, 0x69, 0x78, 0x6c, 0x69, 0x74, 0x41, 0xcb, 0x42, 0x48, 0x80, 0x88, 0xc0, 0x41, 0x77, 0xe1, 0x40, 0x9a, 0x20, 0x62, 0x61, 0x73, 0x40, 0x32, 0x00, 0x96, 0x40, 0x1a, 0x7a, 0x0a, 0x45, 0x6a, 0x73, 0x61, 0x61, 0x81, 0x99, 0xe1, 0x00, 0x02, 0xb8, 0x73, 0x87, 0x20, 0x3e, 0x40, 0xb6, 0x05, 0x8f, 0x74, 0x6f, 0x67, 0x65, 0x00, 0x06, 0x2e, 0x72, 0x43, 0x75, 0xa2, 0x60, 0x85, 0x0d, 0x0a, 0x91, 0x0d, 0x6e, 0x6f, 0x7c, 0x74, 0x20, 0x08, 0x2e, 0xe0, 0x8b, 0x80, 0xc7, 0xa1, 0x10, 0x01, 0x03, 0x63, 0xce, 0x6f, 0x00, 0xb4, 0x80, 0x10, 0x00, 0x0e, 0x74, 0x68, 0x80, 0x59, 0x2a, 0xcc, 0xfe, 0x63, 0xa3, 0xd6, 0x82, 0x5e, 0x21, 0x90, 0xa4, 0x1e, 0x05, 0x11, 0x49, 0xc7, 0xe0, 0x82, 0xc1, 0x40, 0x49, 0x72, 0x0a, 0x63, 0x68, 0x6f, 0x60, 0xd4, 0x80, 0xb5, 0xe1, 0x83, 0x39, 0x64, 0x6f, 0x20, 0x62, 0x20, 0x14, 0x85, 0x50, 0x8c, 0xe3, 0xfd, 0x00, 0x9e, 0x41, 0x25, 0x49, 0x22, 0x97, 0xa3, 0x5d, 0xc0, 0x11, 0x45, 0x0c, 0x42, 0x88, 0x21, 0x8b, 0x9f, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x80, 0x72, 0x6b, 0xcf, 0xc3, 0x27, 0x41, 0x37, 0x23, 0x28, 0xa4, 0x31, 0x79, 0x2c, 0x40, 0x3e, 0x86, 0x04, 0xbd, 0x03, 0x04, 0x6e, 0xa0, 0x53, 0x22, 0x13, 0x75, 0x05, 0x77, 0x12, 0x2c, 0x01, 0x04, 0x9f, 0x83, 0x0e, 0x70, 0x07, 0x24, 0x0d, 0xfd, 0x77, 0xa0, 0x05, 0x63, 0x65, 0xc0, 0x7f, 0xa3, 0x33, 0x4b, 0xb0, 0x53, 0x47, 0x69, 0x76, 0x32, 0x53, 0x6d, 0xc0, 0x70, 0xf8, 0x6e, 0x74, 0x20, 0x90, 0x14, 0x50, 0x0f, 0x03, 0x19, 0x70, 0x06, 0xa1, 0x57, 0x8d, 0x61, 0x72, 0x64, 0x46, 0x20, 0x92, 0x1f, 0x70, 0x61, 0x72, 0x70, 0x4c, 0xb0, 0x66, 0x20, 0x69, 0x74, 0x31, 0x07, 0x50, 0x53, 0x61, 0x78, 0x0c, 0x07, 0xc5, 0x5b, 0x64, 0x20, 0x63, 0x48, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x33, 0xf0, 0x82, 0x00, 0x8b, 0x77, 0x68, 0x30, 0x8c, 0xd1, 0x8a, 0x66, 0x69, 0x9f, 0xe0, 0x1b, 0x40, 0x06, 0x31, 0x04, 0x76, 0x38, 0x31, 0x41, 0x75, 0x6e, 0x56, 0x0f, 0x0f, 0xf1, 0x4e, 0x35, 0x17, 0xf6, 0x12, 0xc2, 0x0b, 0x36, 0x2e, 0x20, 0x52, 0x64, 0x65, 0x76, 0x40, 0x53, 0x64, 0x20, 0x74, 0x58, 0x1a, 0x8f, 0x4c, 0x64, 0x65, 0x73, 0x41, 0x91, 0x47, 0x65, 0xb0, 0x75, 0x30, 0x8a, 0x50, 0x2c, 0x75, 0x62, 0x00, 0x85, 0xda, 0x0f, 0x54, 0xb0, 0x11, 0x46, 0x72, 0x00, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x79, 0x61, 0x24, 0x46, 0x6f, 0x50, 0x13, 0x53, 0x5b, 0xd2, 0x2f, 0x31, 0x03, 0x73, 0x2e, 0x68, 0xe0, 0x58, 0x63, 0x06, 0xd0, 0x3f, 0x2f, 0xb0, 0x4b, 0x6e, 0x65, 0xf2, 0x77, 0xb5, 0x80, 0x73, 0x0a, 0x54, 0x64, 0xd1, 0x37, 0x1f, 0x07, 0x18, 0x07, 0xe0, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x82, 0x70, 0x72, 0x9a, 0x00, 0x71, 0xd8, 0x2e, 0x20, 0x53, 0x21, 0x5d, 0xd0, 0x04, 0x0a, 0x94, 0x85, 0x90, 0x9e, 0x03, 0x81, 0x6c, 0x00, 0x60, 0x73, 0x69, 0x6d, 0x69, 0x6c, 0x61, 0x02, 0x72, 0x01, 0x40, 0x73, 0x70, 0x69, 0x72, 0x69, 0x74, 0xbf, 0x42, 0x03, 0xf0, 0x0a, 0xf5, 0x71, 0x14, 0x03, 0x03, 0x65, 0xb0, 0x0a, 0x0a, 0x30, 0x8a, 0x03, 0xa0, 0xa1, 0x01, 0x03, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x91, 0x01, 0x03, 0x61, 0x64, 0x64, 0xe0, 0x74, 0x73, 0x20, 0x01, 0x0b, 0x17, 0x20, 0x47, 0x80, 0x6c, 0x71, 0x98, 0x72, 0xb1, 0x41, 0x63, 0x65, 0x72, 0x64, 0x6e, 0x73, 0x62, 0x14, 0x45, 0x61, 0x70, 0x65, 0xe4, 0x04, 0x20, 0x8d, 0x90, 0x1c, 0x67, 0xf0, 0x20, 0xb1, 0x96, 0x64, 0x69, 0x73, 0xe1, 0xa5, 0x30, 0x75, 0x69, 0x73, 0x68, 0x21, 0x19, 0x15, 0x02, 0x6e, 0x75, 0xf0, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x4e, 0x91, 0x1b, 0xa5, 0x3e, 0x50, 0xaa, 0x53, 0x40, 0x33, 0x90, 0x12, 0x63, 0x65, 0xf0, 0x03, 0x64, 0x80, 0x21, 0x20, 0x9d, 0xf5, 0x8c, 0x73, 0xf0, 0x30, 0x70, 0x80, 0xa0, 0x2f, 0x65, 0x72, 0x90, 0x09, 0xbc, 0x6e, 0x20, 0x23, 0x04, 0x20, 0x2a, 0x34, 0x05, 0x3f, 0x14, 0x20, 0x5f, 0x1b, 0xe9, 0x31, 0x2b, 0x20, 0x22, 0xd0, 0x17, 0x61, 0x10, 0x30, 0x90, 0x75, 0x00, 0x93, 0xf1, 0xe4, 0x03, 0x22, 0x0a, 0x61, 0xc1, 0xa2, 0xf0, 0xae, 0x11, 0x6b, 0xe0, 0x9e, 0xf9, 0x81, 0x08, 0x68, 0x61, 0x50, 0x2d, 0x00, 0x0a, 0xd5, 0x60, 0x60, 0x1a, 0x16, 0x3b, 0xaf, 0xf2, 0x39, 0x40, 0x7e, 0xc0, 0x10, 0x10, 0x1d, 0x0a, 0x10, 0x33, 0x64, 0x40, 0x4d, 0x40, 0x6f, 0x6e, 0x73, 0x20, 0x65, 0x69, 0x20, 0x03, 0x72, 0xdb, 0xe3, 0x26, 0x20, 0x0b, 0x70, 0xf3, 0x1f, 0x97, 0x0a, 0x20, 0xf0, 0x07, 0x90, 0x04, 0x4d, 0x2e, 0x08, 0x0a, 0x97, 0x02, 0xd2, 0x47, 0x65, 0x20, 0x7f, 0x25, 0x64, 0xdf, 0x72, 0x25, 0x85, 0x13, 0x80, 0x28, 0x33, 0x55, 0x83, 0x13, 0x0a, 0xe0, 0x71, 0x86, 0x13, 0xdc, 0x64, 0x6f, 0xb0, 0x0c, 0x11, 0x4d, 0x13, 0x14, 0x79, 0x30, 0x56, 0xa4, 0x0e, 0xf7, 0xa4, 0x13, 0xf5, 0x30, 0x47, 0x27, 0x0a, 0x0f, 0x13, 0x01, 0x13, 0x24, 0x67, 0x80, 0x5c, 0xfd, 0xc0, 0x4c, 0x6f, 0x31, 0xa0, 0xc0, 0x13, 0xb5, 0x04, 0x80, 0x0c, 0x01, 0x12, 0x4f, 0x04, 0xd2, 0x20, 0xbb, 0x32, 0x20, 0x65, 0x10, 0x03, 0x20, 0x1f, 0x0e, 0x9f, 0x33, 0xff, 0x13, 0x0e, 0x91, 0x65, 0x00, 0x70, 0xb1, 0x05, 0xdf, 0x21, 0xdf, 0x21, 0xd5, 0x21, 0x00, 0x2a, 0x00, 0x78, 0x79, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x64, 0x31, 0x70, 0xb0, 0x64, 0x65, 0x0a, 0x60, 0x42, 0x30, 0x04, 0x72, 0x20, 0xc0, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x16, 0x37, 0xcf, 0x0f, 0xcb, 0xdf, 0x22, 0x12, 0x4e, 0x20, 0x50, 0xae, 0x6c, 0x6c, 0xc2, 0x21, 0x80, 0x54, 0x61, 0x63, 0x4b, 0x72, 0x6f, 0x78, 0x79, 0xf0, 0xa4, 0xc2, 0x0c, 0x63, 0x2e, 0x20, 0x40, 0x9a, 0x60, 0xa4, 0xe2, 0xa6, 0x66, 0x81, 0x80, 0x65, 0x70, 0x7c, 0x74, 0x61, 0xb1, 0xd5, 0x24, 0x1e, 0x85, 0x12, 0xb0, 0x64, 0x91, 0xc4, 0x61, 0x02, 0x6e, 0x91, 0x02, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0xfc, 0x69, 0x7a, 0xb2, 0x0e, 0xf2, 0xb2, 0xe1, 0x26, 0x90, 0x27, 0x14, 0x16, 0x72, 0x06, 0xdf, 0x95, 0x03, 0x81, 0x78, 0x30, 0x0c, 0x05, 0x71, 0xf0, 0x36, 0x00, 0x0f, 0x00, 0x1f, 0x01, 0xff, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0xff, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0xff, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1a, 0x01, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_compressed_block_vector_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_compressed_block_vector_initialize( void ) { libcerror_error_t *error = NULL; libfdata_vector_t *compressed_block_vector = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_compressed_block_vector_data1, 80, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_compressed_block_vector_initialize( &compressed_block_vector, io_handle, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "compressed_block_vector", compressed_block_vector ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfdata_vector_free( &compressed_block_vector, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_block_vector", compressed_block_vector ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_compressed_block_vector_initialize( NULL, io_handle, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); compressed_block_vector = (libfdata_vector_t *) 0x12345678UL; result = libfsntfs_compressed_block_vector_initialize( &compressed_block_vector, io_handle, mft_attribute, &error ); compressed_block_vector = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_compressed_block_vector_initialize( &compressed_block_vector, NULL, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_compressed_block_vector_initialize( &compressed_block_vector, io_handle, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_compressed_block_vector_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_compressed_block_vector_initialize( &compressed_block_vector, io_handle, mft_attribute, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( compressed_block_vector != NULL ) { libfdata_vector_free( &compressed_block_vector, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_block_vector", compressed_block_vector ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_compressed_block_vector_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_compressed_block_vector_initialize( &compressed_block_vector, io_handle, mft_attribute, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( compressed_block_vector != NULL ) { libfdata_vector_free( &compressed_block_vector, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_block_vector", compressed_block_vector ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( compressed_block_vector != NULL ) { libfdata_vector_free( &compressed_block_vector, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_compressed_block_vector_read_element_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_compressed_block_vector_read_element_data( void ) { libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfcache_cache_t *cache = NULL; libfdata_vector_t *compressed_block_vector = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_compressed_block_vector_data1, 80, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_compressed_block_vector_initialize( &compressed_block_vector, io_handle, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "compressed_block_vector", compressed_block_vector ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfcache_cache_initialize( &cache, 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "cache", cache ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize file IO handle */ result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_compressed_block_vector_lznt1_compressed_data1, 24576, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ /* TODO pass data handle result = libfsntfs_compressed_block_vector_read_element_data( NULL, file_io_handle, compressed_block_vector, (libfdata_cache_t *) cache, 0, 0, 0, 4096, LIBFDATA_RANGE_FLAG_IS_COMPRESSED, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_compressed_block_vector_read_element_data( NULL, file_io_handle, compressed_block_vector, (libfdata_cache_t *) cache, 0, 0, 0, 4096, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); */ /* Test error cases */ result = libfsntfs_compressed_block_vector_read_element_data( NULL, file_io_handle, compressed_block_vector, (libfdata_cache_t *) cache, 0, 0, 0, 4096, LIBFDATA_RANGE_FLAG_IS_COMPRESSED, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_compressed_block_vector_read_element_data( NULL, file_io_handle, compressed_block_vector, (libfdata_cache_t *) cache, 0, 0, 0, 0, LIBFDATA_RANGE_FLAG_IS_COMPRESSED, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_compressed_block_vector_read_element_data( NULL, file_io_handle, compressed_block_vector, (libfdata_cache_t *) cache, 0, 0, 0, (size64_t) SSIZE_MAX + 1, LIBFDATA_RANGE_FLAG_IS_COMPRESSED, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_compressed_block_vector_read_element_data( NULL, file_io_handle, NULL, (libfdata_cache_t *) cache, 0, 0, 0, 4096, LIBFDATA_RANGE_FLAG_IS_COMPRESSED, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* TODO implement read from file IO handle failing */ #if defined( HAVE_FSNTFS_TEST_MEMORY ) /* Test libfsntfs_compressed_block_vector_read_element_data with malloc failing in libfsntfs_compressed_block_initialize */ fsntfs_test_malloc_attempts_before_fail = 0; result = libfsntfs_compressed_block_vector_read_element_data( NULL, file_io_handle, compressed_block_vector, (libfdata_cache_t *) cache, 0, 0, 0, 4096, LIBFDATA_RANGE_FLAG_IS_COMPRESSED, 0, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up file IO handle */ result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfcache_cache_free( &cache, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cache", cache ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfdata_vector_free( &compressed_block_vector, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_block_vector", compressed_block_vector ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } if( cache != NULL ) { libfcache_cache_free( &cache, NULL ); } if( compressed_block_vector != NULL ) { libfdata_vector_free( &compressed_block_vector, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_compressed_block_vector_initialize", fsntfs_test_compressed_block_vector_initialize ); FSNTFS_TEST_RUN( "libfsntfs_compressed_block_vector_read_element_data", fsntfs_test_compressed_block_vector_read_element_data ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_compressed_data_handle.c ================================================ /* * Library compressed_data_handle type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfdata.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_cluster_block_stream.h" #include "../libfsntfs/libfsntfs_compressed_data_handle.h" #include "../libfsntfs/libfsntfs_definitions.h" /* Define to make fsntfs_test_file generate verbose output #define FSNTFS_TEST_COMPRESSED_DATA_HANDLE_VERBOSE */ #define FSNTFS_TEST_COMPRESSED_DATA_HANDLE_VERBOSE uint8_t fsntfs_test_compressed_data_handle_lzxpress_huffman_compressed_data1[ 3414 ] = { 0x00, 0x00, 0x00, 0x00, 0xa0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0xb0, 0x89, 0x00, 0xb7, 0x98, 0xa9, 0x9a, 0xba, 0xba, 0xb0, 0x0a, 0x0b, 0x0b, 0x80, 0x8b, 0x8a, 0x89, 0x9b, 0x0b, 0x97, 0xba, 0x09, 0x8a, 0xa9, 0xaa, 0xa0, 0x00, 0x00, 0x00, 0x50, 0x57, 0x46, 0x76, 0x56, 0x8a, 0x66, 0x55, 0xb6, 0x55, 0x65, 0x77, 0x69, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x0a, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0xb9, 0xa9, 0xaa, 0x0b, 0x00, 0x00, 0xbb, 0x77, 0x89, 0x88, 0xa9, 0x9a, 0xbb, 0x0b, 0x90, 0x76, 0x87, 0xa9, 0xaa, 0xaa, 0x9a, 0xa0, 0x9a, 0x76, 0x77, 0x98, 0x9a, 0xa9, 0xb9, 0xbb, 0x9a, 0x75, 0x78, 0xa8, 0xa9, 0xa9, 0xba, 0xab, 0x80, 0x66, 0x77, 0x98, 0x09, 0x0a, 0xba, 0x00, 0xa0, 0x76, 0x78, 0x98, 0xa9, 0x0a, 0xa0, 0xab, 0xa0, 0x80, 0x9a, 0xba, 0xbb, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0xef, 0x00, 0xc0, 0xf0, 0xce, 0x50, 0xfc, 0x9b, 0xa3, 0x9f, 0x9f, 0xe2, 0x9b, 0x76, 0x06, 0x87, 0x6f, 0xe2, 0x9b, 0xd1, 0x65, 0x2f, 0x0e, 0xf8, 0x8b, 0xf0, 0xe8, 0x03, 0xf3, 0x99, 0xf5, 0x1e, 0xbe, 0x6b, 0x7e, 0x8b, 0x55, 0xbe, 0xfa, 0xa5, 0x30, 0x02, 0x41, 0x46, 0x83, 0xc3, 0x3b, 0x40, 0xc0, 0xef, 0x96, 0x1f, 0x88, 0x13, 0xdc, 0x77, 0x07, 0x0e, 0x69, 0xdf, 0xcc, 0xa0, 0x11, 0x44, 0xd4, 0x24, 0x58, 0xdd, 0xb3, 0x6f, 0x7c, 0x32, 0x0e, 0xd5, 0x44, 0x12, 0x3d, 0x43, 0x2e, 0x0e, 0x12, 0xa9, 0xc2, 0x21, 0x27, 0x44, 0x8b, 0x6c, 0xea, 0xad, 0xc3, 0x01, 0x72, 0x39, 0xf0, 0x83, 0xb5, 0xba, 0xe0, 0xc1, 0xf7, 0xef, 0x29, 0xee, 0xa4, 0xcc, 0x9e, 0x26, 0xf1, 0xff, 0x19, 0x34, 0x05, 0xb5, 0x22, 0x31, 0xa6, 0xba, 0x40, 0x50, 0x7c, 0x29, 0x58, 0xcb, 0x0b, 0xb6, 0x16, 0x40, 0xc0, 0xbb, 0xb6, 0x43, 0x99, 0x0d, 0x49, 0x4b, 0x42, 0xa9, 0x0a, 0xb1, 0xa5, 0xcc, 0x07, 0x5d, 0x1a, 0xf9, 0x53, 0x61, 0x87, 0x40, 0x6e, 0x01, 0xd3, 0xd6, 0x28, 0xc6, 0x42, 0x9d, 0xa0, 0x0d, 0xbe, 0xb0, 0x5d, 0x27, 0xad, 0x00, 0x2b, 0x00, 0x3d, 0xa4, 0x1e, 0x33, 0x19, 0x98, 0x58, 0x61, 0x42, 0xa7, 0x8f, 0xc0, 0x8a, 0x3c, 0xde, 0xa2, 0x51, 0x53, 0x0e, 0xc0, 0x96, 0x36, 0xa8, 0xeb, 0x47, 0xa3, 0x96, 0x83, 0xdd, 0x58, 0x15, 0x28, 0x52, 0x28, 0xc2, 0x19, 0x49, 0x71, 0x0e, 0x1e, 0x34, 0x2c, 0x31, 0x9e, 0x89, 0x42, 0xcb, 0x8b, 0xc7, 0x90, 0x13, 0x2a, 0x12, 0x02, 0xc6, 0x45, 0x6e, 0x09, 0x2e, 0x88, 0xea, 0x36, 0xac, 0xb4, 0x3b, 0xa8, 0x5d, 0x66, 0x94, 0x73, 0xcf, 0x15, 0x3a, 0xa8, 0x5e, 0xe7, 0xd2, 0x5d, 0xb8, 0x4d, 0xe1, 0x4c, 0xfa, 0x38, 0xb5, 0x2a, 0xad, 0xa8, 0x54, 0x00, 0x40, 0x30, 0xd9, 0xf0, 0x1f, 0x79, 0x51, 0xfa, 0x5c, 0x47, 0x8d, 0x40, 0x9d, 0xe9, 0x4b, 0x18, 0x6a, 0x83, 0xa5, 0xb2, 0xf4, 0x40, 0x3a, 0x82, 0x18, 0x45, 0xc7, 0xe5, 0x03, 0x24, 0x94, 0x81, 0x7e, 0x19, 0xfc, 0x82, 0x70, 0x21, 0x32, 0xc7, 0x86, 0xec, 0x7b, 0xf3, 0x41, 0x2d, 0xab, 0x0a, 0xd1, 0x41, 0x98, 0x48, 0x03, 0xf4, 0xe1, 0x22, 0xa7, 0x96, 0x00, 0x39, 0x70, 0x91, 0xa0, 0x52, 0xcb, 0x91, 0xc2, 0xa2, 0xc0, 0x8d, 0x03, 0xba, 0xc6, 0xfa, 0x0d, 0x94, 0x41, 0x76, 0x2d, 0x6f, 0xb3, 0xd5, 0x22, 0x2d, 0xce, 0x72, 0x1e, 0xe2, 0x1c, 0x0e, 0x29, 0x6d, 0x05, 0xe3, 0xc8, 0x9b, 0x48, 0xd4, 0x44, 0x44, 0x92, 0xcd, 0xc5, 0x92, 0x20, 0xc6, 0x77, 0x38, 0x72, 0x50, 0x75, 0x00, 0x9d, 0x8f, 0xa6, 0x9f, 0x2a, 0x4d, 0xa4, 0xc5, 0x26, 0x16, 0x13, 0xcd, 0xdc, 0x90, 0x06, 0xf2, 0xb8, 0x74, 0x48, 0xc6, 0x43, 0x32, 0x60, 0x51, 0xe4, 0x49, 0x31, 0x24, 0x6c, 0x90, 0x10, 0x16, 0x23, 0xd2, 0x0f, 0x96, 0x36, 0x7b, 0x7c, 0x91, 0x03, 0xd8, 0x40, 0x55, 0xc8, 0x4a, 0xd5, 0x38, 0xcb, 0x7e, 0x64, 0x64, 0xfc, 0x1b, 0x5e, 0xf1, 0x90, 0x5d, 0x05, 0x2d, 0x29, 0x2c, 0xd2, 0x26, 0x1f, 0xdc, 0x80, 0xb7, 0x51, 0x5e, 0xab, 0x1e, 0x93, 0xf7, 0x4f, 0x51, 0x08, 0x12, 0x08, 0x86, 0x8a, 0x5b, 0x6c, 0x95, 0x6a, 0xea, 0xdb, 0xd2, 0x3a, 0xa2, 0xaf, 0xba, 0xea, 0xbb, 0x62, 0x21, 0xef, 0x28, 0x6d, 0x66, 0xaa, 0x29, 0x2c, 0xdc, 0x12, 0x0f, 0xd3, 0xba, 0xd1, 0x56, 0x91, 0xbc, 0xd7, 0xae, 0xa6, 0x31, 0xe1, 0x46, 0x70, 0xe9, 0x05, 0xe2, 0x15, 0x60, 0x2b, 0x20, 0xa1, 0x98, 0x47, 0xf4, 0xdb, 0xff, 0xdb, 0x2c, 0x2a, 0xd8, 0x3a, 0x84, 0xb0, 0x7a, 0xdc, 0x43, 0xdf, 0xd3, 0x62, 0x70, 0x10, 0xd6, 0xa8, 0x38, 0x07, 0x53, 0x74, 0x41, 0x87, 0x00, 0xf1, 0x3d, 0x64, 0x58, 0x23, 0x66, 0x4b, 0xa8, 0x03, 0x74, 0xf4, 0x5b, 0xdb, 0x77, 0xb7, 0x84, 0xcb, 0x5d, 0x2d, 0xc9, 0xe4, 0x86, 0x78, 0x59, 0xd0, 0xc7, 0x99, 0xd3, 0xa1, 0xae, 0x55, 0xd8, 0xdd, 0x32, 0x5e, 0x0f, 0x32, 0xb8, 0x21, 0xe1, 0x12, 0x31, 0x16, 0xb3, 0x88, 0x17, 0xa8, 0x90, 0xc7, 0xc3, 0xf5, 0x62, 0xe9, 0x46, 0x5c, 0x83, 0xdd, 0x9c, 0xd2, 0x30, 0xb0, 0xff, 0x2a, 0x44, 0x6e, 0xc9, 0x1b, 0xf9, 0x33, 0x10, 0x4f, 0x2e, 0x00, 0x29, 0x3c, 0x52, 0xc1, 0xf4, 0x07, 0x8b, 0x14, 0x79, 0x15, 0x63, 0x07, 0x24, 0xa6, 0x8d, 0x45, 0xc6, 0x7c, 0xaa, 0x44, 0x6e, 0x19, 0xf1, 0x7d, 0x11, 0x6c, 0x94, 0x25, 0xc4, 0xa8, 0x22, 0xcd, 0x10, 0x82, 0x34, 0xe8, 0xf9, 0x25, 0x85, 0x80, 0x1c, 0x68, 0x73, 0xf8, 0x3c, 0x01, 0xec, 0x90, 0xba, 0x8a, 0x7f, 0x2d, 0x72, 0x1a, 0xed, 0x67, 0x02, 0xa0, 0x1d, 0xc7, 0x03, 0xd0, 0x2b, 0x6b, 0xb6, 0x71, 0x8e, 0xb9, 0x02, 0x31, 0x70, 0x24, 0x7b, 0x89, 0x65, 0x44, 0x20, 0xd1, 0x7e, 0x7d, 0x5d, 0xaf, 0xb1, 0x69, 0xa1, 0x92, 0x6e, 0xdc, 0x52, 0x80, 0xb5, 0xd9, 0x66, 0x6e, 0xaa, 0x38, 0x4b, 0xa1, 0xf2, 0x2e, 0xe2, 0x4a, 0x42, 0x44, 0x00, 0x5f, 0x8b, 0xbb, 0x08, 0xd9, 0xa8, 0xd2, 0xa3, 0x13, 0xa5, 0xfd, 0x1b, 0x51, 0x72, 0x24, 0xf4, 0xd7, 0x15, 0xe9, 0x09, 0x74, 0x84, 0x7a, 0x26, 0x32, 0x41, 0xdf, 0x38, 0x29, 0x58, 0xbc, 0x14, 0x0f, 0x2a, 0x91, 0x50, 0xed, 0xf8, 0xbd, 0xc8, 0xdf, 0xeb, 0x6f, 0xf6, 0x63, 0x3d, 0xc5, 0xe8, 0x25, 0x17, 0x47, 0x12, 0xdc, 0x8b, 0x6c, 0x44, 0x23, 0x64, 0x8d, 0x33, 0x2b, 0x5c, 0xc6, 0xa6, 0x57, 0xd2, 0x94, 0xd4, 0x47, 0x11, 0x07, 0x36, 0x6e, 0xc9, 0x56, 0x37, 0xd2, 0x76, 0xcd, 0xfd, 0xd1, 0x40, 0xd6, 0x28, 0x71, 0x34, 0x7c, 0xe0, 0x5f, 0x5f, 0x36, 0xf4, 0xb1, 0x74, 0xdf, 0x9f, 0xad, 0x96, 0x12, 0xec, 0x2f, 0x25, 0xd5, 0x3b, 0x8b, 0x27, 0x2c, 0xd6, 0x55, 0xd7, 0xe0, 0x94, 0x7b, 0xbc, 0x19, 0x8c, 0x72, 0xda, 0x16, 0x41, 0x26, 0xe3, 0xf3, 0x79, 0xcb, 0xc1, 0x2f, 0xa7, 0xf3, 0x6d, 0xb6, 0x5b, 0xf2, 0x22, 0xe4, 0x40, 0x19, 0xa4, 0x38, 0x3d, 0x05, 0x89, 0x41, 0xa2, 0x96, 0x47, 0xcc, 0xea, 0x46, 0x13, 0xaa, 0x10, 0xa0, 0x4b, 0x9e, 0x56, 0xb0, 0x2a, 0x98, 0x0e, 0x0e, 0x7f, 0x04, 0xd3, 0xbf, 0xca, 0x20, 0xa6, 0xec, 0x55, 0xcd, 0xdd, 0x32, 0x2b, 0x44, 0x42, 0x0a, 0x0a, 0x66, 0x4d, 0xe9, 0x5e, 0x93, 0x72, 0xc7, 0x5a, 0xb1, 0x22, 0xfb, 0x6f, 0x1e, 0xf6, 0x3d, 0x94, 0x54, 0x34, 0x96, 0x9f, 0xd2, 0x0d, 0x11, 0xc3, 0x99, 0xf8, 0x74, 0x68, 0x95, 0x0d, 0xe7, 0x8a, 0xc0, 0xfe, 0xc9, 0xeb, 0x46, 0x82, 0x1b, 0x3f, 0x2d, 0x5c, 0x07, 0x2d, 0x22, 0x55, 0x81, 0x6d, 0xb9, 0x24, 0x25, 0xe5, 0x1f, 0x52, 0x90, 0x8b, 0x60, 0x71, 0x74, 0x08, 0xa7, 0xb3, 0x5b, 0xed, 0x29, 0xc4, 0x42, 0x21, 0x07, 0x6e, 0x39, 0xc9, 0x0e, 0xdc, 0xe2, 0x56, 0x98, 0x69, 0xc9, 0x1a, 0x0e, 0xc8, 0xca, 0x44, 0x59, 0x50, 0x99, 0xa7, 0x9e, 0x4b, 0xbb, 0x8b, 0x74, 0x75, 0x9a, 0xa1, 0xd8, 0x31, 0x07, 0xf2, 0x5d, 0x36, 0x3e, 0x53, 0x85, 0x84, 0x34, 0x38, 0x4d, 0x13, 0x5f, 0x20, 0xac, 0xa6, 0x22, 0xaa, 0x42, 0x27, 0xba, 0x7b, 0x0b, 0x7d, 0xde, 0xa6, 0x0c, 0x2a, 0x11, 0x8c, 0x21, 0x9a, 0xfc, 0x8a, 0x1c, 0xb6, 0x3e, 0x75, 0x42, 0xfd, 0x60, 0x1a, 0x5d, 0xa5, 0xd4, 0x6a, 0x01, 0x54, 0x0a, 0x1f, 0x64, 0x9b, 0xc1, 0x02, 0xe8, 0xeb, 0x64, 0xad, 0xcd, 0xe8, 0xda, 0x31, 0x51, 0xea, 0x44, 0x1d, 0x1a, 0xca, 0xa6, 0x04, 0xbb, 0xa3, 0x5e, 0x03, 0x1a, 0xad, 0x26, 0x21, 0x34, 0xdb, 0xb8, 0x4e, 0xc9, 0xe3, 0x02, 0x8b, 0x12, 0x9e, 0x8f, 0x41, 0x22, 0xf0, 0x5a, 0x36, 0xce, 0xdf, 0x2c, 0x8b, 0xb8, 0xd2, 0x78, 0x06, 0x35, 0x1f, 0x38, 0x06, 0xd4, 0x10, 0x71, 0x0b, 0x2a, 0x15, 0xd9, 0x2d, 0x43, 0x81, 0x0d, 0xb0, 0xa8, 0xf7, 0x07, 0xb5, 0x4a, 0xa6, 0x4b, 0xa5, 0x40, 0xe7, 0x99, 0x10, 0x81, 0x48, 0x0a, 0x55, 0xb1, 0xb7, 0xfe, 0x63, 0x95, 0xfc, 0x02, 0xb0, 0xe3, 0xac, 0x02, 0xf5, 0x8a, 0x48, 0xef, 0x44, 0x40, 0xde, 0xae, 0x97, 0xd1, 0x35, 0x39, 0x30, 0x85, 0x59, 0x22, 0x22, 0x2d, 0x0d, 0xf9, 0xba, 0x28, 0xa5, 0xfc, 0x8f, 0xd1, 0xc8, 0x4d, 0xa0, 0x5e, 0x4d, 0x08, 0xf4, 0xaf, 0x7d, 0xb2, 0xf8, 0x4f, 0x0e, 0xc7, 0x16, 0x77, 0x0c, 0x8d, 0x09, 0x2d, 0x17, 0xf1, 0x93, 0xbd, 0x1b, 0x79, 0xd6, 0x6c, 0x3f, 0xfa, 0x6f, 0xd8, 0x96, 0x43, 0xfb, 0x5d, 0x40, 0x87, 0x3a, 0x4c, 0x27, 0xdd, 0x1f, 0xa7, 0xba, 0xa8, 0x59, 0x7c, 0x7e, 0xcd, 0x1b, 0xc2, 0x94, 0x83, 0x9a, 0x1f, 0x93, 0x97, 0x53, 0x30, 0x89, 0x98, 0x8e, 0x5a, 0xca, 0x19, 0xd0, 0x88, 0x86, 0xa5, 0x3b, 0x46, 0x91, 0x38, 0x49, 0xd9, 0xc3, 0xab, 0xc7, 0xb1, 0x85, 0xa3, 0x0f, 0xf2, 0x24, 0xc8, 0x38, 0xbd, 0x19, 0xe1, 0xbe, 0xe1, 0xe3, 0xca, 0x20, 0x3a, 0x5e, 0x8a, 0x68, 0x4f, 0x71, 0x6e, 0x7c, 0x09, 0x4d, 0x23, 0x99, 0xfd, 0x60, 0x9f, 0xc7, 0x18, 0x80, 0xd5, 0x99, 0x59, 0xa7, 0x58, 0xe6, 0x55, 0x0e, 0x88, 0xb0, 0xe9, 0x76, 0xe5, 0x92, 0x35, 0x42, 0x9a, 0x26, 0xf2, 0xdf, 0xe1, 0xa6, 0xfa, 0x84, 0xbc, 0xf0, 0x43, 0xd5, 0x75, 0xbd, 0x0c, 0xb0, 0x6e, 0x8a, 0x16, 0xe3, 0x88, 0x7b, 0x42, 0x71, 0x28, 0x98, 0x9e, 0x44, 0xc4, 0x52, 0x88, 0x75, 0x05, 0x2f, 0x06, 0x46, 0xc4, 0x5d, 0x60, 0xca, 0xcb, 0x8f, 0x79, 0x7f, 0x9e, 0x23, 0x86, 0xf4, 0x5f, 0xee, 0xfb, 0x67, 0xa8, 0x3a, 0x8d, 0xc6, 0xe8, 0xcf, 0xb9, 0xf1, 0x0b, 0x2d, 0xb4, 0x42, 0xb7, 0x8f, 0x24, 0x79, 0x8d, 0x40, 0x15, 0xbd, 0x1b, 0x9d, 0x67, 0xc2, 0x7b, 0xc3, 0x55, 0xf2, 0x2b, 0x2b, 0xf1, 0x27, 0xe5, 0x25, 0x61, 0xc8, 0x4e, 0x8a, 0x52, 0x84, 0x94, 0x32, 0xd6, 0x0a, 0x12, 0xd7, 0x96, 0x37, 0x7a, 0x4a, 0x65, 0x44, 0x34, 0x78, 0xc7, 0xb4, 0xd3, 0x78, 0xbf, 0x7a, 0xcf, 0xd8, 0xc6, 0x5f, 0x2c, 0xeb, 0x81, 0x16, 0xc5, 0xcb, 0xb7, 0x7a, 0x65, 0x5c, 0xb5, 0xa2, 0x1a, 0xd2, 0x90, 0xea, 0x5d, 0x3c, 0xe8, 0xa6, 0x27, 0x59, 0xb7, 0xaf, 0x5f, 0x17, 0x2b, 0x49, 0x41, 0xf7, 0x12, 0x21, 0x5b, 0x10, 0x47, 0xc8, 0xf3, 0x63, 0xaa, 0xeb, 0xd3, 0x73, 0xd2, 0x50, 0x8d, 0x4e, 0x6f, 0x31, 0x9f, 0x3e, 0xef, 0x85, 0x4e, 0x0c, 0xc8, 0x4d, 0x15, 0x82, 0x5a, 0xbb, 0x42, 0xdc, 0x8d, 0xbd, 0x72, 0x0f, 0x75, 0xe4, 0x44, 0x5b, 0x43, 0x65, 0xa4, 0x5d, 0x1e, 0x78, 0x46, 0x44, 0xcb, 0x83, 0xdb, 0x0d, 0xa8, 0xa6, 0xba, 0x38, 0xcd, 0x5c, 0xa1, 0x84, 0xa0, 0x5d, 0x6b, 0x24, 0x27, 0x47, 0xc1, 0x3b, 0x94, 0xef, 0x3c, 0xe1, 0x39, 0x8c, 0x63, 0x05, 0x92, 0xf1, 0xd6, 0x50, 0x51, 0x8c, 0x53, 0xaf, 0x44, 0xd0, 0xb1, 0x3f, 0xd8, 0x1d, 0x03, 0x65, 0x99, 0x1f, 0x2a, 0x87, 0x80, 0x47, 0xc6, 0x70, 0xfd, 0x93, 0x96, 0xd8, 0x13, 0xb6, 0x47, 0x6a, 0xb2, 0x65, 0x7a, 0x2e, 0x48, 0x3a, 0x51, 0xf3, 0x86, 0xb4, 0xd1, 0x17, 0x16, 0xcb, 0xe3, 0x6b, 0xcb, 0x99, 0xbf, 0x7e, 0x81, 0x7d, 0x94, 0x0f, 0x9b, 0x09, 0x1d, 0xbe, 0xd0, 0xf2, 0xaa, 0xc0, 0x3f, 0xe9, 0xe7, 0xb0, 0x4c, 0xb9, 0x9d, 0xb6, 0x1a, 0x00, 0x87, 0x48, 0xb7, 0x02, 0x0d, 0xba, 0x9a, 0x2c, 0x1e, 0x13, 0xa6, 0x48, 0x23, 0x33, 0x84, 0x73, 0x1c, 0x27, 0x3e, 0x9a, 0x2f, 0xa8, 0x6e, 0x45, 0x45, 0x2e, 0x48, 0xe0, 0xa0, 0xe2, 0x58, 0x05, 0x86, 0x3e, 0x7d, 0xe5, 0x81, 0x8b, 0x0b, 0xae, 0x4d, 0xac, 0x21, 0x7d, 0x8e, 0x52, 0xb9, 0xb9, 0x75, 0x50, 0x07, 0xca, 0x4d, 0xc8, 0xe7, 0x22, 0xa3, 0xcb, 0x56, 0x5b, 0x00, 0xc8, 0x48, 0x1e, 0x8f, 0x3d, 0x91, 0x1c, 0x33, 0x26, 0x45, 0x81, 0x66, 0x07, 0xc6, 0x1a, 0x9b, 0xd3, 0x50, 0x3a, 0xd1, 0xa8, 0x60, 0xd0, 0x64, 0xed, 0xe6, 0xc6, 0x78, 0x04, 0xe6, 0x8f, 0xa4, 0x5f, 0x4e, 0x40, 0x1b, 0xf3, 0x5c, 0x22, 0x94, 0x1e, 0xb1, 0xb3, 0xd0, 0xe6, 0xe4, 0x2c, 0x0f, 0x6e, 0x1d, 0x61, 0x55, 0xfb, 0x49, 0xe0, 0xc0, 0x3a, 0x7b, 0x33, 0x65, 0x84, 0xf6, 0x7a, 0xda, 0x24, 0x74, 0x17, 0x3d, 0x55, 0x03, 0xd6, 0xbc, 0x18, 0xda, 0x72, 0x01, 0x25, 0xe0, 0x67, 0x54, 0x3f, 0x5b, 0x78, 0x00, 0xb4, 0xb1, 0xca, 0x6c, 0xe2, 0x81, 0xad, 0x44, 0x5a, 0x84, 0x4e, 0x4d, 0x89, 0x7e, 0x92, 0x7e, 0x6e, 0xa0, 0x71, 0x1b, 0x26, 0x58, 0x38, 0xee, 0x1c, 0x96, 0xfa, 0x67, 0x99, 0x53, 0x76, 0xe8, 0xa3, 0x28, 0x27, 0xfc, 0x2f, 0xdc, 0x4d, 0x34, 0xac, 0x7e, 0xd0, 0x47, 0x7a, 0x7a, 0xac, 0xe7, 0x6a, 0x9b, 0x2c, 0x33, 0xa0, 0x9e, 0x32, 0xaa, 0x33, 0xcc, 0x32, 0xb4, 0xac, 0x30, 0x28, 0xe3, 0x9e, 0xa7, 0x36, 0x5c, 0xde, 0x64, 0xc9, 0x39, 0x6f, 0xfd, 0x15, 0x16, 0x58, 0x5e, 0xea, 0xcc, 0x40, 0xec, 0x88, 0xca, 0x3b, 0x0c, 0xfb, 0x91, 0xb0, 0xb9, 0xb4, 0x78, 0xdf, 0x75, 0xd7, 0x0d, 0xf7, 0x96, 0xc5, 0x3b, 0x23, 0xfc, 0x21, 0x79, 0x20, 0xe1, 0x39, 0x3e, 0xfc, 0x6b, 0xb7, 0x86, 0x9f, 0x81, 0x93, 0x81, 0x34, 0xba, 0xc3, 0x02, 0x43, 0x3c, 0xdf, 0x1c, 0xa1, 0x53, 0xeb, 0xf8, 0x06, 0x8a, 0xc5, 0xe7, 0x5f, 0x36, 0x8d, 0x4a, 0x0c, 0x5d, 0xc1, 0x3e, 0xaf, 0x56, 0xf3, 0xad, 0xfb, 0x15, 0x29, 0x83, 0x40, 0x68, 0xb6, 0xe5, 0xea, 0xab, 0xe1, 0x06, 0x37, 0x62, 0x0e, 0x43, 0x31, 0xcb, 0xa3, 0x31, 0xf1, 0xff, 0xd2, 0x0f, 0xfc, 0x42, 0x25, 0x92, 0x65, 0x33, 0x6b, 0x70, 0x45, 0xb0, 0xee, 0xdf, 0x9f, 0xdc, 0xdb, 0x83, 0xb0, 0x09, 0xeb, 0x3d, 0xac, 0xb9, 0x7e, 0x9d, 0x17, 0x8c, 0xe4, 0x75, 0xa3, 0x50, 0x26, 0x93, 0x81, 0x8b, 0xc4, 0x3e, 0xc6, 0x59, 0x80, 0xcd, 0x0d, 0xad, 0xe2, 0x43, 0xf2, 0xb3, 0xfd, 0x50, 0x6f, 0xa3, 0x52, 0xec, 0x20, 0xea, 0xe2, 0x86, 0x8d, 0x3e, 0x8f, 0xcc, 0x87, 0x27, 0x75, 0x73, 0x0e, 0xed, 0x2c, 0x25, 0xc3, 0x03, 0x19, 0xdf, 0xcf, 0xa1, 0xc2, 0x88, 0xed, 0x51, 0x5d, 0x21, 0x9f, 0x25, 0xcf, 0xa0, 0xfa, 0xe3, 0x12, 0x13, 0x44, 0xb5, 0x99, 0x51, 0x63, 0xe0, 0xc1, 0x86, 0x6d, 0xd9, 0x61, 0xaf, 0x3c, 0x25, 0x7b, 0xea, 0x09, 0x46, 0x0c, 0x2f, 0xbe, 0x9b, 0xb6, 0x8f, 0x98, 0xf3, 0x70, 0x5b, 0x3e, 0xa3, 0xa0, 0x57, 0x77, 0xdd, 0x91, 0x48, 0xee, 0xb3, 0x78, 0x01, 0x31, 0x99, 0xed, 0xd2, 0xa9, 0xc5, 0x4c, 0xb2, 0xbd, 0x7c, 0x7b, 0xe9, 0x4a, 0x65, 0x0e, 0xb0, 0x3f, 0x7b, 0x95, 0x0d, 0x77, 0xb3, 0x55, 0x11, 0xff, 0xfb, 0xd6, 0x82, 0x09, 0xee, 0x8f, 0x50, 0x76, 0x5f, 0x06, 0x57, 0xa2, 0xb6, 0xa1, 0x2f, 0x16, 0x2e, 0x0f, 0xef, 0x3c, 0x93, 0x89, 0x24, 0x8d, 0x60, 0x91, 0x67, 0x98, 0x86, 0x43, 0x61, 0x7f, 0x60, 0x31, 0x7c, 0xa2, 0x4e, 0x8e, 0xa0, 0xa2, 0x92, 0x47, 0x6f, 0x24, 0x5b, 0x14, 0x09, 0x15, 0xfb, 0xe5, 0x12, 0x37, 0x81, 0x8d, 0xf7, 0x53, 0x5a, 0x15, 0xc1, 0x4f, 0xc5, 0x0a, 0x23, 0x3d, 0x44, 0x25, 0x8b, 0xa5, 0x7d, 0xf7, 0xd2, 0xb7, 0x95, 0xc7, 0xf3, 0x4d, 0x2b, 0x18, 0xf0, 0x6f, 0x5e, 0x0a, 0xff, 0x9f, 0xb0, 0xf5, 0x45, 0x35, 0x04, 0xc6, 0xc2, 0xab, 0x76, 0xbb, 0x35, 0xd3, 0x1a, 0xe6, 0x2b, 0x9f, 0xee, 0xa8, 0x74, 0x09, 0x7e, 0x7b, 0x5b, 0x4e, 0xc6, 0x65, 0x90, 0x1f, 0x67, 0x70, 0x42, 0xae, 0x37, 0xe3, 0x27, 0xc0, 0x0e, 0xeb, 0x4a, 0xe4, 0x58, 0x17, 0x87, 0x09, 0xba, 0xc3, 0xa1, 0x96, 0x3a, 0x9e, 0x47, 0xfa, 0xc2, 0xcf, 0x70, 0x6f, 0x79, 0x4c, 0xe6, 0xcd, 0x73, 0x8c, 0x07, 0x9c, 0xe9, 0x91, 0x08, 0x55, 0x08, 0x2f, 0x44, 0x08, 0x36, 0x9d, 0x91, 0x4d, 0x35, 0xaf, 0x2b, 0x99, 0x5d, 0x2a, 0xdd, 0xf3, 0x47, 0xcf, 0xc2, 0x7b, 0x03, 0xea, 0x24, 0x6c, 0x86, 0x73, 0x64, 0xd7, 0x95, 0xf9, 0x31, 0x6c, 0x86, 0x7e, 0xd8, 0x4d, 0x21, 0xdb, 0x9b, 0xcb, 0x22, 0x1c, 0xa4, 0x97, 0xbb, 0x1b, 0x80, 0x75, 0x9f, 0xda, 0x2e, 0xad, 0xed, 0x87, 0x6a, 0x21, 0xfa, 0x38, 0x7f, 0x28, 0x71, 0x44, 0xa9, 0x56, 0x4c, 0x36, 0x3c, 0x8c, 0xb4, 0xd0, 0x01, 0xe6, 0xf1, 0x07, 0x36, 0x14, 0xba, 0xd5, 0xf7, 0xfc, 0x1e, 0x36, 0x44, 0x1f, 0x45, 0xa3, 0x0b, 0x84, 0xde, 0x8a, 0xb7, 0xa4, 0x93, 0x4f, 0x64, 0x28, 0xa5, 0xce, 0x62, 0x5e, 0xef, 0x6c, 0xe6, 0xfd, 0x25, 0x99, 0x96, 0x8f, 0x7d, 0x53, 0x8d, 0x25, 0x4e, 0x13, 0xfb, 0xe7, 0xef, 0xbc, 0x46, 0x74, 0x20, 0x43, 0x9f, 0xc3, 0x7d, 0x5d, 0xdc, 0xd3, 0x96, 0x63, 0xe1, 0x10, 0xa1, 0xcc, 0x2c, 0x77, 0xd3, 0xf0, 0xed, 0x59, 0x28, 0xd6, 0x2f, 0x07, 0x8d, 0x07, 0x54, 0xe1, 0x89, 0xb4, 0x73, 0x6e, 0x2d, 0x9e, 0xec, 0xb5, 0x9f, 0x38, 0xaa, 0x29, 0xce, 0x49, 0x0a, 0x62, 0x5e, 0x0b, 0x3e, 0xac, 0x6f, 0xc0, 0xe2, 0x15, 0x53, 0x41, 0x99, 0x75, 0xbb, 0xf5, 0x21, 0x77, 0xc7, 0x31, 0xb4, 0xcb, 0xca, 0xfd, 0x1a, 0xeb, 0x84, 0x1f, 0xed, 0x17, 0xb0, 0x5f, 0x60, 0x69, 0x36, 0xc7, 0x30, 0x84, 0xf2, 0x92, 0x3b, 0x1a, 0x46, 0xc6, 0xa3, 0x12, 0x9d, 0xb7, 0x0c, 0xfa, 0xd1, 0x33, 0x65, 0x0a, 0x72, 0x07, 0x46, 0x71, 0xbd, 0x3f, 0x91, 0xf3, 0x26, 0xda, 0x87, 0x9a, 0xfd, 0x30, 0x86, 0x04, 0xbe, 0x5b, 0x25, 0x53, 0x37, 0xef, 0xed, 0x22, 0x3a, 0xcf, 0xc6, 0xc5, 0x65, 0xe6, 0x58, 0x11, 0xaa, 0x0f, 0xe8, 0x84, 0x22, 0x05, 0xe3, 0x7f, 0x6b, 0x13, 0xc8, 0x4c, 0x46, 0x81, 0xe2, 0x62, 0x37, 0x63, 0x13, 0xcb, 0x22, 0x8d, 0x91, 0x68, 0xcf, 0xe9, 0xf5, 0x1f, 0x5a, 0x51, 0x8a, 0x29, 0x14, 0xdd, 0x51, 0xe3, 0xd4, 0x3d, 0xfd, 0x09, 0xd6, 0x98, 0x4c, 0xee, 0xb6, 0x34, 0xc2, 0x46, 0xc5, 0xc2, 0xe2, 0xb2, 0xd4, 0xa1, 0xc6, 0x71, 0xbf, 0xca, 0x97, 0x6c, 0x4c, 0xe8, 0x86, 0x31, 0x9f, 0x28, 0x31, 0x16, 0x6b, 0xb7, 0x3e, 0x74, 0x14, 0xfd, 0x0a, 0x93, 0x45, 0x0c, 0xdb, 0xca, 0x5b, 0x6a, 0x4c, 0xb3, 0xb1, 0x5c, 0x0a, 0x86, 0x14, 0xa7, 0x6b, 0x2a, 0x0a, 0xb7, 0x75, 0xb6, 0x93, 0x53, 0x51, 0x7a, 0xec, 0xa2, 0x0e, 0xb2, 0xe7, 0x21, 0x54, 0x91, 0x3b, 0xdf, 0xcb, 0x63, 0x51, 0x29, 0x62, 0x28, 0x4e, 0x76, 0xa1, 0xa7, 0xdd, 0x37, 0x94, 0xde, 0x6f, 0x75, 0x4a, 0xb5, 0x22, 0x88, 0x11, 0xd5, 0x7c, 0x44, 0xa6, 0x43, 0x6e, 0x7f, 0x18, 0xed, 0x8d, 0x4f, 0x2a, 0x74, 0x99, 0x11, 0x13, 0xe6, 0x0d, 0xa6, 0xfa, 0x77, 0x1d, 0xa5, 0x5a, 0x49, 0x01, 0x16, 0x2d, 0x2a, 0x57, 0xfc, 0x13, 0xe2, 0xc3, 0xe0, 0x17, 0xa3, 0x57, 0xea, 0xb2, 0x5b, 0x1b, 0x9c, 0xce, 0x7b, 0xd2, 0x12, 0xf3, 0x54, 0xdf, 0x38, 0x1a, 0x54, 0x7c, 0xbc, 0x07, 0x7e, 0xe6, 0xc8, 0xf6, 0x6e, 0x15, 0x17, 0x93, 0x4e, 0xf9, 0xcb, 0xee, 0xa1, 0xb1, 0x89, 0xa4, 0xa4, 0xf5, 0xb3, 0x07, 0xdc, 0x16, 0xf1, 0x08, 0x4c, 0xd8, 0xff, 0xbf, 0xe8, 0xaa, 0xf1, 0xe2, 0x07, 0xe8, 0xca, 0x0c, 0xd8, 0x7e, 0x4e, 0x74, 0xf1, 0x91, 0x05, 0xa5, 0x3f, 0x21, 0x77, 0x33, 0x97, 0x10, 0x6d, 0xc3, 0xf6, 0xab, 0x2d, 0xcc, 0xf0, 0x3d, 0x83, 0x32, 0x1a, 0xc4, 0xbc, 0x86, 0xdb, 0x78, 0xf7, 0x02, 0x2e, 0x43, 0x5d, 0x3e, 0x55, 0x44, 0x8a, 0x88, 0x09, 0xe7, 0x3f, 0xc5, 0x03, 0xfe, 0xe9, 0xff, 0xf0, 0xae, 0xf6, 0x93, 0xd8, 0xc7, 0x3e, 0x3f, 0x04, 0x82, 0xa6, 0x4f, 0x1a, 0x4e, 0x19, 0x75, 0x82, 0x8e, 0x27, 0xfd, 0x46, 0x03, 0x09, 0x50, 0x8d, 0x24, 0xdb, 0xd7, 0xd4, 0xdf, 0x3c, 0x35, 0xd7, 0xec, 0x3c, 0xba, 0x83, 0x0a, 0x66, 0x60, 0xca, 0x93, 0x37, 0x66, 0x19, 0xca, 0x9f, 0x41, 0xac, 0x0c, 0x73, 0x1d, 0xd5, 0x9a, 0x30, 0x38, 0x3b, 0x59, 0x4c, 0xc3, 0xcc, 0x67, 0x13, 0xf1, 0x02, 0x30, 0x0c, 0xa8, 0x6f, 0x93, 0x5b, 0x06, 0x82, 0x2e, 0x24, 0x10, 0x27, 0x54, 0xa6, 0x5f, 0x0c, 0x03, 0x1a, 0xa3, 0x9b, 0xc6, 0x8e, 0x33, 0x92, 0x32, 0x33, 0xcb, 0xb2, 0x62, 0xe9, 0x19, 0xf2, 0x9b, 0xdd, 0x36, 0xaa, 0x67, 0x19, 0xd3, 0x39, 0x47, 0x9c, 0x6c, 0x22, 0x46, 0x08, 0x7e, 0x94, 0x83, 0x7b, 0x52, 0xbc, 0xfe, 0x46, 0xd2, 0x9e, 0x17, 0x24, 0x04, 0xa6, 0xca, 0x83, 0x6a, 0xb6, 0x88, 0x65, 0x36, 0x48, 0x2e, 0x4c, 0xc8, 0x6d, 0xa7, 0xf9, 0xc9, 0x3c, 0xc2, 0xd2, 0x2f, 0xe0, 0x14, 0xed, 0x38, 0x51, 0xdd, 0xea, 0x36, 0x56, 0xbe, 0x79, 0x03, 0x51, 0x22, 0x03, 0xae, 0x65, 0x60, 0xb7, 0x82, 0x86, 0x46, 0x27, 0xf1, 0x7b, 0x91, 0xea, 0xc6, 0x59, 0x29, 0x43, 0x23, 0x1b, 0xa6, 0x7a, 0x14, 0x35, 0x8a, 0x44, 0xd6, 0xde, 0xc8, 0x17, 0x43, 0x5f, 0x0f, 0xc4, 0x71, 0x11, 0xe5, 0xec, 0x21, 0x7f, 0x41, 0xa2, 0xc6, 0x03, 0x28, 0x98, 0x7e, 0x45, 0xac, 0x30, 0x91, 0xee, 0x65, 0x8d, 0x04, 0xef, 0x18, 0x8e, 0xbc, 0x3a, 0x21, 0x6e, 0xfb, 0xeb, 0x89, 0x2b, 0xc1, 0x35, 0x34, 0x90, 0x6d, 0x87, 0xa0, 0xa2, 0x99, 0xed, 0x41, 0x66, 0x02, 0xd4, 0x04, 0x6c, 0xa2, 0x75, 0xb3, 0x11, 0x00, 0xd9, 0xaa, 0x7a, 0x30, 0x82, 0x3a, 0x1a, 0x64, 0x4f, 0x5e, 0x1b, 0xbe, 0x82, 0xa0, 0xc7, 0x2c, 0xda, 0x8e, 0x74, 0x06, 0x81, 0x7b, 0x77, 0xde, 0x12, 0xaf, 0x69, 0x21, 0x43, 0x3d, 0xd1, 0x96, 0xc9, 0x1c, 0xb5, 0x8e, 0x42, 0x5c, 0x43, 0x8a, 0x7e, 0xbe, 0xba, 0xb0, 0x1e, 0x76, 0x8f, 0xe9, 0x34, 0xdb, 0x43, 0x37, 0x05, 0x32, 0x2f, 0xea, 0xca, 0x2d, 0x11, 0x65, 0x1d, 0xa9, 0xd6, 0xe1, 0x9c, 0x6b, 0x40, 0x16, 0x3a, 0x48, 0xa6, 0x38, 0xa5, 0x96, 0x18, 0x71, 0xc0, 0xcd, 0xb1, 0xf3, 0xa0, 0x3c, 0x14, 0x18, 0x80, 0x78, 0x38, 0xa4, 0x3b, 0x37, 0x6c, 0x08, 0xaa, 0x5a, 0xdc, 0xe8, 0x72, 0x8e, 0xc3, 0x15, 0x61, 0x28, 0x6e, 0xcf, 0x8f, 0xae, 0xb6, 0xdf, 0x00, 0xe7, 0xfc, 0x06, 0xcf, 0x5c, 0xb0, 0x3d, 0x8b, 0x1d, 0x0a, 0x10, 0xa2, 0xb7, 0x71, 0x94, 0x9d, 0xe2, 0x5a, 0x28, 0x50, 0x9a, 0xd8, 0x52, 0x7c, 0x48, 0x80, 0x4f, 0x21, 0xcb, 0x30, 0x4a, 0x87, 0x2c, 0xf0, 0x96, 0xe3, 0xd7, 0xc8, 0xd4, 0xa6, 0x0c, 0x14, 0xa0, 0x43, 0xbe, 0x68, 0xfd, 0x0a, 0x67, 0x42, 0xdd, 0xfa, 0x4d, 0x78, 0x09, 0xb8, 0x65, 0x31, 0xcc, 0x8d, 0x07, 0xfa, 0xec, 0x08, 0x75, 0x82, 0x50, 0x22, 0xdd, 0xa0, 0xc2, 0x46, 0xa5, 0xc1, 0x41, 0x24, 0xc4, 0xe8, 0x16, 0x44, 0xb5, 0x92, 0xd4, 0xc5, 0x44, 0xd3, 0x94, 0xa4, 0x5f, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_compressed_data_handle_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_compressed_data_handle_initialize( void ) { libcerror_error_t *error = NULL; libfdata_stream_t *compressed_data_stream = NULL; libfsntfs_compressed_data_handle_t *compressed_data_handle = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 3; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Initialize test */ result = libfsntfs_cluster_block_stream_initialize_from_data( &compressed_data_stream, fsntfs_test_compressed_data_handle_lzxpress_huffman_compressed_data1, 3414, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "compressed_data_stream", compressed_data_stream ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_compressed_data_handle_initialize( &compressed_data_handle, compressed_data_stream, 2, 7638, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "compressed_data_handle", compressed_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); compressed_data_stream = NULL; result = libfsntfs_compressed_data_handle_free( &compressed_data_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_data_handle", compressed_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ result = libfsntfs_cluster_block_stream_initialize_from_data( &compressed_data_stream, fsntfs_test_compressed_data_handle_lzxpress_huffman_compressed_data1, 3414, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "compressed_data_stream", compressed_data_stream ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_compressed_data_handle_initialize( NULL, compressed_data_stream, 2, 7638, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); compressed_data_handle = (libfsntfs_compressed_data_handle_t *) 0x12345678UL; result = libfsntfs_compressed_data_handle_initialize( &compressed_data_handle, compressed_data_stream, 2, 7638, &error ); compressed_data_handle = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_compressed_data_handle_initialize( &compressed_data_handle, NULL, 2, 7638, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_compressed_data_handle_initialize( &compressed_data_handle, compressed_data_stream, (uint32_t) -1, 7638, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_compressed_data_handle_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_compressed_data_handle_initialize( &compressed_data_handle, compressed_data_stream, 2, 7638, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( compressed_data_handle != NULL ) { compressed_data_handle->compressed_data_stream = NULL; libfsntfs_compressed_data_handle_free( &compressed_data_handle, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_data_handle", compressed_data_handle ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_compressed_data_handle_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_compressed_data_handle_initialize( &compressed_data_handle, compressed_data_stream, 2, 7638, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( compressed_data_handle != NULL ) { compressed_data_handle->compressed_data_stream = NULL; libfsntfs_compressed_data_handle_free( &compressed_data_handle, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_data_handle", compressed_data_handle ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_compressed_data_handle_free( &compressed_data_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_data_handle", compressed_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfdata_stream_free( &compressed_data_stream, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_data_stream", compressed_data_stream ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( compressed_data_handle != NULL ) { libfsntfs_compressed_data_handle_free( &compressed_data_handle, NULL ); } if( compressed_data_stream != NULL ) { libfdata_stream_free( &compressed_data_stream, NULL ); } return( 0 ); } /* Tests the libfsntfs_compressed_data_handle_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_compressed_data_handle_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_compressed_data_handle_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_compressed_data_handle_get_compressed_block_offsets function * Returns 1 if successful or 0 if not */ int fsntfs_test_compressed_data_handle_get_compressed_block_offsets( void ) { libcerror_error_t *error = NULL; libfdata_stream_t *compressed_data_stream = NULL; libfsntfs_compressed_data_handle_t *compressed_data_handle = NULL; int result = 0; /* Initialize test */ result = libfsntfs_cluster_block_stream_initialize_from_data( &compressed_data_stream, fsntfs_test_compressed_data_handle_lzxpress_huffman_compressed_data1, 3414, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "compressed_data_stream", compressed_data_stream ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_compressed_data_handle_initialize( &compressed_data_handle, compressed_data_stream, 2, 7638, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "compressed_data_handle", compressed_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); compressed_data_stream = NULL; /* Test regular cases */ result = libfsntfs_compressed_data_handle_get_compressed_block_offsets( compressed_data_handle, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_compressed_data_handle_get_compressed_block_offsets( NULL, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_compressed_data_handle_free( &compressed_data_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_data_handle", compressed_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( compressed_data_handle != NULL ) { libfsntfs_compressed_data_handle_free( &compressed_data_handle, NULL ); } if( compressed_data_stream != NULL ) { libfdata_stream_free( &compressed_data_stream, NULL ); } return( 0 ); } /* Tests the libfsntfs_compressed_data_handle_read_segment_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_compressed_data_handle_read_segment_data( void ) { uint8_t segment_data[ 16 ]; uint8_t expected_segment_data1[ 12 ] = { 0x09, 0x09, 0x20, 0x20, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x45, 0x53 }; libcerror_error_t *error = NULL; libfdata_stream_t *compressed_data_stream = NULL; libfsntfs_compressed_data_handle_t *compressed_data_handle = NULL; ssize_t read_count = 0; int result = 0; /* Initialize test */ result = libfsntfs_cluster_block_stream_initialize_from_data( &compressed_data_stream, fsntfs_test_compressed_data_handle_lzxpress_huffman_compressed_data1, 3414, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "compressed_data_stream", compressed_data_stream ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_compressed_data_handle_initialize( &compressed_data_handle, compressed_data_stream, 2, 7638, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "compressed_data_handle", compressed_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); compressed_data_stream = NULL; /* Test regular cases */ read_count = libfsntfs_compressed_data_handle_read_segment_data( compressed_data_handle, NULL, 0, 0, segment_data, 12, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "read_count", read_count, (ssize_t) 12 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( segment_data, expected_segment_data1, 12 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); /* Test error cases */ read_count = libfsntfs_compressed_data_handle_read_segment_data( NULL, NULL, 0, 0, segment_data, 16, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_compressed_data_handle_read_segment_data( compressed_data_handle, NULL, -1, 0, segment_data, 16, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_compressed_data_handle_read_segment_data( compressed_data_handle, NULL, 0, 0, NULL, 16, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_compressed_data_handle_read_segment_data( compressed_data_handle, NULL, 0, 0, segment_data, (size_t) SSIZE_MAX + 1, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_compressed_data_handle_free( &compressed_data_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_data_handle", compressed_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( compressed_data_handle != NULL ) { libfsntfs_compressed_data_handle_free( &compressed_data_handle, NULL ); } if( compressed_data_stream != NULL ) { libfdata_stream_free( &compressed_data_stream, NULL ); } return( 0 ); } /* Tests the libfsntfs_compressed_data_handle_seek_segment_offset function * Returns 1 if successful or 0 if not */ int fsntfs_test_compressed_data_handle_seek_segment_offset( void ) { libcerror_error_t *error = NULL; libfdata_stream_t *compressed_data_stream = NULL; libfsntfs_compressed_data_handle_t *compressed_data_handle = NULL; off64_t offset = 0; int result = 0; /* Initialize test */ result = libfsntfs_cluster_block_stream_initialize_from_data( &compressed_data_stream, fsntfs_test_compressed_data_handle_lzxpress_huffman_compressed_data1, 3414, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "compressed_data_stream", compressed_data_stream ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_compressed_data_handle_initialize( &compressed_data_handle, compressed_data_stream, 2, 7638, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "compressed_data_handle", compressed_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); compressed_data_stream = NULL; /* Test regular cases */ offset = libfsntfs_compressed_data_handle_seek_segment_offset( compressed_data_handle, NULL, 0, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ offset = libfsntfs_compressed_data_handle_seek_segment_offset( NULL, NULL, 0, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); offset = libfsntfs_compressed_data_handle_seek_segment_offset( compressed_data_handle, NULL, -1, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); offset = libfsntfs_compressed_data_handle_seek_segment_offset( compressed_data_handle, NULL, 0, 0, -1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_compressed_data_handle_free( &compressed_data_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compressed_data_handle", compressed_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( compressed_data_handle != NULL ) { libfsntfs_compressed_data_handle_free( &compressed_data_handle, NULL ); } if( compressed_data_stream != NULL ) { libfdata_stream_free( &compressed_data_stream, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( HAVE_DEBUG_OUTPUT ) && defined( FSNTFS_TEST_COMPRESSED_DATA_HANDLE_VERBOSE ) libfsntfs_notify_set_verbose( 1 ); libfsntfs_notify_set_stream( stderr, NULL ); #endif #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_compressed_data_handle_initialize", fsntfs_test_compressed_data_handle_initialize ); FSNTFS_TEST_RUN( "libfsntfs_compressed_data_handle_free", fsntfs_test_compressed_data_handle_free ); FSNTFS_TEST_RUN( "libfsntfs_compressed_data_handle_get_compressed_block_offsets", fsntfs_test_compressed_data_handle_get_compressed_block_offsets ); FSNTFS_TEST_RUN( "libfsntfs_compressed_data_handle_read_segment_data", fsntfs_test_compressed_data_handle_read_segment_data ); FSNTFS_TEST_RUN( "libfsntfs_compressed_data_handle_seek_segment_offset", fsntfs_test_compressed_data_handle_seek_segment_offset ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_compression.c ================================================ /* * Library compression type test program * * Copyright (C) 2018-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_compression.h" #include "../libfsntfs/libfsntfs_definitions.h" uint8_t fsntfs_test_compression_lznt1_compressed_data1[ 8192 ] = { 0x65, 0xb8, 0x00, 0x09, 0x09, 0x20, 0x20, 0x20, 0x47, 0x4e, 0x55, 0x00, 0x20, 0x4c, 0x45, 0x53, 0x53, 0x45, 0x52, 0x20, 0x00, 0x47, 0x45, 0x4e, 0x45, 0x52, 0x41, 0x4c, 0x20, 0x80, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x00, 0x18, 0x60, 0x45, 0x4e, 0x53, 0x45, 0x0a, 0x00, 0x90, 0x11, 0x08, 0x56, 0x00, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x00, 0x2c, 0x20, 0x32, 0x39, 0x20, 0x4a, 0x75, 0x6e, 0x00, 0x65, 0x20, 0x32, 0x30, 0x30, 0x37, 0x0a, 0x0a, 0x00, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x40, 0x68, 0x74, 0x20, 0x28, 0x43, 0x29, 0x02, 0x28, 0x20, 0x00, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x00, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x20, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x00, 0x7a, 0x2c, 0x20, 0x00, 0x49, 0x6e, 0x63, 0x2e, 0x20, 0x3c, 0x68, 0x74, 0x00, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x66, 0x73, 0x66, 0x00, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x40, 0x45, 0x76, 0x65, 0x72, 0x79, 0x6f, 0x00, 0x54, 0x69, 0x00, 0x73, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x00, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x01, 0x00, 0x5d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x00, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2a, 0x20, 0x00, 0x2b, 0x62, 0x00, 0x4f, 0x6d, 0x01, 0x1c, 0x69, 0x65, 0x00, 0x73, 0x0a, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x01, 0x00, 0x39, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x00, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x08, 0x74, 0x2c, 0x20, 0x00, 0x2f, 0x20, 0x63, 0x68, 0x61, 0x00, 0x6e, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, 0x02, 0x20, 0x00, 0x12, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x6c, 0x80, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x2e, 0x0a, 0x80, 0x5f, 0xbc, 0x20, 0x54, 0x01, 0x1d, 0x80, 0x29, 0x82, 0x6f, 0x02, 0x25, 0x65, 0x83, 0x93, 0x00, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x00, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x12, 0x62, 0x80, 0x2f, 0x20, 0x4c, 0x84, 0x31, 0x69, 0x6e, 0x63, 0x80, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x80, 0x40, 0xa0, 0x74, 0x68, 0x65, 0x20, 0x74, 0x00, 0x5b, 0x73, 0x02, 0x55, 0xa0, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x81, 0x77, 0x73, 0x81, 0x4c, 0x5d, 0x85, 0x2c, 0x33, 0x03, 0x53, 0x83, 0x2d, 0x0b, 0x2a, 0x0a, 0x04, 0x2a, 0x2c, 0x80, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x65, 0x81, 0x5d, 0x09, 0x00, 0x7f, 0x62, 0x79, 0x00, 0x6b, 0x65, 0x20, 0x61, 0x64, 0x17, 0x83, 0x26, 0x80, 0x41, 0x02, 0x8d, 0x73, 0x01, 0x54, 0x73, 0x20, 0x6c, 0x1b, 0x00, 0x88, 0x01, 0x12, 0x65, 0x00, 0x65, 0x00, 0x64, 0x20, 0x20, 0x30, 0x08, 0x2e, 0x20, 0x41, 0x07, 0x15, 0x44, 0x65, 0x66, 0x69, 0x06, 0x6e, 0x83, 0x42, 0x82, 0x0e, 0x41, 0x73, 0x20, 0x75, 0x73, 0x01, 0xc0, 0x0b, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x2c, 0x0c, 0x20, 0x22, 0x42, 0x4c, 0x04, 0x1e, 0x22, 0x20, 0x72, 0x65, 0xae, 0x66, 0x40, 0x78, 0x41, 0x5c, 0xd2, 0x2b, 0x4c, 0xc2, 0x42, 0x0a, 0xd3, 0x42, 0x16, 0x2c, 0x42, 0x3d, 0xc1, 0x40, 0x22, 0xc1, 0x97, 0x47, 0x50, 0x4c, 0x27, 0xdd, 0x13, 0x14, 0x12, 0x02, 0x2a, 0x22, 0x54, 0x00, 0x53, 0x4c, 0x69, 0xa0, 0x62, 0x72, 0x61, 0x72, 0x79, 0xc9, 0x11, 0x61, 0x80, 0x7b, 0x03, 0xc0, 0x26, 0x80, 0x30, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x67, 0x7a, 0x6f, 0x00, 0x03, 0x6e, 0x40, 0x03, 0x42, 0x49, 0xc0, 0x75, 0xc5, 0x50, 0x0a, 0x4a, 0x6f, 0x40, 0x22, 0x72, 0x40, 0x4e, 0x61, 0x6e, 0xc0, 0x25, 0x20, 0x12, 0x41, 0x00, 0x54, 0x69, 0x63, 0x82, 0x9f, 0x20, 0x6f, 0x72, 0x44, 0x20, 0x61, 0xc0, 0xab, 0x6d, 0x62, 0x69, 0x01, 0x0e, 0x57, 0xe1, 0x81, 0x11, 0x61, 0x73, 0x20, 0x64, 0x41, 0x4a, 0x01, 0x12, 0x46, 0x52, 0x50, 0x41, 0x6e, 0x20, 0x22, 0xc8, 0x0d, 0x22, 0x81, 0x8d, 0x61, 0x08, 0x6e, 0x79, 0x20, 0x02, 0x1e, 0x74, 0x68, 0x61, 0x74, 0xe0, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x02, 0x54, 0x01, 0x75, 0x00, 0x1a, 0x04, 0x69, 0x6e, 0x80, 0x7f, 0x66, 0x61, 0x63, 0x65, 0x20, 0x00, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x0e, 0x0a, 0x44, 0x6f, 0x44, 0x32, 0x83, 0xa2, 0x77, 0x68, 0x69, 0x63, 0x26, 0x68, 0x05, 0xa1, 0xc2, 0x29, 0x77, 0x69, 0xc0, 0xab, 0x62, 0x61, 0x4f, 0x41, 0x66, 0x40, 0xd7, 0xc1, 0x50, 0x04, 0x0c, 0x2e, 0x0a, 0x43, 0x70, 0x6e, 0x02, 0x67, 0xc0, 0x2c, 0x73, 0x75, 0x62, 0x63, 0x6c, 0x61, 0xfe, 0x73, 0xc2, 0x93, 0xc0, 0x41, 0x82, 0x02, 0x86, 0x2d, 0x43, 0x89, 0x84, 0x0d, 0x01, 0x17, 0x14, 0x64, 0x65, 0x40, 0x90, 0x64, 0x80, 0x0d, 0x6d, 0x6f, 0x64, 0x64, 0x65, 0x0a, 0x40, 0xb4, 0x75, 0x73, 0x81, 0xbf, 0xd2, 0x14, 0x20, 0xc3, 0xcb, 0x14, 0x43, 0x45, 0x20, 0x22, 0x43, 0x6f, 0x88, 0x24, 0xe3, 0x1f, 0xa3, 0xa3, 0x1f, 0xc0, 0x1b, 0x64, 0x75, 0x63, 0xc3, 0x2e, 0x63, 0x82, 0x04, 0x43, 0x41, 0x0b, 0x00, 0x2b, 0x6c, 0x69, 0x6e, 0x6b, 0xa3, 0x0c, 0x0a, 0xa1, 0x49, 0x2e, 0x77, 0x69, 0x74, 0x68, 0x60, 0x31, 0x65, 0xe0, 0x66, 0x19, 0x22, 0x3a, 0x2e, 0x20, 0xe0, 0x6d, 0xa0, 0x24, 0x61, 0x72, 0x74, 0xc0, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, 0xa1, 0x79, 0x29, 0x6f, 0x3d, 0xe4, 0x18, 0x0a, 0x02, 0x07, 0xe3, 0x25, 0xa1, 0x22, 0x0a, 0x12, 0x20, 0x77, 0x21, 0xc0, 0x36, 0x6d, 0x61, 0x64, 0x65, 0xa1, 0x1d, 0x61, 0x6c, 0x9e, 0x73, 0xc0, 0x84, 0x20, 0x7a, 0x80, 0x12, 0x21, 0x05, 0x22, 0x4c, 0x20, 0x11, 0x9b, 0xe0, 0x2f, 0x24, 0x96, 0x22, 0x42, 0x1a, 0x61, 0x4a, 0x22, 0x4d, 0x00, 0x62, 0x02, 0x6d, 0xa0, 0x68, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x06, 0x70, 0xa1, 0x74, 0xa0, 0x2b, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x10, 0x65, 0x22, 0x20, 0x66, 0xb0, 0x43, 0x6d, 0x65, 0x61, 0x74, 0x6e, 0x73, 0xc1, 0x17, 0x0a, 0x71, 0x06, 0x42, 0x06, 0x8e, 0x13, 0x2c, 0x80, 0x20, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x83, 0x21, 0xf8, 0x79, 0x20, 0x73, 0xe2, 0x0b, 0x80, 0x57, 0x60, 0x31, 0x61, 0x0c, 0x60, 0x86, 0xb7, 0x66, 0x83, 0x8e, 0x07, 0x60, 0x0d, 0x61, 0xc0, 0x96, 0x20, 0x88, 0x73, 0x80, 0x48, 0x92, 0x72, 0x40, 0x1a, 0x69, 0x6e, 0x80, 0x1c, 0x6f, 0x6c, 0x02, 0x58, 0xf1, 0x00, 0x6d, 0x72, 0x65, 0x0a, 0xaa, 0x45, 0x68, 0x2d, 0xc3, 0x70, 0xc1, 0x9b, 0xf9, 0x26, 0x49, 0x6e, 0x6b, 0x20, 0x08, 0x04, 0x21, 0xe7, 0x20, 0x6b, 0x19, 0xa9, 0x35, 0x06, 0x43, 0x00, 0x46, 0x3d, 0x21, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0xf6, 0x74, 0xe2, 0x19, 0xe1, 0x7e, 0x2f, 0xc0, 0x26, 0x48, 0x1c, 0x66, 0x22, 0x0a, 0x13, 0x27, 0x80, 0xa5, 0x28, 0x22, 0x80, 0xc1, 0x61, 0x0a, 0x61, 0xba, 0x75, 0x74, 0x20, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x61, 0x66, 0x67, 0x72, 0x80, 0x61, 0x6d, 0x73, 0x20, 0x6e, 0x65, 0x65, 0x40, 0x67, 0x39, 0x62, 0x08, 0x72, 0x65, 0x43, 0x4d, 0xc1, 0x28, 0xcf, 0x24, 0x66, 0x72, 0x7c, 0x6f, 0x6d, 0xe2, 0x32, 0xca, 0x0c, 0xa1, 0xbd, 0x87, 0x2f, 0xa1, 0x06, 0x53, 0xe0, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x84, 0x4f, 0x60, 0xc5, 0x65, 0xb0, 0x03, 0xca, 0x49, 0x22, 0x23, 0x31, 0x2e, 0x20, 0x45, 0x78, 0x63, 0xec, 0x65, 0x70, 0x61, 0x33, 0xc1, 0xa0, 0x53, 0x80, 0x1c, 0x02, 0xde, 0x45, 0x06, 0xa3, 0x44, 0x9b, 0x82, 0x05, 0x59, 0x6f, 0x75, 0x40, 0x80, 0x79, 0x80, 0x20, 0xd0, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x6d, 0x63, 0xa1, 0x91, 0x60, 0x2d, 0x17, 0x22, 0x84, 0xc0, 0xdd, 0xe0, 0xc6, 0x73, 0x03, 0x08, 0x73, 0x20, 0x33, 0x39, 0xc1, 0x24, 0x20, 0x34, 0xe3, 0x08, 0x07, 0x95, 0x22, 0x5c, 0x6f, 0x75, 0xd0, 0x74, 0x20, 0x62, 0x65, 0x61, 0x1c, 0x62, 0xa1, 0xe4, 0xa1, 0x71, 0x9f, 0xe4, 0x06, 0xc0, 0x06, 0x68, 0xd1, 0x60, 0xaa, 0x02, 0x0f, 0x32, 0x2e, 0xe0, 0x97, 0x03, 0x61, 0x0e, 0x41, 0x06, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x85, 0x27, 0x3c, 0x73, 0x42, 0x04, 0x49, 0x66, 0x20, 0x79, 0xc1, 0x13, 0x73, 0x81, 0x03, 0x43, 0x13, 0x70, 0x79, 0x65, 0x18, 0xc4, 0x35, 0x92, 0x22, 0x2c, 0xe6, 0x20, 0xa0, 0x25, 0x90, 0x02, 0x72, 0x20, 0x60, 0x42, 0x70, 0x04, 0x33, 0x52, 0x3a, 0x73, 0xb0, 0x01, 0x0a, 0x80, 0x4c, 0x83, 0x19, 0x57, 0x61, 0x61, 0x20, 0xf0, 0x66, 0x75, 0x6e, 0x63, 0xc2, 0x11, 0x00, 0x1f, 0x11, 0x1c, 0x41, 0x12, 0x7c, 0x62, 0x65, 0x13, 0x6b, 0x41, 0x08, 0x80, 0x44, 0x10, 0x46, 0xf8, 0x18, 0x0a, 0xd7, 0x92, 0x52, 0x40, 0x67, 0x12, 0x34, 0x20, 0x46, 0x05, 0x28, 0x09, 0x5a, 0x11, 0x73, 0x90, 0x20, 0x61, 0x72, 0x67, 0xf2, 0x7a, 0x20, 0x70, 0x30, 0x4e, 0x71, 0x51, 0x14, 0x68, 0x65, 0x6e, 0xd2, 0x1d, 0x36, 0x03, 0x60, 0x13, 0x69, 0x48, 0x6e, 0x76, 0x6f, 0xe0, 0x2c, 0x29, 0x2c, 0x91, 0x01, 0x6e, 0xfd, 0x33, 0x0e, 0x61, 0x2a, 0x18, 0x77, 0x0e, 0x13, 0x0d, 0x40, 0x40, 0x30, 0x62, 0xc1, 0x45, 0xc2, 0x3a, 0x71, 0x7e, 0x20, 0x61, 0x29, 0x20, 0xa3, 0x19, 0xa9, 0x6f, 0x7e, 0x2c, 0x16, 0x5b, 0x70, 0x05, 0x90, 0x5d, 0xb2, 0x13, 0xd0, 0x5d, 0x40, 0x1d, 0x67, 0x98, 0x6f, 0x6f, 0x64, 0x60, 0x0b, 0x11, 0x4c, 0x65, 0x66, 0xa0, 0x3b, 0xee, 0x74, 0x20, 0x0f, 0xf1, 0x91, 0x30, 0x86, 0x75, 0x70, 0x8d, 0xe1, 0x0d, 0x42, 0x14, 0x39, 0x81, 0x26, 0x65, 0x76, 0xf0, 0x86, 0x80, 0x1e, 0xfa, 0x66, 0x64, 0x6f, 0xff, 0x40, 0x62, 0x01, 0x39, 0x62, 0x7d, 0x72, 0x5a, 0xf1, 0x03, 0x9d, 0x14, 0x12, 0x0d, 0xf7, 0x11, 0xa2, 0x73, 0x50, 0x31, 0x6c, 0x20, 0x6f, 0xb0, 0x7e, 0x61, 0xb0, 0x85, 0x17, 0xb2, 0x1a, 0x31, 0x91, 0x00, 0x08, 0x6d, 0xb0, 0x8e, 0x20, 0x20, 0x77, 0x4b, 0x00, 0x68, 0xe0, 0x06, 0x72, 0xd0, 0x12, 0x72, 0x74, 0x91, 0x1d, 0x69, 0x1a, 0x74, 0x40, 0x93, 0x75, 0xc0, 0x88, 0xa0, 0x64, 0x72, 0x65, 0x6d, 0x1c, 0x61, 0x69, 0x30, 0x4b, 0x91, 0x4b, 0x30, 0x22, 0x66, 0x75, 0x6c, 0x36, 0x2c, 0x60, 0x6f, 0xe2, 0x0f, 0x62, 0xe7, 0x0f, 0x44, 0x88, 0x50, 0x4c, 0xf4, 0x2c, 0x20, 0x72, 0x56, 0x6e, 0xa1, 0x97, 0xe4, 0x26, 0xef, 0x86, 0x60, 0x30, 0x27, 0x91, 0x67, 0xa1, 0x0b, 0x99, 0x13, 0x20, 0x61, 0xa3, 0x75, 0x62, 0x6c, 0x1d, 0xc0, 0x8f, 0x6f, 0xd3, 0x13, 0xe1, 0x9a, 0x52, 0x28, 0x33, 0x2e, 0x20, 0xee, 0x4f, 0x83, 0x42, 0x31, 0x45, 0x71, 0x9f, 0x6f, 0xd3, 0x92, 0x82, 0x2b, 0x80, 0x0d, 0x1c, 0x72, 0x69, 0x90, 0x58, 0x62, 0x3c, 0x44, 0x29, 0x20, 0x48, 0x65, 0x81, 0x10, 0x5d, 0x72, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x93, 0x2c, 0xff, 0x41, 0x5b, 0xd9, 0x46, 0x11, 0x10, 0xf1, 0x0e, 0x6b, 0x26, 0x82, 0x38, 0xd8, 0x98, 0xf0, 0x00, 0x43, 0xb0, 0x78, 0xd5, 0x05, 0x0a, 0x61, 0x20, 0x68, 0x73, 0x05, 0x66, 0xf7, 0x70, 0x05, 0x43, 0x0a, 0xc0, 0x24, 0x70, 0xf0, 0x67, 0xa1, 0x04, 0xa1, 0x1b, 0xf4, 0x07, 0x33, 0x90, 0x69, 0x6c, 0x3d, 0x73, 0x75, 0xc0, 0x7a, 0x03, 0x08, 0x0a, 0x63, 0x1f, 0x90, 0x51, 0xd5, 0x23, 0x82, 0x9e, 0xd0, 0x12, 0xc2, 0x33, 0x63, 0x68, 0x6f, 0x3f, 0x10, 0xa1, 0x5c, 0x24, 0x60, 0x21, 0x21, 0xa9, 0xf0, 0x69, 0x57, 0xa2, 0x64, 0x0a, 0xce, 0x6d, 0x65, 0x0f, 0x00, 0x08, 0x51, 0x21, 0x6c, 0x69, 0x70, 0xae, 0xe0, 0x2e, 0x55, 0x60, 0xae, 0x6e, 0xf0, 0x2f, 0x72, 0x60, 0x8a, 0x6c, 0x41, 0x1d, 0x61, 0x3c, 0x6d, 0x65, 0x10, 0x0c, 0x90, 0x38, 0x62, 0x36, 0x60, 0xaf, 0x75, 0x63, 0xe2, 0x74, 0x00, 0x27, 0x0a, 0x6c, 0x61, 0x10, 0x07, 0xb0, 0x1e, 0xa1, 0x53, 0xc8, 0x61, 0x63, 0x63, 0x20, 0x99, 0x6f, 0x72, 0x50, 0x02, 0x01, 0x58, 0x45, 0x60, 0x6d, 0x6c, 0x80, 0x0f, 0x63, 0x72, 0x6f, 0x00, 0x01, 0x69, 0xba, 0x6e, 0xc0, 0x78, 0x65, 0x06, 0x3b, 0x43, 0xa9, 0x60, 0x50, 0x70, 0x50, 0x64, 0x19, 0xc0, 0xaa, 0x28, 0x74, 0xd0, 0x35, 0x40, 0x03, 0x66, 0x65, 0x77, 0x0b, 0x60, 0x4a, 0xa1, 0x02, 0x73, 0xa1, 0x40, 0x6c, 0x65, 0x6e, 0x67, 0x9c, 0x74, 0x68, 0xe0, 0x35, 0x40, 0x06, 0x10, 0xb4, 0x20, 0x62, 0x60, 0x3a, 0x39, 0x25, 0x12, 0x66, 0x6f, 0x01, 0xb3, 0xa0, 0x1b, 0x86, 0x34, 0x47, 0x69, 0x8a, 0x76, 0xb2, 0x8e, 0x6d, 0xa0, 0x94, 0x6e, 0x74, 0x20, 0xe0, 0x0c, 0xf3, 0x50, 0x10, 0xc3, 0x24, 0x65, 0x61, 0x60, 0x13, 0x72, 0xbb, 0x14, 0x25, 0x39, 0x1c, 0xff, 0x32, 0x41, 0x50, 0x17, 0xc1, 0x24, 0x85, 0x1f, 0xe0, 0x10, 0xa2, 0xa9, 0xa1, 0x6e, 0xb0, 0xb9, 0x7f, 0xc0, 0xbe, 0x55, 0x02, 0x55, 0x83, 0x12, 0x54, 0x61, 0x2e, 0x70, 0x02, 0xd0, 0x42, 0x65, 0xbf, 0xd1, 0x03, 0x25, 0x57, 0x02, 0x8c, 0x20, 0x04, 0xf4, 0x9f, 0xd2, 0x27, 0x20, 0xb0, 0x2e, 0xf4, 0x41, 0x63, 0xf0, 0x89, 0x70, 0x61, 0x9b, 0x41, 0x1e, 0x39, 0x08, 0x22, 0x2f, 0xff, 0xe1, 0xa4, 0x07, 0x43, 0xc4, 0x5d, 0x72, 0x06, 0x32, 0x2e, 0xa4, 0xc4, 0x81, 0x06, 0xd5, 0xc4, 0xfd, 0x92, 0x05, 0x34, 0x01, 0x58, 0xb8, 0x91, 0x93, 0x2a, 0xfe, 0x60, 0xeb, 0x8a, 0x54, 0x47, 0xc7, 0x7f, 0x23, 0x80, 0x33, 0xc0, 0x3c, 0x2c, 0x0a, 0x74, 0x00, 0x47, 0x10, 0x4f, 0x28, 0x6f, 0x67, 0x65, 0xb0, 0x0a, 0x72, 0x10, 0x84, 0x66, 0x66, 0xe1, 0xd1, 0x63, 0x76, 0x65, 0x6c, 0x79, 0xa1, 0x18, 0xc1, 0x22, 0x10, 0x8b, 0x6f, 0xf0, 0xcf, 0x80, 0x77, 0xd9, 0x5a, 0xf4, 0x19, 0x0a, 0x3d, 0x85, 0x95, 0x15, 0x63, 0xf8, 0x6f, 0x6e, 0x74, 0xe0, 0x40, 0x30, 0x26, 0xb0, 0x15, 0x61, 0x10, 0x7b, 0x09, 0xc5, 0x81, 0x24, 0x72, 0xa1, 0x44, 0x73, 0x65, 0x0a, 0xd0, 0x1f, 0xa0, 0x1c, 0x1c, 0x65, 0x72, 0xf1, 0x39, 0x80, 0x36, 0x50, 0xb1, 0x62, 0x75, 0x67, 0x7e, 0x67, 0xd1, 0x00, 0x62, 0x30, 0x59, 0x07, 0x21, 0x26, 0x43, 0x66, 0xb2, 0x97, 0x64, 0xe4, 0x6f, 0x20, 0x22, 0x1f, 0x6f, 0x66, 0x10, 0x5f, 0x60, 0x27, 0xbf, 0x22, 0xff, 0xbf, 0x22, 0x80, 0xb2, 0x52, 0x18, 0xbe, 0x22, 0x0b, 0x0a, 0x71, 0x20, 0x21, 0x18, 0xa1, 0x0b, 0x7f, 0xdf, 0x22, 0x01, 0xdd, 0x21, 0x0c, 0xdf, 0x22, 0x20, 0x24, 0xdf, 0x22, 0x80, 0xcf, 0x64, 0xfb, 0xe3, 0xae, 0xdf, 0x22, 0x20, 0xdb, 0x22, 0x5b, 0x08, 0xff, 0x22, 0xf2, 0xe1, 0x30, 0x79, 0xc7, 0xff, 0x22, 0xb0, 0xf3, 0xfa, 0x22, 0x20, 0x63, 0x29, 0x00, 0xf0, 0x7f, 0xc7, 0x91, 0x32, 0x0b, 0x64, 0x69, 0x73, 0x30, 0x39, 0x79, 0x73, 0x70, 0x84, 0x37, 0x35, 0xf4, 0x83, 0x34, 0x40, 0xc9, 0x75, 0x91, 0x18, 0xb1, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x63, 0x80, 0x92, 0x6f, 0x30, 0xdb, 0x63, 0x94, 0x41, 0x23, 0x65, 0x07, 0x2e, 0x03, 0x86, 0x97, 0x75, 0x12, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x03, 0xc4, 0x13, 0x80, 0x61, 0x6e, 0x73, 0xb7, 0x00, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x73, 0x2c, 0x20, 0x80, 0x61, 0x73, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x01, 0x70, 0x00, 0x61, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x00, 0x6e, 0x63, 0x65, 0x20, 0x64, 0x69, 0x72, 0x65, 0x00, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x00, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x02, 0x6f, 0x01, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x80, 0x70, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x02, 0x38, 0x00, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x08, 0x61, 0x6e, 0x64, 0x00, 0x1e, 0x69, 0x73, 0x20, 0x6c, 0x09, 0x00, 0xb2, 0x6e, 0x73, 0x00, 0x86, 0x6f, 0x63, 0x75, 0x6d, 0x20, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x01, 0x68, 0x64, 0x29, 0x80, 0x20, 0x44, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x05, 0x6e, 0x40, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x00, 0x62, 0x3a, 0x03, 0x02, 0x1f, 0x00, 0x57, 0x20, 0x30, 0x29, 0x20, 0x43, 0x6f, 0x10, 0x6e, 0x76, 0x65, 0x79, 0x02, 0x58, 0x4d, 0x69, 0x6e, 0x10, 0x69, 0x6d, 0x61, 0x6c, 0x00, 0x12, 0x72, 0x72, 0x65, 0x20, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x01, 0x8f, 0x53, 0x6f, 0xc4, 0x75, 0x72, 0x00, 0xa0, 0x75, 0x6e, 0x64, 0x01, 0x93, 0x00, 0x9c, 0x90, 0x74, 0x65, 0x72, 0x6d, 0x04, 0x8c, 0x69, 0x73, 0x01, 0x69, 0x5d, 0x01, 0x49, 0x4c, 0x03, 0x83, 0x00, 0xdf, 0x02, 0x95, 0x65, 0x0c, 0x44, 0x41, 0x04, 0x70, 0x70, 0x80, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x01, 0x80, 0x0c, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x05, 0x20, 0x73, 0x75, 0xc0, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x01, 0x0a, 0x83, 0x22, 0x03, 0x84, 0x38, 0x82, 0x36, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0xf1, 0x00, 0x05, 0x69, 0x74, 0x2c, 0x82, 0x55, 0x84, 0x90, 0x85, 0x1e, 0x00, 0x9e, 0x50, 0x6f, 0x6d, 0x62, 0x69, 0x01, 0x76, 0x72, 0x80, 0xaa, 0x6c, 0x18, 0x69, 0x6e, 0x6b, 0x02, 0x13, 0x89, 0x3b, 0x77, 0x69, 0x74, 0x02, 0x68, 0x00, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x80, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x81, 0x47, 0x6c, 0x6f, 0x66, 0x85, 0x22, 0x01, 0xbd, 0x4c, 0x00, 0x1d, 0x00, 0x0e, 0x56, 0x83, 0x04, 0x0e, 0x00, 0xc2, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x80, 0x80, 0x14, 0x61, 0x20, 0x06, 0x1d, 0x43, 0x03, 0x36, 0x64, 0x20, 0x57, 0x70, 0x6f, 0x72, 0x6b, 0x2c, 0x01, 0x66, 0x00, 0x1d, 0x85, 0x22, 0x6d, 0x08, 0x61, 0x6e, 0x6e, 0x00, 0x95, 0x73, 0x70, 0x65, 0x63, 0x61, 0x03, 0x34, 0x62, 0x79, 0x20, 0x73, 0x01, 0xee, 0xc0, 0x3e, 0x36, 0x3f, 0x0d, 0x71, 0x80, 0x40, 0x80, 0x77, 0x81, 0x60, 0xc0, 0x5a, 0x45, 0x10, 0x43, 0x6f, 0x87, 0x0f, 0x60, 0x03, 0x75, 0x81, 0x5a, 0x31, 0x29, 0x20, 0x55, 0x40, 0x7b, 0x84, 0x61, 0x20, 0x86, 0x4c, 0x73, 0x68, 0x61, 0x72, 0xc0, 0x2c, 0x00, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x00, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0xe6, 0x6d, 0xc1, 0x52, 0x40, 0x87, 0x6e, 0x6b, 0xc1, 0x71, 0x82, 0x3f, 0x88, 0x29, 0xc2, 0x4c, 0x43, 0x0b, 0x2e, 0x20, 0x20, 0x41, 0x47, 0x12, 0x87, 0x0e, 0x47, 0xc0, 0x95, 0xc1, 0x8e, 0x02, 0x5e, 0x28, 0x61, 0x29, 0x81, 0xa4, 0x73, 0x02, 0x20, 0x00, 0x61, 0x72, 0x75, 0x6e, 0x20, 0x74, 0x69, 0xd4, 0x6d, 0x65, 0xc5, 0x2a, 0x61, 0x41, 0xa7, 0x79, 0x85, 0x35, 0x04, 0x15, 0x00, 0x20, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x3c, 0x20, 0x70, 0x00, 0x92, 0x40, 0xa4, 0x80, 0xa1, 0x46, 0x6d, 0x27, 0x73, 0x31, 0x40, 0x0c, 0x6d, 0x70, 0x75, 0x80, 0x91, 0xc5, 0x10, 0x73, 0x79, 0x10, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x7d, 0x28, 0x62, 0x29, 0x28, 0x20, 0x77, 0x69, 0x00, 0xc8, 0x6f, 0x80, 0x7b, 0x61, 0x74, 0xe6, 0x65, 0x80, 0x10, 0x41, 0x02, 0x6c, 0x79, 0x40, 0x05, 0xd2, 0x6f, 0x05, 0x11, 0x4f, 0x44, 0xc7, 0x45, 0x20, 0x02, 0x2e, 0x00, 0x31, 0x69, 0x6e, 0x00, 0x1a, 0x66, 0x00, 0x61, 0x63, 0x65, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0xf7, 0x40, 0xa0, 0xc1, 0x98, 0xc5, 0x42, 0x20, 0x43, 0x7b, 0x85, 0x10, 0x04, 0x7d, 0x83, 0x5a, 0x00, 0x65, 0x29, 0x20, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x01, 0x00, 0xab, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x19, 0x83, 0xaf, 0x49, 0x6e, 0x81, 0xad, 0xc2, 0x02, 0x2c, 0x20, 0x62, 0x0c, 0x75, 0x74, 0xc0, 0x36, 0x00, 0x27, 0x69, 0x66, 0x20, 0x79, 0x00, 0x6f, 0x75, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x84, 0x20, 0x6f, 0x80, 0x59, 0x72, 0x77, 0x69, 0x73, 0x02, 0x49, 0x80, 0x62, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0xc0, 0xf7, 0x0d, 0xc0, 0x75, 0x6f, 0xc1, 0x19, 0x62, 0x0a, 0x73, 0x75, 0x63, 0x68, 0xfb, 0x00, 0x47, 0x66, 0x09, 0x20, 0xc3, 0x5d, 0x0d, 0x45, 0x41, 0x13, 0x04, 0x7e, 0xe3, 0x23, 0x0c, 0x6f, 0x6e, 0xa0, 0x0d, 0x43, 0x83, 0x20, 0x65, 0x78, 0x74, 0x4f, 0x81, 0x2b, 0x42, 0x1d, 0xee, 0x09, 0x63, 0x73, 0x6e, 0x65, 0xa0, 0x8e, 0x73, 0x1b, 0xa1, 0x42, 0x60, 0x06, 0x69, 0xe3, 0x18, 0x22, 0x87, 0x65, 0x78, 0x65, 0xfe, 0x63, 0x60, 0x30, 0x13, 0x62, 0x81, 0x35, 0x21, 0x0f, 0xea, 0x5c, 0x41, 0x17, 0x01, 0x61, 0xe4, 0x64, 0x20, 0x00, 0x5a, 0x72, 0x65, 0xc0, 0x29, 0x00, 0x6e, 0x21, 0x4b, 0x5e, 0x6f, 0x45, 0x6e, 0x81, 0x01, 0x24, 0x4c, 0x1f, 0x6f, 0x6e, 0x67, 0x46, 0x6e, 0xc2, 0x6b, 0x27, 0x6e, 0x2e, 0x20, 0x28, 0x49, 0x02, 0x72, 0xc1, 0x29, 0x11, 0xa0, 0x7c, 0x20, 0x6f, 0x70, 0xa2, 0x86, 0x34, 0x64, 0x30, 0x03, 0x23, 0x7f, 0x95, 0x31, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x64, 0x61, 0x63, 0xc2, 0x3c, 0x6e, 0x79, 0xc1, 0x17, 0x60, 0x11, 0x20, 0x1f, 0x9a, 0x9a, 0x41, 0xa8, 0x8b, 0x6d, 0xe8, 0x16, 0x03, 0x20, 0x64, 0x65, 0x2e, 0xcc, 0x20, 0x49, 0x83, 0x3b, 0xaa, 0x11, 0x31, 0x2c, 0x02, 0x3e, 0x82, 0x0e, 0x7f, 0x20, 0x84, 0x62, 0x3a, 0xe1, 0x0d, 0xc9, 0x13, 0x21, 0x08, 0xc8, 0x45, 0xe4, 0x84, 0x20, 0xff, 0x1f, 0x84, 0xa0, 0xac, 0x84, 0x3e, 0x41, 0x08, 0x60, 0x44, 0x40, 0x66, 0x64, 0x84, 0x0c, 0xab, 0xc9, 0xa3, 0xb3, 0x2e, 0x29, 0x41, 0xba, 0x35, 0x2e, 0x80, 0x03, 0xa2, 0xa0, 0x5e, 0x64, 0x00, 0x5b, 0x61, 0x81, 0xa0, 0xc6, 0x82, 0x59, 0x59, 0x40, 0x53, 0x6d, 0x7a, 0x61, 0xc0, 0x71, 0x6c, 0x00, 0x61, 0x20, 0x82, 0xe3, 0x84, 0xa0, 0x62, 0x69, 0x78, 0x6c, 0x69, 0x74, 0x41, 0xcb, 0x42, 0x48, 0x80, 0x88, 0xc0, 0x41, 0x77, 0xe1, 0x40, 0x9a, 0x20, 0x62, 0x61, 0x73, 0x40, 0x32, 0x00, 0x96, 0x40, 0x1a, 0x7a, 0x0a, 0x45, 0x6a, 0x73, 0x61, 0x61, 0x81, 0x99, 0xe1, 0x00, 0x02, 0xb8, 0x73, 0x87, 0x20, 0x3e, 0x40, 0xb6, 0x05, 0x8f, 0x74, 0x6f, 0x67, 0x65, 0x00, 0x06, 0x2e, 0x72, 0x43, 0x75, 0xa2, 0x60, 0x85, 0x0d, 0x0a, 0x91, 0x0d, 0x6e, 0x6f, 0x7c, 0x74, 0x20, 0x08, 0x2e, 0xe0, 0x8b, 0x80, 0xc7, 0xa1, 0x10, 0x01, 0x03, 0x63, 0xce, 0x6f, 0x00, 0xb4, 0x80, 0x10, 0x00, 0x0e, 0x74, 0x68, 0x80, 0x59, 0x2a, 0xcc, 0xfe, 0x63, 0xa3, 0xd6, 0x82, 0x5e, 0x21, 0x90, 0xa4, 0x1e, 0x05, 0x11, 0x49, 0xc7, 0xe0, 0x82, 0xc1, 0x40, 0x49, 0x72, 0x0a, 0x63, 0x68, 0x6f, 0x60, 0xd4, 0x80, 0xb5, 0xe1, 0x83, 0x39, 0x64, 0x6f, 0x20, 0x62, 0x20, 0x14, 0x85, 0x50, 0x8c, 0xe3, 0xfd, 0x00, 0x9e, 0x41, 0x25, 0x49, 0x22, 0x97, 0xa3, 0x5d, 0xc0, 0x11, 0x45, 0x0c, 0x42, 0x88, 0x21, 0x8b, 0x9f, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x80, 0x72, 0x6b, 0xcf, 0xc3, 0x27, 0x41, 0x37, 0x23, 0x28, 0xa4, 0x31, 0x79, 0x2c, 0x40, 0x3e, 0x86, 0x04, 0xbd, 0x03, 0x04, 0x6e, 0xa0, 0x53, 0x22, 0x13, 0x75, 0x05, 0x77, 0x12, 0x2c, 0x01, 0x04, 0x9f, 0x83, 0x0e, 0x70, 0x07, 0x24, 0x0d, 0xfd, 0x77, 0xa0, 0x05, 0x63, 0x65, 0xc0, 0x7f, 0xa3, 0x33, 0x4b, 0xb0, 0x53, 0x47, 0x69, 0x76, 0x32, 0x53, 0x6d, 0xc0, 0x70, 0xf8, 0x6e, 0x74, 0x20, 0x90, 0x14, 0x50, 0x0f, 0x03, 0x19, 0x70, 0x06, 0xa1, 0x57, 0x8d, 0x61, 0x72, 0x64, 0x46, 0x20, 0x92, 0x1f, 0x70, 0x61, 0x72, 0x70, 0x4c, 0xb0, 0x66, 0x20, 0x69, 0x74, 0x31, 0x07, 0x50, 0x53, 0x61, 0x78, 0x0c, 0x07, 0xc5, 0x5b, 0x64, 0x20, 0x63, 0x48, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x33, 0xf0, 0x82, 0x00, 0x8b, 0x77, 0x68, 0x30, 0x8c, 0xd1, 0x8a, 0x66, 0x69, 0x9f, 0xe0, 0x1b, 0x40, 0x06, 0x31, 0x04, 0x76, 0x38, 0x31, 0x41, 0x75, 0x6e, 0x56, 0x0f, 0x0f, 0xf1, 0x4e, 0x35, 0x17, 0xf6, 0x12, 0xc2, 0x0b, 0x36, 0x2e, 0x20, 0x52, 0x64, 0x65, 0x76, 0x40, 0x53, 0x64, 0x20, 0x74, 0x58, 0x1a, 0x8f, 0x4c, 0x64, 0x65, 0x73, 0x41, 0x91, 0x47, 0x65, 0xb0, 0x75, 0x30, 0x8a, 0x50, 0x2c, 0x75, 0x62, 0x00, 0x85, 0xda, 0x0f, 0x54, 0xb0, 0x11, 0x46, 0x72, 0x00, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x79, 0x61, 0x24, 0x46, 0x6f, 0x50, 0x13, 0x53, 0x5b, 0xd2, 0x2f, 0x31, 0x03, 0x73, 0x2e, 0x68, 0xe0, 0x58, 0x63, 0x06, 0xd0, 0x3f, 0x2f, 0xb0, 0x4b, 0x6e, 0x65, 0xf2, 0x77, 0xb5, 0x80, 0x73, 0x0a, 0x54, 0x64, 0xd1, 0x37, 0x1f, 0x07, 0x18, 0x07, 0xe0, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x82, 0x70, 0x72, 0x9a, 0x00, 0x71, 0xd8, 0x2e, 0x20, 0x53, 0x21, 0x5d, 0xd0, 0x04, 0x0a, 0x94, 0x85, 0x90, 0x9e, 0x03, 0x81, 0x6c, 0x00, 0x60, 0x73, 0x69, 0x6d, 0x69, 0x6c, 0x61, 0x02, 0x72, 0x01, 0x40, 0x73, 0x70, 0x69, 0x72, 0x69, 0x74, 0xbf, 0x42, 0x03, 0xf0, 0x0a, 0xf5, 0x71, 0x14, 0x03, 0x03, 0x65, 0xb0, 0x0a, 0x0a, 0x30, 0x8a, 0x03, 0xa0, 0xa1, 0x01, 0x03, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x91, 0x01, 0x03, 0x61, 0x64, 0x64, 0xe0, 0x74, 0x73, 0x20, 0x01, 0x0b, 0x17, 0x20, 0x47, 0x80, 0x6c, 0x71, 0x98, 0x72, 0xb1, 0x41, 0x63, 0x65, 0x72, 0x64, 0x6e, 0x73, 0x62, 0x14, 0x45, 0x61, 0x70, 0x65, 0xe4, 0x04, 0x20, 0x8d, 0x90, 0x1c, 0x67, 0xf0, 0x20, 0xb1, 0x96, 0x64, 0x69, 0x73, 0xe1, 0xa5, 0x30, 0x75, 0x69, 0x73, 0x68, 0x21, 0x19, 0x15, 0x02, 0x6e, 0x75, 0xf0, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x4e, 0x91, 0x1b, 0xa5, 0x3e, 0x50, 0xaa, 0x53, 0x40, 0x33, 0x90, 0x12, 0x63, 0x65, 0xf0, 0x03, 0x64, 0x80, 0x21, 0x20, 0x9d, 0xf5, 0x8c, 0x73, 0xf0, 0x30, 0x70, 0x80, 0xa0, 0x2f, 0x65, 0x72, 0x90, 0x09, 0xbc, 0x6e, 0x20, 0x23, 0x04, 0x20, 0x2a, 0x34, 0x05, 0x3f, 0x14, 0x20, 0x5f, 0x1b, 0xe9, 0x31, 0x2b, 0x20, 0x22, 0xd0, 0x17, 0x61, 0x10, 0x30, 0x90, 0x75, 0x00, 0x93, 0xf1, 0xe4, 0x03, 0x22, 0x0a, 0x61, 0xc1, 0xa2, 0xf0, 0xae, 0x11, 0x6b, 0xe0, 0x9e, 0xf9, 0x81, 0x08, 0x68, 0x61, 0x50, 0x2d, 0x00, 0x0a, 0xd5, 0x60, 0x60, 0x1a, 0x16, 0x3b, 0xaf, 0xf2, 0x39, 0x40, 0x7e, 0xc0, 0x10, 0x10, 0x1d, 0x0a, 0x10, 0x33, 0x64, 0x40, 0x4d, 0x40, 0x6f, 0x6e, 0x73, 0x20, 0x65, 0x69, 0x20, 0x03, 0x72, 0xdb, 0xe3, 0x26, 0x20, 0x0b, 0x70, 0xf3, 0x1f, 0x97, 0x0a, 0x20, 0xf0, 0x07, 0x90, 0x04, 0x4d, 0x2e, 0x08, 0x0a, 0x97, 0x02, 0xd2, 0x47, 0x65, 0x20, 0x7f, 0x25, 0x64, 0xdf, 0x72, 0x25, 0x85, 0x13, 0x80, 0x28, 0x33, 0x55, 0x83, 0x13, 0x0a, 0xe0, 0x71, 0x86, 0x13, 0xdc, 0x64, 0x6f, 0xb0, 0x0c, 0x11, 0x4d, 0x13, 0x14, 0x79, 0x30, 0x56, 0xa4, 0x0e, 0xf7, 0xa4, 0x13, 0xf5, 0x30, 0x47, 0x27, 0x0a, 0x0f, 0x13, 0x01, 0x13, 0x24, 0x67, 0x80, 0x5c, 0xfd, 0xc0, 0x4c, 0x6f, 0x31, 0xa0, 0xc0, 0x13, 0xb5, 0x04, 0x80, 0x0c, 0x01, 0x12, 0x4f, 0x04, 0xd2, 0x20, 0xbb, 0x32, 0x20, 0x65, 0x10, 0x03, 0x20, 0x1f, 0x0e, 0x9f, 0x33, 0xff, 0x13, 0x0e, 0x91, 0x65, 0x00, 0x70, 0xb1, 0x05, 0xdf, 0x21, 0xdf, 0x21, 0xd5, 0x21, 0x00, 0x2a, 0x00, 0x78, 0x79, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x64, 0x31, 0x70, 0xb0, 0x64, 0x65, 0x0a, 0x60, 0x42, 0x30, 0x04, 0x72, 0x20, 0xc0, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x16, 0x37, 0xcf, 0x0f, 0xcb, 0xdf, 0x22, 0x12, 0x4e, 0x20, 0x50, 0xae, 0x6c, 0x6c, 0xc2, 0x21, 0x80, 0x54, 0x61, 0x63, 0x4b, 0x72, 0x6f, 0x78, 0x79, 0xf0, 0xa4, 0xc2, 0x0c, 0x63, 0x2e, 0x20, 0x40, 0x9a, 0x60, 0xa4, 0xe2, 0xa6, 0x66, 0x81, 0x80, 0x65, 0x70, 0x7c, 0x74, 0x61, 0xb1, 0xd5, 0x24, 0x1e, 0x85, 0x12, 0xb0, 0x64, 0x91, 0xc4, 0x61, 0x02, 0x6e, 0x91, 0x02, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0xfc, 0x69, 0x7a, 0xb2, 0x0e, 0xf2, 0xb2, 0xe1, 0x26, 0x90, 0x27, 0x14, 0x16, 0x72, 0x06, 0xdf, 0x95, 0x03, 0x81, 0x78, 0x30, 0x0c, 0x05, 0x71, 0xf0, 0x36, 0x00, 0x0f, 0x00, 0x1f, 0x01, 0xff, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0xff, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0xff, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x1a, 0x01, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x03, 0xb0, 0x02, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t fsntfs_test_compression_lzxpress_huffman_compressed_data1[ 4096 ] = { 0x00, 0x00, 0x00, 0x00, 0xa0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0xb0, 0x89, 0x00, 0xb7, 0x98, 0xa9, 0x9a, 0xba, 0xba, 0xb0, 0x0a, 0x0b, 0x0b, 0x80, 0x8b, 0x8a, 0x89, 0x9b, 0x0b, 0x97, 0xba, 0x09, 0x8a, 0xa9, 0xaa, 0xa0, 0x00, 0x00, 0x00, 0x50, 0x57, 0x46, 0x76, 0x56, 0x8a, 0x66, 0x55, 0xb6, 0x55, 0x65, 0x77, 0x69, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x0a, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0xb9, 0xa9, 0xaa, 0x0b, 0x00, 0x00, 0xbb, 0x77, 0x89, 0x88, 0xa9, 0x9a, 0xbb, 0x0b, 0x90, 0x76, 0x87, 0xa9, 0xaa, 0xaa, 0x9a, 0xa0, 0x9a, 0x76, 0x77, 0x98, 0x9a, 0xa9, 0xb9, 0xbb, 0x9a, 0x75, 0x78, 0xa8, 0xa9, 0xa9, 0xba, 0xab, 0x80, 0x66, 0x77, 0x98, 0x09, 0x0a, 0xba, 0x00, 0xa0, 0x76, 0x78, 0x98, 0xa9, 0x0a, 0xa0, 0xab, 0xa0, 0x80, 0x9a, 0xba, 0xbb, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0xef, 0x00, 0xc0, 0xf0, 0xce, 0x50, 0xfc, 0x9b, 0xa3, 0x9f, 0x9f, 0xe2, 0x9b, 0x76, 0x06, 0x87, 0x6f, 0xe2, 0x9b, 0xd1, 0x65, 0x2f, 0x0e, 0xf8, 0x8b, 0xf0, 0xe8, 0x03, 0xf3, 0x99, 0xf5, 0x1e, 0xbe, 0x6b, 0x7e, 0x8b, 0x55, 0xbe, 0xfa, 0xa5, 0x30, 0x02, 0x41, 0x46, 0x83, 0xc3, 0x3b, 0x40, 0xc0, 0xef, 0x96, 0x1f, 0x88, 0x13, 0xdc, 0x77, 0x07, 0x0e, 0x69, 0xdf, 0xcc, 0xa0, 0x11, 0x44, 0xd4, 0x24, 0x58, 0xdd, 0xb3, 0x6f, 0x7c, 0x32, 0x0e, 0xd5, 0x44, 0x12, 0x3d, 0x43, 0x2e, 0x0e, 0x12, 0xa9, 0xc2, 0x21, 0x27, 0x44, 0x8b, 0x6c, 0xea, 0xad, 0xc3, 0x01, 0x72, 0x39, 0xf0, 0x83, 0xb5, 0xba, 0xe0, 0xc1, 0xf7, 0xef, 0x29, 0xee, 0xa4, 0xcc, 0x9e, 0x26, 0xf1, 0xff, 0x19, 0x34, 0x05, 0xb5, 0x22, 0x31, 0xa6, 0xba, 0x40, 0x50, 0x7c, 0x29, 0x58, 0xcb, 0x0b, 0xb6, 0x16, 0x40, 0xc0, 0xbb, 0xb6, 0x43, 0x99, 0x0d, 0x49, 0x4b, 0x42, 0xa9, 0x0a, 0xb1, 0xa5, 0xcc, 0x07, 0x5d, 0x1a, 0xf9, 0x53, 0x61, 0x87, 0x40, 0x6e, 0x01, 0xd3, 0xd6, 0x28, 0xc6, 0x42, 0x9d, 0xa0, 0x0d, 0xbe, 0xb0, 0x5d, 0x27, 0xad, 0x00, 0x2b, 0x00, 0x3d, 0xa4, 0x1e, 0x33, 0x19, 0x98, 0x58, 0x61, 0x42, 0xa7, 0x8f, 0xc0, 0x8a, 0x3c, 0xde, 0xa2, 0x51, 0x53, 0x0e, 0xc0, 0x96, 0x36, 0xa8, 0xeb, 0x47, 0xa3, 0x96, 0x83, 0xdd, 0x58, 0x15, 0x28, 0x52, 0x28, 0xc2, 0x19, 0x49, 0x71, 0x0e, 0x1e, 0x34, 0x2c, 0x31, 0x9e, 0x89, 0x42, 0xcb, 0x8b, 0xc7, 0x90, 0x13, 0x2a, 0x12, 0x02, 0xc6, 0x45, 0x6e, 0x09, 0x2e, 0x88, 0xea, 0x36, 0xac, 0xb4, 0x3b, 0xa8, 0x5d, 0x66, 0x94, 0x73, 0xcf, 0x15, 0x3a, 0xa8, 0x5e, 0xe7, 0xd2, 0x5d, 0xb8, 0x4d, 0xe1, 0x4c, 0xfa, 0x38, 0xb5, 0x2a, 0xad, 0xa8, 0x54, 0x00, 0x40, 0x30, 0xd9, 0xf0, 0x1f, 0x79, 0x51, 0xfa, 0x5c, 0x47, 0x8d, 0x40, 0x9d, 0xe9, 0x4b, 0x18, 0x6a, 0x83, 0xa5, 0xb2, 0xf4, 0x40, 0x3a, 0x82, 0x18, 0x45, 0xc7, 0xe5, 0x03, 0x24, 0x94, 0x81, 0x7e, 0x19, 0xfc, 0x82, 0x70, 0x21, 0x32, 0xc7, 0x86, 0xec, 0x7b, 0xf3, 0x41, 0x2d, 0xab, 0x0a, 0xd1, 0x41, 0x98, 0x48, 0x03, 0xf4, 0xe1, 0x22, 0xa7, 0x96, 0x00, 0x39, 0x70, 0x91, 0xa0, 0x52, 0xcb, 0x91, 0xc2, 0xa2, 0xc0, 0x8d, 0x03, 0xba, 0xc6, 0xfa, 0x0d, 0x94, 0x41, 0x76, 0x2d, 0x6f, 0xb3, 0xd5, 0x22, 0x2d, 0xce, 0x72, 0x1e, 0xe2, 0x1c, 0x0e, 0x29, 0x6d, 0x05, 0xe3, 0xc8, 0x9b, 0x48, 0xd4, 0x44, 0x44, 0x92, 0xcd, 0xc5, 0x92, 0x20, 0xc6, 0x77, 0x38, 0x72, 0x50, 0x75, 0x00, 0x9d, 0x8f, 0xa6, 0x9f, 0x2a, 0x4d, 0xa4, 0xc5, 0x26, 0x16, 0x13, 0xcd, 0xdc, 0x90, 0x06, 0xf2, 0xb8, 0x74, 0x48, 0xc6, 0x43, 0x32, 0x60, 0x51, 0xe4, 0x49, 0x31, 0x24, 0x6c, 0x90, 0x10, 0x16, 0x23, 0xd2, 0x0f, 0x96, 0x36, 0x7b, 0x7c, 0x91, 0x03, 0xd8, 0x40, 0x55, 0xc8, 0x4a, 0xd5, 0x38, 0xcb, 0x7e, 0x64, 0x64, 0xfc, 0x1b, 0x5e, 0xf1, 0x90, 0x5d, 0x05, 0x2d, 0x29, 0x2c, 0xd2, 0x26, 0x1f, 0xdc, 0x80, 0xb7, 0x51, 0x5e, 0xab, 0x1e, 0x93, 0xf7, 0x4f, 0x51, 0x08, 0x12, 0x08, 0x86, 0x8a, 0x5b, 0x6c, 0x95, 0x6a, 0xea, 0xdb, 0xd2, 0x3a, 0xa2, 0xaf, 0xba, 0xea, 0xbb, 0x62, 0x21, 0xef, 0x28, 0x6d, 0x66, 0xaa, 0x29, 0x2c, 0xdc, 0x12, 0x0f, 0xd3, 0xba, 0xd1, 0x56, 0x91, 0xbc, 0xd7, 0xae, 0xa6, 0x31, 0xe1, 0x46, 0x70, 0xe9, 0x05, 0xe2, 0x15, 0x60, 0x2b, 0x20, 0xa1, 0x98, 0x47, 0xf4, 0xdb, 0xff, 0xdb, 0x2c, 0x2a, 0xd8, 0x3a, 0x84, 0xb0, 0x7a, 0xdc, 0x43, 0xdf, 0xd3, 0x62, 0x70, 0x10, 0xd6, 0xa8, 0x38, 0x07, 0x53, 0x74, 0x41, 0x87, 0x00, 0xf1, 0x3d, 0x64, 0x58, 0x23, 0x66, 0x4b, 0xa8, 0x03, 0x74, 0xf4, 0x5b, 0xdb, 0x77, 0xb7, 0x84, 0xcb, 0x5d, 0x2d, 0xc9, 0xe4, 0x86, 0x78, 0x59, 0xd0, 0xc7, 0x99, 0xd3, 0xa1, 0xae, 0x55, 0xd8, 0xdd, 0x32, 0x5e, 0x0f, 0x32, 0xb8, 0x21, 0xe1, 0x12, 0x31, 0x16, 0xb3, 0x88, 0x17, 0xa8, 0x90, 0xc7, 0xc3, 0xf5, 0x62, 0xe9, 0x46, 0x5c, 0x83, 0xdd, 0x9c, 0xd2, 0x30, 0xb0, 0xff, 0x2a, 0x44, 0x6e, 0xc9, 0x1b, 0xf9, 0x33, 0x10, 0x4f, 0x2e, 0x00, 0x29, 0x3c, 0x52, 0xc1, 0xf4, 0x07, 0x8b, 0x14, 0x79, 0x15, 0x63, 0x07, 0x24, 0xa6, 0x8d, 0x45, 0xc6, 0x7c, 0xaa, 0x44, 0x6e, 0x19, 0xf1, 0x7d, 0x11, 0x6c, 0x94, 0x25, 0xc4, 0xa8, 0x22, 0xcd, 0x10, 0x82, 0x34, 0xe8, 0xf9, 0x25, 0x85, 0x80, 0x1c, 0x68, 0x73, 0xf8, 0x3c, 0x01, 0xec, 0x90, 0xba, 0x8a, 0x7f, 0x2d, 0x72, 0x1a, 0xed, 0x67, 0x02, 0xa0, 0x1d, 0xc7, 0x03, 0xd0, 0x2b, 0x6b, 0xb6, 0x71, 0x8e, 0xb9, 0x02, 0x31, 0x70, 0x24, 0x7b, 0x89, 0x65, 0x44, 0x20, 0xd1, 0x7e, 0x7d, 0x5d, 0xaf, 0xb1, 0x69, 0xa1, 0x92, 0x6e, 0xdc, 0x52, 0x80, 0xb5, 0xd9, 0x66, 0x6e, 0xaa, 0x38, 0x4b, 0xa1, 0xf2, 0x2e, 0xe2, 0x4a, 0x42, 0x44, 0x00, 0x5f, 0x8b, 0xbb, 0x08, 0xd9, 0xa8, 0xd2, 0xa3, 0x13, 0xa5, 0xfd, 0x1b, 0x51, 0x72, 0x24, 0xf4, 0xd7, 0x15, 0xe9, 0x09, 0x74, 0x84, 0x7a, 0x26, 0x32, 0x41, 0xdf, 0x38, 0x29, 0x58, 0xbc, 0x14, 0x0f, 0x2a, 0x91, 0x50, 0xed, 0xf8, 0xbd, 0xc8, 0xdf, 0xeb, 0x6f, 0xf6, 0x63, 0x3d, 0xc5, 0xe8, 0x25, 0x17, 0x47, 0x12, 0xdc, 0x8b, 0x6c, 0x44, 0x23, 0x64, 0x8d, 0x33, 0x2b, 0x5c, 0xc6, 0xa6, 0x57, 0xd2, 0x94, 0xd4, 0x47, 0x11, 0x07, 0x36, 0x6e, 0xc9, 0x56, 0x37, 0xd2, 0x76, 0xcd, 0xfd, 0xd1, 0x40, 0xd6, 0x28, 0x71, 0x34, 0x7c, 0xe0, 0x5f, 0x5f, 0x36, 0xf4, 0xb1, 0x74, 0xdf, 0x9f, 0xad, 0x96, 0x12, 0xec, 0x2f, 0x25, 0xd5, 0x3b, 0x8b, 0x27, 0x2c, 0xd6, 0x55, 0xd7, 0xe0, 0x94, 0x7b, 0xbc, 0x19, 0x8c, 0x72, 0xda, 0x16, 0x41, 0x26, 0xe3, 0xf3, 0x79, 0xcb, 0xc1, 0x2f, 0xa7, 0xf3, 0x6d, 0xb6, 0x5b, 0xf2, 0x22, 0xe4, 0x40, 0x19, 0xa4, 0x38, 0x3d, 0x05, 0x89, 0x41, 0xa2, 0x96, 0x47, 0xcc, 0xea, 0x46, 0x13, 0xaa, 0x10, 0xa0, 0x4b, 0x9e, 0x56, 0xb0, 0x2a, 0x98, 0x0e, 0x0e, 0x7f, 0x04, 0xd3, 0xbf, 0xca, 0x20, 0xa6, 0xec, 0x55, 0xcd, 0xdd, 0x32, 0x2b, 0x44, 0x42, 0x0a, 0x0a, 0x66, 0x4d, 0xe9, 0x5e, 0x93, 0x72, 0xc7, 0x5a, 0xb1, 0x22, 0xfb, 0x6f, 0x1e, 0xf6, 0x3d, 0x94, 0x54, 0x34, 0x96, 0x9f, 0xd2, 0x0d, 0x11, 0xc3, 0x99, 0xf8, 0x74, 0x68, 0x95, 0x0d, 0xe7, 0x8a, 0xc0, 0xfe, 0xc9, 0xeb, 0x46, 0x82, 0x1b, 0x3f, 0x2d, 0x5c, 0x07, 0x2d, 0x22, 0x55, 0x81, 0x6d, 0xb9, 0x24, 0x25, 0xe5, 0x1f, 0x52, 0x90, 0x8b, 0x60, 0x71, 0x74, 0x08, 0xa7, 0xb3, 0x5b, 0xed, 0x29, 0xc4, 0x42, 0x21, 0x07, 0x6e, 0x39, 0xc9, 0x0e, 0xdc, 0xe2, 0x56, 0x98, 0x69, 0xc9, 0x1a, 0x0e, 0xc8, 0xca, 0x44, 0x59, 0x50, 0x99, 0xa7, 0x9e, 0x4b, 0xbb, 0x8b, 0x74, 0x75, 0x9a, 0xa1, 0xd8, 0x31, 0x07, 0xf2, 0x5d, 0x36, 0x3e, 0x53, 0x85, 0x84, 0x34, 0x38, 0x4d, 0x13, 0x5f, 0x20, 0xac, 0xa6, 0x22, 0xaa, 0x42, 0x27, 0xba, 0x7b, 0x0b, 0x7d, 0xde, 0xa6, 0x0c, 0x2a, 0x11, 0x8c, 0x21, 0x9a, 0xfc, 0x8a, 0x1c, 0xb6, 0x3e, 0x75, 0x42, 0xfd, 0x60, 0x1a, 0x5d, 0xa5, 0xd4, 0x6a, 0x01, 0x54, 0x0a, 0x1f, 0x64, 0x9b, 0xc1, 0x02, 0xe8, 0xeb, 0x64, 0xad, 0xcd, 0xe8, 0xda, 0x31, 0x51, 0xea, 0x44, 0x1d, 0x1a, 0xca, 0xa6, 0x04, 0xbb, 0xa3, 0x5e, 0x03, 0x1a, 0xad, 0x26, 0x21, 0x34, 0xdb, 0xb8, 0x4e, 0xc9, 0xe3, 0x02, 0x8b, 0x12, 0x9e, 0x8f, 0x41, 0x22, 0xf0, 0x5a, 0x36, 0xce, 0xdf, 0x2c, 0x8b, 0xb8, 0xd2, 0x78, 0x06, 0x35, 0x1f, 0x38, 0x06, 0xd4, 0x10, 0x71, 0x0b, 0x2a, 0x15, 0xd9, 0x2d, 0x43, 0x81, 0x0d, 0xb0, 0xa8, 0xf7, 0x07, 0xb5, 0x4a, 0xa6, 0x4b, 0xa5, 0x40, 0xe7, 0x99, 0x10, 0x81, 0x48, 0x0a, 0x55, 0xb1, 0xb7, 0xfe, 0x63, 0x95, 0xfc, 0x02, 0xb0, 0xe3, 0xac, 0x02, 0xf5, 0x8a, 0x48, 0xef, 0x44, 0x40, 0xde, 0xae, 0x97, 0xd1, 0x35, 0x39, 0x30, 0x85, 0x59, 0x22, 0x22, 0x2d, 0x0d, 0xf9, 0xba, 0x28, 0xa5, 0xfc, 0x8f, 0xd1, 0xc8, 0x4d, 0xa0, 0x5e, 0x4d, 0x08, 0xf4, 0xaf, 0x7d, 0xb2, 0xf8, 0x4f, 0x0e, 0xc7, 0x16, 0x77, 0x0c, 0x8d, 0x09, 0x2d, 0x17, 0xf1, 0x93, 0xbd, 0x1b, 0x79, 0xd6, 0x6c, 0x3f, 0xfa, 0x6f, 0xd8, 0x96, 0x43, 0xfb, 0x5d, 0x40, 0x87, 0x3a, 0x4c, 0x27, 0xdd, 0x1f, 0xa7, 0xba, 0xa8, 0x59, 0x7c, 0x7e, 0xcd, 0x1b, 0xc2, 0x94, 0x83, 0x9a, 0x1f, 0x93, 0x97, 0x53, 0x30, 0x89, 0x98, 0x8e, 0x5a, 0xca, 0x19, 0xd0, 0x88, 0x86, 0xa5, 0x3b, 0x46, 0x91, 0x38, 0x49, 0xd9, 0xc3, 0xab, 0xc7, 0xb1, 0x85, 0xa3, 0x0f, 0xf2, 0x24, 0xc8, 0x38, 0xbd, 0x19, 0xe1, 0xbe, 0xe1, 0xe3, 0xca, 0x20, 0x3a, 0x5e, 0x8a, 0x68, 0x4f, 0x71, 0x6e, 0x7c, 0x09, 0x4d, 0x23, 0x99, 0xfd, 0x60, 0x9f, 0xc7, 0x18, 0x80, 0xd5, 0x99, 0x59, 0xa7, 0x58, 0xe6, 0x55, 0x0e, 0x88, 0xb0, 0xe9, 0x76, 0xe5, 0x92, 0x35, 0x42, 0x9a, 0x26, 0xf2, 0xdf, 0xe1, 0xa6, 0xfa, 0x84, 0xbc, 0xf0, 0x43, 0xd5, 0x75, 0xbd, 0x0c, 0xb0, 0x6e, 0x8a, 0x16, 0xe3, 0x88, 0x7b, 0x42, 0x71, 0x28, 0x98, 0x9e, 0x44, 0xc4, 0x52, 0x88, 0x75, 0x05, 0x2f, 0x06, 0x46, 0xc4, 0x5d, 0x60, 0xca, 0xcb, 0x8f, 0x79, 0x7f, 0x9e, 0x23, 0x86, 0xf4, 0x5f, 0xee, 0xfb, 0x67, 0xa8, 0x3a, 0x8d, 0xc6, 0xe8, 0xcf, 0xb9, 0xf1, 0x0b, 0x2d, 0xb4, 0x42, 0xb7, 0x8f, 0x24, 0x79, 0x8d, 0x40, 0x15, 0xbd, 0x1b, 0x9d, 0x67, 0xc2, 0x7b, 0xc3, 0x55, 0xf2, 0x2b, 0x2b, 0xf1, 0x27, 0xe5, 0x25, 0x61, 0xc8, 0x4e, 0x8a, 0x52, 0x84, 0x94, 0x32, 0xd6, 0x0a, 0x12, 0xd7, 0x96, 0x37, 0x7a, 0x4a, 0x65, 0x44, 0x34, 0x78, 0xc7, 0xb4, 0xd3, 0x78, 0xbf, 0x7a, 0xcf, 0xd8, 0xc6, 0x5f, 0x2c, 0xeb, 0x81, 0x16, 0xc5, 0xcb, 0xb7, 0x7a, 0x65, 0x5c, 0xb5, 0xa2, 0x1a, 0xd2, 0x90, 0xea, 0x5d, 0x3c, 0xe8, 0xa6, 0x27, 0x59, 0xb7, 0xaf, 0x5f, 0x17, 0x2b, 0x49, 0x41, 0xf7, 0x12, 0x21, 0x5b, 0x10, 0x47, 0xc8, 0xf3, 0x63, 0xaa, 0xeb, 0xd3, 0x73, 0xd2, 0x50, 0x8d, 0x4e, 0x6f, 0x31, 0x9f, 0x3e, 0xef, 0x85, 0x4e, 0x0c, 0xc8, 0x4d, 0x15, 0x82, 0x5a, 0xbb, 0x42, 0xdc, 0x8d, 0xbd, 0x72, 0x0f, 0x75, 0xe4, 0x44, 0x5b, 0x43, 0x65, 0xa4, 0x5d, 0x1e, 0x78, 0x46, 0x44, 0xcb, 0x83, 0xdb, 0x0d, 0xa8, 0xa6, 0xba, 0x38, 0xcd, 0x5c, 0xa1, 0x84, 0xa0, 0x5d, 0x6b, 0x24, 0x27, 0x47, 0xc1, 0x3b, 0x94, 0xef, 0x3c, 0xe1, 0x39, 0x8c, 0x63, 0x05, 0x92, 0xf1, 0xd6, 0x50, 0x51, 0x8c, 0x53, 0xaf, 0x44, 0xd0, 0xb1, 0x3f, 0xd8, 0x1d, 0x03, 0x65, 0x99, 0x1f, 0x2a, 0x87, 0x80, 0x47, 0xc6, 0x70, 0xfd, 0x93, 0x96, 0xd8, 0x13, 0xb6, 0x47, 0x6a, 0xb2, 0x65, 0x7a, 0x2e, 0x48, 0x3a, 0x51, 0xf3, 0x86, 0xb4, 0xd1, 0x17, 0x16, 0xcb, 0xe3, 0x6b, 0xcb, 0x99, 0xbf, 0x7e, 0x81, 0x7d, 0x94, 0x0f, 0x9b, 0x09, 0x1d, 0xbe, 0xd0, 0xf2, 0xaa, 0xc0, 0x3f, 0xe9, 0xe7, 0xb0, 0x4c, 0xb9, 0x9d, 0xb6, 0x1a, 0x00, 0x87, 0x48, 0xb7, 0x02, 0x0d, 0xba, 0x9a, 0x2c, 0x1e, 0x13, 0xa6, 0x48, 0x23, 0x33, 0x84, 0x73, 0x1c, 0x27, 0x3e, 0x9a, 0x2f, 0xa8, 0x6e, 0x45, 0x45, 0x2e, 0x48, 0xe0, 0xa0, 0xe2, 0x58, 0x05, 0x86, 0x3e, 0x7d, 0xe5, 0x81, 0x8b, 0x0b, 0xae, 0x4d, 0xac, 0x21, 0x7d, 0x8e, 0x52, 0xb9, 0xb9, 0x75, 0x50, 0x07, 0xca, 0x4d, 0xc8, 0xe7, 0x22, 0xa3, 0xcb, 0x56, 0x5b, 0x00, 0xc8, 0x48, 0x1e, 0x8f, 0x3d, 0x91, 0x1c, 0x33, 0x26, 0x45, 0x81, 0x66, 0x07, 0xc6, 0x1a, 0x9b, 0xd3, 0x50, 0x3a, 0xd1, 0xa8, 0x60, 0xd0, 0x64, 0xed, 0xe6, 0xc6, 0x78, 0x04, 0xe6, 0x8f, 0xa4, 0x5f, 0x4e, 0x40, 0x1b, 0xf3, 0x5c, 0x22, 0x94, 0x1e, 0xb1, 0xb3, 0xd0, 0xe6, 0xe4, 0x2c, 0x0f, 0x6e, 0x1d, 0x61, 0x55, 0xfb, 0x49, 0xe0, 0xc0, 0x3a, 0x7b, 0x33, 0x65, 0x84, 0xf6, 0x7a, 0xda, 0x24, 0x74, 0x17, 0x3d, 0x55, 0x03, 0xd6, 0xbc, 0x18, 0xda, 0x72, 0x01, 0x25, 0xe0, 0x67, 0x54, 0x3f, 0x5b, 0x78, 0x00, 0xb4, 0xb1, 0xca, 0x6c, 0xe2, 0x81, 0xad, 0x44, 0x5a, 0x84, 0x4e, 0x4d, 0x89, 0x7e, 0x92, 0x7e, 0x6e, 0xa0, 0x71, 0x1b, 0x26, 0x58, 0x38, 0xee, 0x1c, 0x96, 0xfa, 0x67, 0x99, 0x53, 0x76, 0xe8, 0xa3, 0x28, 0x27, 0xfc, 0x2f, 0xdc, 0x4d, 0x34, 0xac, 0x7e, 0xd0, 0x47, 0x7a, 0x7a, 0xac, 0xe7, 0x6a, 0x9b, 0x2c, 0x33, 0xa0, 0x9e, 0x32, 0xaa, 0x33, 0xcc, 0x32, 0xb4, 0xac, 0x30, 0x28, 0xe3, 0x9e, 0xa7, 0x36, 0x5c, 0xde, 0x64, 0xc9, 0x39, 0x6f, 0xfd, 0x15, 0x16, 0x58, 0x5e, 0xea, 0xcc, 0x40, 0xec, 0x88, 0xca, 0x3b, 0x0c, 0xfb, 0x91, 0xb0, 0xb9, 0xb4, 0x78, 0xdf, 0x75, 0xd7, 0x0d, 0xf7, 0x96, 0xc5, 0x3b, 0x23, 0xfc, 0x21, 0x79, 0x20, 0xe1, 0x39, 0x3e, 0xfc, 0x6b, 0xb7, 0x86, 0x9f, 0x81, 0x93, 0x81, 0x34, 0xba, 0xc3, 0x02, 0x43, 0x3c, 0xdf, 0x1c, 0xa1, 0x53, 0xeb, 0xf8, 0x06, 0x8a, 0xc5, 0xe7, 0x5f, 0x36, 0x8d, 0x4a, 0x0c, 0x5d, 0xc1, 0x3e, 0xaf, 0x56, 0xf3, 0xad, 0xfb, 0x15, 0x29, 0x83, 0x40, 0x68, 0xb6, 0xe5, 0xea, 0xab, 0xe1, 0x06, 0x37, 0x62, 0x0e, 0x43, 0x31, 0xcb, 0xa3, 0x31, 0xf1, 0xff, 0xd2, 0x0f, 0xfc, 0x42, 0x25, 0x92, 0x65, 0x33, 0x6b, 0x70, 0x45, 0xb0, 0xee, 0xdf, 0x9f, 0xdc, 0xdb, 0x83, 0xb0, 0x09, 0xeb, 0x3d, 0xac, 0xb9, 0x7e, 0x9d, 0x17, 0x8c, 0xe4, 0x75, 0xa3, 0x50, 0x26, 0x93, 0x81, 0x8b, 0xc4, 0x3e, 0xc6, 0x59, 0x80, 0xcd, 0x0d, 0xad, 0xe2, 0x43, 0xf2, 0xb3, 0xfd, 0x50, 0x6f, 0xa3, 0x52, 0xec, 0x20, 0xea, 0xe2, 0x86, 0x8d, 0x3e, 0x8f, 0xcc, 0x87, 0x27, 0x75, 0x73, 0x0e, 0xed, 0x2c, 0x25, 0xc3, 0x03, 0x19, 0xdf, 0xcf, 0xa1, 0xc2, 0x88, 0xed, 0x51, 0x5d, 0x21, 0x9f, 0x25, 0xcf, 0xa0, 0xfa, 0xe3, 0x12, 0x13, 0x44, 0xb5, 0x99, 0x51, 0x63, 0xe0, 0xc1, 0x86, 0x6d, 0xd9, 0x61, 0xaf, 0x3c, 0x25, 0x7b, 0xea, 0x09, 0x46, 0x0c, 0x2f, 0xbe, 0x9b, 0xb6, 0x8f, 0x98, 0xf3, 0x70, 0x5b, 0x3e, 0xa3, 0xa0, 0x57, 0x77, 0xdd, 0x91, 0x48, 0xee, 0xb3, 0x78, 0x01, 0x31, 0x99, 0xed, 0xd2, 0xa9, 0xc5, 0x4c, 0xb2, 0xbd, 0x7c, 0x7b, 0xe9, 0x4a, 0x65, 0x0e, 0xb0, 0x3f, 0x7b, 0x95, 0x0d, 0x77, 0xb3, 0x55, 0x11, 0xff, 0xfb, 0xd6, 0x82, 0x09, 0xee, 0x8f, 0x50, 0x76, 0x5f, 0x06, 0x57, 0xa2, 0xb6, 0xa1, 0x2f, 0x16, 0x2e, 0x0f, 0xef, 0x3c, 0x93, 0x89, 0x24, 0x8d, 0x60, 0x91, 0x67, 0x98, 0x86, 0x43, 0x61, 0x7f, 0x60, 0x31, 0x7c, 0xa2, 0x4e, 0x8e, 0xa0, 0xa2, 0x92, 0x47, 0x6f, 0x24, 0x5b, 0x14, 0x09, 0x15, 0xfb, 0xe5, 0x12, 0x37, 0x81, 0x8d, 0xf7, 0x53, 0x5a, 0x15, 0xc1, 0x4f, 0xc5, 0x0a, 0x23, 0x3d, 0x44, 0x25, 0x8b, 0xa5, 0x7d, 0xf7, 0xd2, 0xb7, 0x95, 0xc7, 0xf3, 0x4d, 0x2b, 0x18, 0xf0, 0x6f, 0x5e, 0x0a, 0xff, 0x9f, 0xb0, 0xf5, 0x45, 0x35, 0x04, 0xc6, 0xc2, 0xab, 0x76, 0xbb, 0x35, 0xd3, 0x1a, 0xe6, 0x2b, 0x9f, 0xee, 0xa8, 0x74, 0x09, 0x7e, 0x7b, 0x5b, 0x4e, 0xc6, 0x65, 0x90, 0x1f, 0x67, 0x70, 0x42, 0xae, 0x37, 0xe3, 0x27, 0xc0, 0x0e, 0xeb, 0x4a, 0xe4, 0x58, 0x17, 0x87, 0x09, 0xba, 0xc3, 0xa1, 0x96, 0x3a, 0x9e, 0x47, 0xfa, 0xc2, 0xcf, 0x70, 0x6f, 0x79, 0x4c, 0xe6, 0xcd, 0x73, 0x8c, 0x07, 0x9c, 0xe9, 0x91, 0x08, 0x55, 0x08, 0x2f, 0x44, 0x08, 0x36, 0x9d, 0x91, 0x4d, 0x35, 0xaf, 0x2b, 0x99, 0x5d, 0x2a, 0xdd, 0xf3, 0x47, 0xcf, 0xc2, 0x7b, 0x03, 0xea, 0x24, 0x6c, 0x86, 0x73, 0x64, 0xd7, 0x95, 0xf9, 0x31, 0x6c, 0x86, 0x7e, 0xd8, 0x4d, 0x21, 0xdb, 0x9b, 0xcb, 0x22, 0x1c, 0xa4, 0x97, 0xbb, 0x1b, 0x80, 0x75, 0x9f, 0xda, 0x2e, 0xad, 0xed, 0x87, 0x6a, 0x21, 0xfa, 0x38, 0x7f, 0x28, 0x71, 0x44, 0xa9, 0x56, 0x4c, 0x36, 0x3c, 0x8c, 0xb4, 0xd0, 0x01, 0xe6, 0xf1, 0x07, 0x36, 0x14, 0xba, 0xd5, 0xf7, 0xfc, 0x1e, 0x36, 0x44, 0x1f, 0x45, 0xa3, 0x0b, 0x84, 0xde, 0x8a, 0xb7, 0xa4, 0x93, 0x4f, 0x64, 0x28, 0xa5, 0xce, 0x62, 0x5e, 0xef, 0x6c, 0xe6, 0xfd, 0x25, 0x99, 0x96, 0x8f, 0x7d, 0x53, 0x8d, 0x25, 0x4e, 0x13, 0xfb, 0xe7, 0xef, 0xbc, 0x46, 0x74, 0x20, 0x43, 0x9f, 0xc3, 0x7d, 0x5d, 0xdc, 0xd3, 0x96, 0x63, 0xe1, 0x10, 0xa1, 0xcc, 0x2c, 0x77, 0xd3, 0xf0, 0xed, 0x59, 0x28, 0xd6, 0x2f, 0x07, 0x8d, 0x07, 0x54, 0xe1, 0x89, 0xb4, 0x73, 0x6e, 0x2d, 0x9e, 0xec, 0xb5, 0x9f, 0x38, 0xaa, 0x29, 0xce, 0x49, 0x0a, 0x62, 0x5e, 0x0b, 0x3e, 0xac, 0x6f, 0xc0, 0xe2, 0x15, 0x53, 0x41, 0x99, 0x75, 0xbb, 0xf5, 0x21, 0x77, 0xc7, 0x31, 0xb4, 0xcb, 0xca, 0xfd, 0x1a, 0xeb, 0x84, 0x1f, 0xed, 0x17, 0xb0, 0x5f, 0x60, 0x69, 0x36, 0xc7, 0x30, 0x84, 0xf2, 0x92, 0x3b, 0x1a, 0x46, 0xc6, 0xa3, 0x12, 0x9d, 0xb7, 0x0c, 0xfa, 0xd1, 0x33, 0x65, 0x0a, 0x72, 0x07, 0x46, 0x71, 0xbd, 0x3f, 0x91, 0xf3, 0x26, 0xda, 0x87, 0x9a, 0xfd, 0x30, 0x86, 0x04, 0xbe, 0x5b, 0x25, 0x53, 0x37, 0xef, 0xed, 0x22, 0x3a, 0xcf, 0xc6, 0xc5, 0x65, 0xe6, 0x58, 0x11, 0xaa, 0x0f, 0xe8, 0x84, 0x22, 0x05, 0xe3, 0x7f, 0x6b, 0x13, 0xc8, 0x4c, 0x46, 0x81, 0xe2, 0x62, 0x37, 0x63, 0x13, 0xcb, 0x22, 0x8d, 0x91, 0x68, 0xcf, 0xe9, 0xf5, 0x1f, 0x5a, 0x51, 0x8a, 0x29, 0x14, 0xdd, 0x51, 0xe3, 0xd4, 0x3d, 0xfd, 0x09, 0xd6, 0x98, 0x4c, 0xee, 0xb6, 0x34, 0xc2, 0x46, 0xc5, 0xc2, 0xe2, 0xb2, 0xd4, 0xa1, 0xc6, 0x71, 0xbf, 0xca, 0x97, 0x6c, 0x4c, 0xe8, 0x86, 0x31, 0x9f, 0x28, 0x31, 0x16, 0x6b, 0xb7, 0x3e, 0x74, 0x14, 0xfd, 0x0a, 0x93, 0x45, 0x0c, 0xdb, 0xca, 0x5b, 0x6a, 0x4c, 0xb3, 0xb1, 0x5c, 0x0a, 0x86, 0x14, 0xa7, 0x6b, 0x2a, 0x0a, 0xb7, 0x75, 0xb6, 0x93, 0x53, 0x51, 0x7a, 0xec, 0xa2, 0x0e, 0xb2, 0xe7, 0x21, 0x54, 0x91, 0x3b, 0xdf, 0xcb, 0x63, 0x51, 0x29, 0x62, 0x28, 0x4e, 0x76, 0xa1, 0xa7, 0xdd, 0x37, 0x94, 0xde, 0x6f, 0x75, 0x4a, 0xb5, 0x22, 0x88, 0x11, 0xd5, 0x7c, 0x44, 0xa6, 0x43, 0x6e, 0x7f, 0x18, 0xed, 0x8d, 0x4f, 0x2a, 0x74, 0x99, 0x11, 0x13, 0xe6, 0x0d, 0xa6, 0xfa, 0x77, 0x1d, 0xa5, 0x5a, 0x49, 0x01, 0x16, 0x2d, 0x2a, 0x57, 0xfc, 0x13, 0xe2, 0xc3, 0xe0, 0x17, 0xa3, 0x57, 0xea, 0xb2, 0x5b, 0x1b, 0x9c, 0xce, 0x7b, 0xd2, 0x12, 0xf3, 0x54, 0xdf, 0x38, 0x1a, 0x54, 0x7c, 0xbc, 0x07, 0x7e, 0xe6, 0xc8, 0xf6, 0x6e, 0x15, 0x17, 0x93, 0x4e, 0xf9, 0xcb, 0xee, 0xa1, 0xb1, 0x89, 0xa4, 0xa4, 0xf5, 0xb3, 0x07, 0xdc, 0x16, 0xf1, 0x08, 0x4c, 0xd8, 0xff, 0xbf, 0xe8, 0xaa, 0xf1, 0xe2, 0x07, 0xe8, 0xca, 0x0c, 0xd8, 0x7e, 0x4e, 0x74, 0xf1, 0x91, 0x05, 0xa5, 0x3f, 0x21, 0x77, 0x33, 0x97, 0x10, 0x6d, 0xc3, 0xf6, 0xab, 0x2d, 0xcc, 0xf0, 0x3d, 0x83, 0x32, 0x1a, 0xc4, 0xbc, 0x86, 0xdb, 0x78, 0xf7, 0x02, 0x2e, 0x43, 0x5d, 0x3e, 0x55, 0x44, 0x8a, 0x88, 0x09, 0xe7, 0x3f, 0xc5, 0x03, 0xfe, 0xe9, 0xff, 0xf0, 0xae, 0xf6, 0x93, 0xd8, 0xc7, 0x3e, 0x3f, 0x04, 0x82, 0xa6, 0x4f, 0x1a, 0x4e, 0x19, 0x75, 0x82, 0x8e, 0x27, 0xfd, 0x46, 0x03, 0x09, 0x50, 0x8d, 0x24, 0xdb, 0xd7, 0xd4, 0xdf, 0x3c, 0x35, 0xd7, 0xec, 0x3c, 0xba, 0x83, 0x0a, 0x66, 0x60, 0xca, 0x93, 0x37, 0x66, 0x19, 0xca, 0x9f, 0x41, 0xac, 0x0c, 0x73, 0x1d, 0xd5, 0x9a, 0x30, 0x38, 0x3b, 0x59, 0x4c, 0xc3, 0xcc, 0x67, 0x13, 0xf1, 0x02, 0x30, 0x0c, 0xa8, 0x6f, 0x93, 0x5b, 0x06, 0x82, 0x2e, 0x24, 0x10, 0x27, 0x54, 0xa6, 0x5f, 0x0c, 0x03, 0x1a, 0xa3, 0x9b, 0xc6, 0x8e, 0x33, 0x92, 0x32, 0x33, 0xcb, 0xb2, 0x62, 0xe9, 0x19, 0xf2, 0x9b, 0xdd, 0x36, 0xaa, 0x67, 0x19, 0xd3, 0x39, 0x47, 0x9c, 0x6c, 0x22, 0x46, 0x08, 0x7e, 0x94, 0x83, 0x7b, 0x52, 0xbc, 0xfe, 0x46, 0xd2, 0x9e, 0x17, 0x24, 0x04, 0xa6, 0xca, 0x83, 0x6a, 0xb6, 0x88, 0x65, 0x36, 0x48, 0x2e, 0x4c, 0xc8, 0x6d, 0xa7, 0xf9, 0xc9, 0x3c, 0xc2, 0xd2, 0x2f, 0xe0, 0x14, 0xed, 0x38, 0x51, 0xdd, 0xea, 0x36, 0x56, 0xbe, 0x79, 0x03, 0x51, 0x22, 0x03, 0xae, 0x65, 0x60, 0xb7, 0x82, 0x86, 0x46, 0x27, 0xf1, 0x7b, 0x91, 0xea, 0xc6, 0x59, 0x29, 0x43, 0x23, 0x1b, 0xa6, 0x7a, 0x14, 0x35, 0x8a, 0x44, 0xd6, 0xde, 0xc8, 0x17, 0x43, 0x5f, 0x0f, 0xc4, 0x71, 0x11, 0xe5, 0xec, 0x21, 0x7f, 0x41, 0xa2, 0xc6, 0x03, 0x28, 0x98, 0x7e, 0x45, 0xac, 0x30, 0x91, 0xee, 0x65, 0x8d, 0x04, 0xef, 0x18, 0x8e, 0xbc, 0x3a, 0x21, 0x6e, 0xfb, 0xeb, 0x89, 0x2b, 0xc1, 0x35, 0x34, 0x90, 0x6d, 0x87, 0xa0, 0xa2, 0x99, 0xed, 0x41, 0x66, 0x02, 0xd4, 0x04, 0x6c, 0xa2, 0x75, 0xb3, 0x11, 0x00, 0xd9, 0xaa, 0x7a, 0x30, 0x82, 0x3a, 0x1a, 0x64, 0x4f, 0x5e, 0x1b, 0xbe, 0x82, 0xa0, 0xc7, 0x2c, 0xda, 0x8e, 0x74, 0x06, 0x81, 0x7b, 0x77, 0xde, 0x12, 0xaf, 0x69, 0x21, 0x43, 0x3d, 0xd1, 0x96, 0xc9, 0x1c, 0xb5, 0x8e, 0x42, 0x5c, 0x43, 0x8a, 0x7e, 0xbe, 0xba, 0xb0, 0x1e, 0x76, 0x8f, 0xe9, 0x34, 0xdb, 0x43, 0x37, 0x05, 0x32, 0x2f, 0xea, 0xca, 0x2d, 0x11, 0x65, 0x1d, 0xa9, 0xd6, 0xe1, 0x9c, 0x6b, 0x40, 0x16, 0x3a, 0x48, 0xa6, 0x38, 0xa5, 0x96, 0x18, 0x71, 0xc0, 0xcd, 0xb1, 0xf3, 0xa0, 0x3c, 0x14, 0x18, 0x80, 0x78, 0x38, 0xa4, 0x3b, 0x37, 0x6c, 0x08, 0xaa, 0x5a, 0xdc, 0xe8, 0x72, 0x8e, 0xc3, 0x15, 0x61, 0x28, 0x6e, 0xcf, 0x8f, 0xae, 0xb6, 0xdf, 0x00, 0xe7, 0xfc, 0x06, 0xcf, 0x5c, 0xb0, 0x3d, 0x8b, 0x1d, 0x0a, 0x10, 0xa2, 0xb7, 0x71, 0x94, 0x9d, 0xe2, 0x5a, 0x28, 0x50, 0x9a, 0xd8, 0x52, 0x7c, 0x48, 0x80, 0x4f, 0x21, 0xcb, 0x30, 0x4a, 0x87, 0x2c, 0xf0, 0x96, 0xe3, 0xd7, 0xc8, 0xd4, 0xa6, 0x0c, 0x14, 0xa0, 0x43, 0xbe, 0x68, 0xfd, 0x0a, 0x67, 0x42, 0xdd, 0xfa, 0x4d, 0x78, 0x09, 0xb8, 0x65, 0x31, 0xcc, 0x8d, 0x07, 0xfa, 0xec, 0x08, 0x75, 0x82, 0x50, 0x22, 0xdd, 0xa0, 0xc2, 0x46, 0xa5, 0xc1, 0x41, 0x24, 0xc4, 0xe8, 0x16, 0x44, 0xb5, 0x92, 0xd4, 0xc5, 0x44, 0xd3, 0x94, 0xa4, 0x5f, 0x00, 0x00, 0x39, 0x00, 0x31, 0x00, 0x65, 0x00, 0x66, 0x00, 0x62, 0x00, 0x38, 0x00, 0x62, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x3f, 0x00, 0x5c, 0x00, 0x53, 0x00, 0x54, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x41, 0x00, 0x47, 0x00, 0x45, 0x00, 0x23, 0x00, 0x56, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x23, 0x00, 0x7b, 0x00, 0x30, 0x00, 0x61, 0x00, 0x63, 0x00, 0x36, 0x00, 0x62, 0x00, 0x63, 0x00, 0x36, 0x00, 0x61, 0x00, 0x2d, 0x00, 0x37, 0x00, 0x35, 0x00, 0x36, 0x00, 0x30, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x31, 0x00, 0x65, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x39, 0x00, 0x66, 0x00, 0x62, 0x00, 0x30, 0x00, 0x2d, 0x00, 0x38, 0x00, 0x30, 0x00, 0x36, 0x00, 0x65, 0x00, 0x36, 0x00, 0x66, 0x00, 0x36, 0x00, 0x65, 0x00, 0x36, 0x00, 0x39, 0x00, 0x36, 0x00, 0x33, 0x00, 0x7d, 0x00, 0x23, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x46, 0x00, 0x45, 0x00, 0x32, 0x00, 0x34, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x23, 0x00, 0x7b, 0x00, 0x35, 0x00, 0x33, 0x00, 0x66, 0x00, 0x35, 0x00, 0x36, 0x00, 0x33, 0x00, 0x30, 0x00, 0x64, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x36, 0x00, 0x62, 0x00, 0x66, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x31, 0x00, 0x64, 0x00, 0x30, 0x00, 0x2d, 0x00, 0x39, 0x00, 0x34, 0x00, 0x66, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x30, 0x00, 0x61, 0x00, 0x30, 0x00, 0x63, 0x00, 0x39, 0x00, 0x31, 0x00, 0x65, 0x00, 0x66, 0x00, 0x62, 0x00, 0x38, 0x00, 0x62, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x3f, 0x00, 0x5c, 0x00, 0x53, 0x00, 0x54, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x41, 0x00, 0x47, 0x00, 0x45, 0x00, 0x23, 0x00, 0x56, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x23, 0x00, 0x7b, 0x00, 0x32, 0x00, 0x34, 0x00, 0x62, 0x00, 0x37, 0x00, 0x35, 0x00, 0x66, 0x00, 0x63, 0x00, 0x66, 0x00, 0x2d, 0x00, 0x34, 0x00, 0x64, 0x00, 0x35, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x31, 0x00, 0x65, 0x00, 0x39, 0x00, 0x2d, 0x00, 0x61, 0x00, 0x30, 0x00, 0x62, 0x00, 0x34, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x32, 0x00, 0x35, 0x00, 0x34, 0x00, 0x30, 0x00, 0x30, 0x00, 0x65, 0x00, 0x65, 0x00, 0x62, 0x00, 0x36, 0x00, 0x30, 0x00, 0x35, 0x00, 0x7d, 0x00, 0x23, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x23, 0x00, 0x7b, 0x00, 0x35, 0x00, 0x33, 0x00, 0x66, 0x00, 0x35, 0x00, 0x36, 0x00, 0x33, 0x00, 0x30, 0x00, 0x64, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x36, 0x00, 0x62, 0x00, 0x66, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x31, 0x00, 0x64, 0x00, 0x30, 0x00, 0x2d, 0x00, 0x39, 0x00, 0x34, 0x00, 0x66, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x30, 0x00, 0x61, 0x00, 0x30, 0x00, 0x63, 0x00, 0x39, 0x00, 0x31, 0x00, 0x65, 0x00, 0x66, 0x00, 0x62, 0x00, 0x38, 0x00, 0x62, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x3f, 0x00, 0x5c, 0x00, 0x53, 0x00, 0x54, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x41, 0x00, 0x47, 0x00, 0x45, 0x00, 0x23, 0x00, 0x56, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x23, 0x00, 0x7b, 0x00, 0x33, 0x00, 0x31, 0x00, 0x66, 0x00, 0x64, 0x00, 0x36, 0x00, 0x65, 0x00, 0x38, 0x00, 0x61, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x30, 0x00, 0x62, 0x00, 0x66, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x31, 0x00, 0x65, 0x00, 0x39, 0x00, 0x2d, 0x00, 0x61, 0x00, 0x30, 0x00, 0x39, 0x00, 0x33, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x32, 0x00, 0x35, 0x00, 0x34, 0x00, 0x30, 0x00, 0x30, 0x00, 0x65, 0x00, 0x65, 0x00, 0x62, 0x00, 0x36, 0x00, 0x30, 0x00, 0x35, 0x00, 0x7d, 0x00, 0x23, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x23, 0x00, 0x7b, 0x00, 0x35, 0x00, 0x33, 0x00, 0x66, 0x00, 0x35, 0x00, 0x36, 0x00, 0x33, 0x00, 0x30, 0x00, 0x64, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x36, 0x00, 0x62, 0x00, 0x66, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x31, 0x00, 0x64, 0x00, 0x30, 0x00, 0x2d, 0x00, 0x39, 0x00, 0x34, 0x00, 0x66, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x30, 0x00, 0x61, 0x00, 0x30, 0x00 }; uint8_t fsntfs_test_compression_uncompressed_data1[ 7638 ] = { 0x09, 0x09, 0x20, 0x20, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x45, 0x53, 0x53, 0x45, 0x52, 0x20, 0x47, 0x45, 0x4e, 0x45, 0x52, 0x41, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x2c, 0x20, 0x32, 0x39, 0x20, 0x4a, 0x75, 0x6e, 0x65, 0x20, 0x32, 0x30, 0x30, 0x37, 0x0a, 0x0a, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x43, 0x29, 0x20, 0x32, 0x30, 0x30, 0x37, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x20, 0x3c, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x66, 0x73, 0x66, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x45, 0x76, 0x65, 0x72, 0x79, 0x6f, 0x6e, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x72, 0x62, 0x61, 0x74, 0x69, 0x6d, 0x20, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x0a, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x73, 0x0a, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x0a, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x64, 0x20, 0x62, 0x65, 0x6c, 0x6f, 0x77, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x30, 0x2e, 0x20, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x41, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x2c, 0x20, 0x22, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x0a, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x22, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x22, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x0a, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x22, 0x54, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x22, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x0a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x61, 0x73, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x65, 0x6c, 0x6f, 0x77, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x41, 0x6e, 0x20, 0x22, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x73, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x0a, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x20, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x0a, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x73, 0x75, 0x62, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x69, 0x73, 0x20, 0x64, 0x65, 0x65, 0x6d, 0x65, 0x64, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x0a, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x41, 0x20, 0x22, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x22, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x22, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x0a, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x22, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x2c, 0x20, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x0a, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x72, 0x65, 0x0a, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x22, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x74, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x73, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x31, 0x2e, 0x20, 0x45, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x33, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x34, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x62, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x32, 0x2e, 0x20, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x49, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x0a, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x74, 0x68, 0x61, 0x74, 0x20, 0x75, 0x73, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x28, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x29, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x0a, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x29, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x61, 0x69, 0x74, 0x68, 0x20, 0x65, 0x66, 0x66, 0x6f, 0x72, 0x74, 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x77, 0x68, 0x61, 0x74, 0x65, 0x76, 0x65, 0x72, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x73, 0x20, 0x70, 0x75, 0x72, 0x70, 0x6f, 0x73, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x69, 0x6e, 0x67, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x6f, 0x72, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x29, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x33, 0x2e, 0x20, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x0a, 0x61, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x20, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x0a, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x64, 0x0a, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x0a, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x73, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x0a, 0x28, 0x74, 0x65, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x66, 0x65, 0x77, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x29, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x29, 0x20, 0x47, 0x69, 0x76, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x73, 0x20, 0x75, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x29, 0x20, 0x41, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x34, 0x2e, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x0a, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x20, 0x64, 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x0a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x64, 0x6f, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x0a, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x29, 0x20, 0x47, 0x69, 0x76, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x73, 0x20, 0x75, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x29, 0x20, 0x41, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x29, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x73, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x73, 0x20, 0x64, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x64, 0x29, 0x20, 0x44, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x29, 0x20, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x75, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x36, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x29, 0x20, 0x55, 0x73, 0x65, 0x20, 0x61, 0x20, 0x73, 0x75, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x20, 0x20, 0x41, 0x20, 0x73, 0x75, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x20, 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x28, 0x61, 0x29, 0x20, 0x75, 0x73, 0x65, 0x73, 0x20, 0x61, 0x74, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x27, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x28, 0x62, 0x29, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x6c, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x65, 0x29, 0x20, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x36, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x6e, 0x65, 0x63, 0x65, 0x73, 0x73, 0x61, 0x72, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x28, 0x49, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x34, 0x64, 0x30, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x0a, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x34, 0x64, 0x31, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x36, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x35, 0x2e, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x73, 0x69, 0x64, 0x65, 0x20, 0x62, 0x79, 0x20, 0x73, 0x69, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x0a, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x0a, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x0a, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x29, 0x20, 0x41, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x62, 0x61, 0x73, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x29, 0x20, 0x47, 0x69, 0x76, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x36, 0x2e, 0x20, 0x52, 0x65, 0x76, 0x69, 0x73, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20, 0x72, 0x65, 0x76, 0x69, 0x73, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, 0x6e, 0x65, 0x77, 0x0a, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x69, 0x6d, 0x69, 0x6c, 0x61, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x70, 0x69, 0x72, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6d, 0x61, 0x79, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x20, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x45, 0x61, 0x63, 0x68, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x20, 0x64, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x63, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x22, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x0a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x79, 0x20, 0x61, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x0a, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x68, 0x6f, 0x6f, 0x73, 0x65, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x0a, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x65, 0x76, 0x65, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x0a, 0x77, 0x68, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x27, 0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x0a, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x68, 0x6f, 0x6f, 0x73, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x0a, 0x0a }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_decompress_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_decompress_data( void ) { libcerror_error_t *error = NULL; uint8_t *uncompressed_data = NULL; void *memset_result = NULL; size_t uncompressed_data_size = 0; int result = 0; /* Initialize test */ uncompressed_data = (uint8_t *) memory_allocate( 8192 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "uncompressed_data", uncompressed_data ); /* Test regular cases */ memset_result = memory_set( uncompressed_data, 0, 8192 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "memset_result", memset_result ); uncompressed_data_size = 8192; result = libfsntfs_decompress_data( fsntfs_test_compression_lznt1_compressed_data1, 8192, LIBFSNTFS_COMPRESSION_METHOD_LZNT1, uncompressed_data, &uncompressed_data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "uncompressed_data_size", uncompressed_data_size, (size_t) 8192 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( uncompressed_data, fsntfs_test_compression_uncompressed_data1, 7638 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memset_result = memory_set( uncompressed_data, 0, 8192 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "memset_result", memset_result ); uncompressed_data_size = 8192; result = libfsntfs_decompress_data( fsntfs_test_compression_lzxpress_huffman_compressed_data1, 4096, LIBFSNTFS_COMPRESSION_METHOD_LZXPRESS_HUFFMAN, uncompressed_data, &uncompressed_data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "uncompressed_data_size", uncompressed_data_size, (size_t) 8192 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( uncompressed_data, fsntfs_test_compression_uncompressed_data1, 7638 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); /* Test error cases */ memset_result = memory_set( uncompressed_data, 0, 8192 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "memset_result", memset_result ); uncompressed_data_size = 8192; result = libfsntfs_decompress_data( NULL, 8192, LIBFSNTFS_COMPRESSION_METHOD_LZNT1, uncompressed_data, &uncompressed_data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_decompress_data( uncompressed_data, (size_t) SSIZE_MAX + 1, LIBFSNTFS_COMPRESSION_METHOD_LZNT1, uncompressed_data, &uncompressed_data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_decompress_data( fsntfs_test_compression_lznt1_compressed_data1, 8192, -1, uncompressed_data, &uncompressed_data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_decompress_data( fsntfs_test_compression_lznt1_compressed_data1, 8192, LIBFSNTFS_COMPRESSION_METHOD_LZNT1, NULL, &uncompressed_data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_decompress_data( fsntfs_test_compression_lznt1_compressed_data1, 8192, LIBFSNTFS_COMPRESSION_METHOD_LZNT1, uncompressed_data, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ memory_free( uncompressed_data ); uncompressed_data = NULL; return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( uncompressed_data != NULL ) { memory_free( uncompressed_data ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_decompress_data", fsntfs_test_decompress_data ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_compression_unit_data_handle.c ================================================ /* * Library compression_unit_data_handle type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_compression_unit_data_handle.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" uint8_t fsntfs_test_compression_unit_data_handle_data1[ 80 ] = { 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x01, 0x01, 0x0e, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_compression_unit_data_handle_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_compression_unit_data_handle_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_compression_unit_data_handle_t *compression_unit_data_handle = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_compression_unit_data_handle_data1, 80, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_compression_unit_data_handle_initialize( &compression_unit_data_handle, io_handle, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "compression_unit_data_handle", compression_unit_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_compression_unit_data_handle_free( &compression_unit_data_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compression_unit_data_handle", compression_unit_data_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_compression_unit_data_handle_initialize( NULL, io_handle, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); compression_unit_data_handle = (libfsntfs_compression_unit_data_handle_t *) 0x12345678UL; result = libfsntfs_compression_unit_data_handle_initialize( &compression_unit_data_handle, io_handle, mft_attribute, &error ); compression_unit_data_handle = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_compression_unit_data_handle_initialize( &compression_unit_data_handle, NULL, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_compression_unit_data_handle_initialize( &compression_unit_data_handle, io_handle, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_compression_unit_data_handle_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_compression_unit_data_handle_initialize( &compression_unit_data_handle, io_handle, mft_attribute, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( compression_unit_data_handle != NULL ) { libfsntfs_compression_unit_data_handle_free( &compression_unit_data_handle, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compression_unit_data_handle", compression_unit_data_handle ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_compression_unit_data_handle_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_compression_unit_data_handle_initialize( &compression_unit_data_handle, io_handle, mft_attribute, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( compression_unit_data_handle != NULL ) { libfsntfs_compression_unit_data_handle_free( &compression_unit_data_handle, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compression_unit_data_handle", compression_unit_data_handle ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( compression_unit_data_handle != NULL ) { libfsntfs_compression_unit_data_handle_free( &compression_unit_data_handle, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_compression_unit_data_handle_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_compression_unit_data_handle_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_compression_unit_data_handle_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_compression_unit_data_handle_initialize", fsntfs_test_compression_unit_data_handle_initialize ); FSNTFS_TEST_RUN( "libfsntfs_compression_unit_data_handle_free", fsntfs_test_compression_unit_data_handle_free ); /* TODO add tests for libfsntfs_compression_unit_data_handle_get_number_of_descriptors */ /* TODO add tests for libfsntfs_compression_unit_data_handle_get_descriptor_by_index */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_compression_unit_descriptor.c ================================================ /* * Library compression_unit_descriptor type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_compression_unit_descriptor.h" #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_compression_unit_descriptor_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_compression_unit_descriptor_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_compression_unit_descriptor_t *compression_unit_descriptor = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_compression_unit_descriptor_initialize( &compression_unit_descriptor, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "compression_unit_descriptor", compression_unit_descriptor ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_compression_unit_descriptor_free( &compression_unit_descriptor, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compression_unit_descriptor", compression_unit_descriptor ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_compression_unit_descriptor_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); compression_unit_descriptor = (libfsntfs_compression_unit_descriptor_t *) 0x12345678UL; result = libfsntfs_compression_unit_descriptor_initialize( &compression_unit_descriptor, &error ); compression_unit_descriptor = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_compression_unit_descriptor_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_compression_unit_descriptor_initialize( &compression_unit_descriptor, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( compression_unit_descriptor != NULL ) { libfsntfs_compression_unit_descriptor_free( &compression_unit_descriptor, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compression_unit_descriptor", compression_unit_descriptor ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_compression_unit_descriptor_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_compression_unit_descriptor_initialize( &compression_unit_descriptor, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( compression_unit_descriptor != NULL ) { libfsntfs_compression_unit_descriptor_free( &compression_unit_descriptor, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "compression_unit_descriptor", compression_unit_descriptor ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( compression_unit_descriptor != NULL ) { libfsntfs_compression_unit_descriptor_free( &compression_unit_descriptor, NULL ); } return( 0 ); } /* Tests the libfsntfs_compression_unit_descriptor_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_compression_unit_descriptor_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_compression_unit_descriptor_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_compression_unit_descriptor_initialize", fsntfs_test_compression_unit_descriptor_initialize ); FSNTFS_TEST_RUN( "libfsntfs_compression_unit_descriptor_free", fsntfs_test_compression_unit_descriptor_free ); /* TODO: add tests for libfsntfs_compression_unit_descriptor_append_data_segment */ /* TODO: add tests for libfsntfs_compression_unit_descriptor_print */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_data_run.c ================================================ /* * Library data_run type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfdata.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_data_run.h" #include "../libfsntfs/libfsntfs_io_handle.h" uint8_t fsntfs_test_data_run_data1[ 6 ] = { 0x11, 0x03, 0x37, 0x01, 0x0d, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_data_run_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_data_run_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_data_run_t *data_run = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_data_run_initialize( &data_run, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "data_run", data_run ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_data_run_free( &data_run, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "data_run", data_run ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_data_run_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); data_run = (libfsntfs_data_run_t *) 0x12345678UL; result = libfsntfs_data_run_initialize( &data_run, &error ); data_run = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_data_run_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_data_run_initialize( &data_run, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( data_run != NULL ) { libfsntfs_data_run_free( &data_run, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "data_run", data_run ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_data_run_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_data_run_initialize( &data_run, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( data_run != NULL ) { libfsntfs_data_run_free( &data_run, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "data_run", data_run ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( data_run != NULL ) { libfsntfs_data_run_free( &data_run, NULL ); } return( 0 ); } /* Tests the libfsntfs_data_run_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_data_run_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_data_run_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_data_run_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_data_run_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_data_run_t *data_run = NULL; libfsntfs_io_handle_t *io_handle = NULL; ssize_t read_count = 0; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_data_run_initialize( &data_run, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "data_run", data_run ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ read_count = libfsntfs_data_run_read_data( data_run, io_handle, fsntfs_test_data_run_data1, 6, data_run->cluster_block_number, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) 3 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); FSNTFS_TEST_ASSERT_EQUAL_UINT64( "data_run->cluster_block_number", data_run->cluster_block_number, (uint64_t) 55 ); FSNTFS_TEST_ASSERT_EQUAL_UINT64( "data_run->start_offset", (uint64_t) data_run->start_offset, (uint64_t) 55 * 4096 ); FSNTFS_TEST_ASSERT_EQUAL_UINT64( "data_run->size", (uint64_t) data_run->size, (uint64_t) 12288 ); FSNTFS_TEST_ASSERT_EQUAL_UINT32( "data_run->range_flags", (uint32_t) data_run->range_flags, (uint32_t) 0 ); read_count = libfsntfs_data_run_read_data( data_run, io_handle, &( fsntfs_test_data_run_data1[ 3 ] ), 6 - 3, data_run->cluster_block_number, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) 2 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); FSNTFS_TEST_ASSERT_EQUAL_UINT64( "data_run->cluster_block_number", data_run->cluster_block_number, (uint64_t) 0 ); FSNTFS_TEST_ASSERT_EQUAL_UINT64( "data_run->start_offset", (uint64_t) data_run->start_offset, (uint64_t) 0 ); FSNTFS_TEST_ASSERT_EQUAL_UINT64( "data_run->size", (uint64_t) data_run->size, (uint64_t) 53248 ); FSNTFS_TEST_ASSERT_EQUAL_UINT32( "data_run->range_flags", (uint32_t) data_run->range_flags, (uint32_t) LIBFDATA_RANGE_FLAG_IS_SPARSE ); read_count = libfsntfs_data_run_read_data( data_run, io_handle, &( fsntfs_test_data_run_data1[ 5 ] ), 6 - 5, data_run->cluster_block_number, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); FSNTFS_TEST_ASSERT_EQUAL_UINT64( "data_run->cluster_block_number", data_run->cluster_block_number, (uint64_t) 0 ); FSNTFS_TEST_ASSERT_EQUAL_UINT64( "data_run->start_offset", (uint64_t) data_run->start_offset, (uint64_t) 0 ); FSNTFS_TEST_ASSERT_EQUAL_UINT64( "data_run->size", (uint64_t) data_run->size, (uint64_t) 0 ); FSNTFS_TEST_ASSERT_EQUAL_UINT32( "data_run->range_flags", (uint32_t) data_run->range_flags, (uint32_t) 0 ); /* Test error cases */ read_count = libfsntfs_data_run_read_data( NULL, io_handle, fsntfs_test_data_run_data1, 6, data_run->cluster_block_number, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_data_run_read_data( data_run, NULL, fsntfs_test_data_run_data1, 6, data_run->cluster_block_number, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_data_run_read_data( data_run, io_handle, NULL, 6, data_run->cluster_block_number, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_data_run_read_data( data_run, io_handle, fsntfs_test_data_run_data1, (size_t) SSIZE_MAX + 1, data_run->cluster_block_number, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_data_run_read_data( data_run, io_handle, fsntfs_test_data_run_data1, 0, data_run->cluster_block_number, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_data_run_free( &data_run, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "data_run", data_run ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( data_run != NULL ) { libfsntfs_data_run_free( &data_run, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_data_run_initialize", fsntfs_test_data_run_initialize ); FSNTFS_TEST_RUN( "libfsntfs_data_run_free", fsntfs_test_data_run_free ); FSNTFS_TEST_RUN( "libfsntfs_data_run_read_data", fsntfs_test_data_run_read_data ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_data_stream.c ================================================ /* * Library data_stream type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #if defined( HAVE_SYS_TIME_H ) #include #endif #include #include "fsntfs_test_functions.h" #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_rwlock.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_data_stream.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" /* Define to make fsntfs_test_file generate verbose output #define FSNTFS_TEST_DATA_STREAM_VERBOSE */ #define FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE 4096 uint8_t fsntfs_test_data_stream_data1[ 112 ] = { 0x80, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x01, 0x11, 0x40, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x65, 0x00, 0x64, 0x00, 0x44, 0x00, 0x61, 0x00, 0x74, 0x00, 0x61, 0x00, 0x11, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t fsntfs_test_data_stream_data2[ 24576 ] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x20, 0x20, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x45, 0x53, 0x53, 0x45, 0x52, 0x20, 0x47, 0x45, 0x4e, 0x45, 0x52, 0x41, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x2c, 0x20, 0x32, 0x39, 0x20, 0x4a, 0x75, 0x6e, 0x65, 0x20, 0x32, 0x30, 0x30, 0x37, 0x0a, 0x0a, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x43, 0x29, 0x20, 0x32, 0x30, 0x30, 0x37, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x20, 0x3c, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x66, 0x73, 0x66, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x3e, 0x0a, 0x20, 0x45, 0x76, 0x65, 0x72, 0x79, 0x6f, 0x6e, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x72, 0x62, 0x61, 0x74, 0x69, 0x6d, 0x20, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x0a, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x73, 0x0a, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x0a, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x64, 0x20, 0x62, 0x65, 0x6c, 0x6f, 0x77, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x30, 0x2e, 0x20, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x41, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x2c, 0x20, 0x22, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x0a, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x22, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x22, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x0a, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x22, 0x54, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x22, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x0a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x61, 0x73, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x65, 0x6c, 0x6f, 0x77, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x41, 0x6e, 0x20, 0x22, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x73, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x0a, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x20, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x0a, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x73, 0x75, 0x62, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x69, 0x73, 0x20, 0x64, 0x65, 0x65, 0x6d, 0x65, 0x64, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x0a, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x41, 0x20, 0x22, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x22, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x22, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x0a, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x22, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x2c, 0x20, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x0a, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x73, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x72, 0x65, 0x0a, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x22, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x74, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x73, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x31, 0x2e, 0x20, 0x45, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x33, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x34, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x62, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x32, 0x2e, 0x20, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x49, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x0a, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x74, 0x68, 0x61, 0x74, 0x20, 0x75, 0x73, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x28, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x29, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x0a, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x29, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x61, 0x69, 0x74, 0x68, 0x20, 0x65, 0x66, 0x66, 0x6f, 0x72, 0x74, 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x77, 0x68, 0x61, 0x74, 0x65, 0x76, 0x65, 0x72, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x73, 0x20, 0x70, 0x75, 0x72, 0x70, 0x6f, 0x73, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x69, 0x6e, 0x67, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x6f, 0x72, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x29, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x33, 0x2e, 0x20, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x0a, 0x61, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x20, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x0a, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x64, 0x0a, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x0a, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x73, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x0a, 0x28, 0x74, 0x65, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x66, 0x65, 0x77, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x29, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x29, 0x20, 0x47, 0x69, 0x76, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x73, 0x20, 0x75, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x29, 0x20, 0x41, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x34, 0x2e, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x0a, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x20, 0x64, 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x0a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x64, 0x6f, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x0a, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x29, 0x20, 0x47, 0x69, 0x76, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x73, 0x20, 0x75, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x29, 0x20, 0x41, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x29, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x73, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x73, 0x20, 0x64, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x64, 0x29, 0x20, 0x44, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x29, 0x20, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x75, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x36, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x29, 0x20, 0x55, 0x73, 0x65, 0x20, 0x61, 0x20, 0x73, 0x75, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x20, 0x20, 0x41, 0x20, 0x73, 0x75, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x20, 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x28, 0x61, 0x29, 0x20, 0x75, 0x73, 0x65, 0x73, 0x20, 0x61, 0x74, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x27, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x28, 0x62, 0x29, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x6c, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x65, 0x29, 0x20, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x36, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x6e, 0x65, 0x63, 0x65, 0x73, 0x73, 0x61, 0x72, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x28, 0x49, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x34, 0x64, 0x30, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x0a, 0x20, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x34, 0x64, 0x31, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x36, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x50, 0x4c, 0x0a, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x35, 0x2e, 0x20, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x73, 0x69, 0x64, 0x65, 0x20, 0x62, 0x79, 0x20, 0x73, 0x69, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x0a, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x0a, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x0a, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x29, 0x20, 0x41, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x62, 0x61, 0x73, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x66, 0x61, 0x63, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x79, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x62, 0x29, 0x20, 0x47, 0x69, 0x76, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x36, 0x2e, 0x20, 0x52, 0x65, 0x76, 0x69, 0x73, 0x65, 0x64, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20, 0x72, 0x65, 0x76, 0x69, 0x73, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, 0x6e, 0x65, 0x77, 0x0a, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x69, 0x6d, 0x69, 0x6c, 0x61, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x70, 0x69, 0x72, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6d, 0x61, 0x79, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x20, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x45, 0x61, 0x63, 0x68, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x20, 0x64, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x63, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x22, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x0a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x79, 0x20, 0x61, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x0a, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x68, 0x6f, 0x6f, 0x73, 0x65, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x0a, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x65, 0x76, 0x65, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x61, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x0a, 0x77, 0x68, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, 0x20, 0x4c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x27, 0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x0a, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x68, 0x6f, 0x6f, 0x73, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_data_stream_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_data_stream_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_data_stream_t *data_stream = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 3; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_data_stream_data1, 112, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_data_stream_initialize( &data_stream, io_handle, NULL, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "data_stream", data_stream ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_data_stream_free( &data_stream, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "data_stream", data_stream ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_data_stream_initialize( NULL, io_handle, NULL, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); data_stream = (libfsntfs_data_stream_t *) 0x12345678UL; result = libfsntfs_data_stream_initialize( &data_stream, io_handle, NULL, mft_attribute, &error ); data_stream = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_data_stream_initialize( &data_stream, NULL, NULL, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_data_stream_initialize( &data_stream, io_handle, NULL, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_data_stream_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_data_stream_initialize( &data_stream, io_handle, NULL, mft_attribute, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( data_stream != NULL ) { libfsntfs_data_stream_free( &data_stream, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "data_stream", data_stream ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_data_stream_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_data_stream_initialize( &data_stream, io_handle, NULL, mft_attribute, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( data_stream != NULL ) { libfsntfs_data_stream_free( &data_stream, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "data_stream", data_stream ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( data_stream != NULL ) { libfsntfs_data_stream_free( &data_stream, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* Tests the libfsntfs_data_stream_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_data_stream_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_data_stream_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_data_stream_get_utf8_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_data_stream_get_utf8_name_size( libfsntfs_data_stream_t *data_stream ) { libcerror_error_t *error = NULL; size_t utf8_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_data_stream_get_utf8_name_size( data_stream, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf8_name_size", utf8_name_size, (size_t) 18 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_data_stream_get_utf8_name_size( NULL, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_data_stream_get_utf8_name_size( data_stream, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_data_stream_get_utf8_name_size with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_data_stream_get_utf8_name_size( data_stream, &utf8_name_size, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_data_stream_get_utf8_name_size with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_data_stream_get_utf8_name_size( data_stream, &utf8_name_size, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_data_stream_get_utf8_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_data_stream_get_utf8_name( libfsntfs_data_stream_t *data_stream ) { uint8_t utf8_name[ 32 ]; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_data_stream_get_utf8_name( data_stream, utf8_name, 32, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_data_stream_get_utf8_name( NULL, utf8_name, 32, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_data_stream_get_utf8_name( data_stream, NULL, 32, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_data_stream_get_utf8_name( data_stream, utf8_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_data_stream_get_utf8_name( data_stream, utf8_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_data_stream_get_utf8_name with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_data_stream_get_utf8_name( data_stream, utf8_name, 32, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_data_stream_get_utf8_name with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_data_stream_get_utf8_name( data_stream, utf8_name, 32, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_data_stream_get_utf16_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_data_stream_get_utf16_name_size( libfsntfs_data_stream_t *data_stream ) { libcerror_error_t *error = NULL; size_t utf16_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_data_stream_get_utf16_name_size( data_stream, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf16_name_size", utf16_name_size, (size_t) 18 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_data_stream_get_utf16_name_size( NULL, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_data_stream_get_utf16_name_size( data_stream, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_data_stream_get_utf16_name_size with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_data_stream_get_utf16_name_size( data_stream, &utf16_name_size, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_data_stream_get_utf16_name_size with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_data_stream_get_utf16_name_size( data_stream, &utf16_name_size, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_data_stream_get_utf16_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_data_stream_get_utf16_name( libfsntfs_data_stream_t *data_stream ) { uint16_t utf16_name[ 32 ]; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_data_stream_get_utf16_name( data_stream, utf16_name, 32, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_data_stream_get_utf16_name( NULL, utf16_name, 32, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_data_stream_get_utf16_name( data_stream, NULL, 32, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_data_stream_get_utf16_name( data_stream, utf16_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_data_stream_get_utf16_name( data_stream, utf16_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_data_stream_get_utf16_name with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_data_stream_get_utf16_name( data_stream, utf16_name, 32, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_data_stream_get_utf16_name with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_data_stream_get_utf16_name( data_stream, utf16_name, 32, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_data_stream_read_buffer function * Returns 1 if successful or 0 if not */ int fsntfs_test_data_stream_read_buffer( libfsntfs_data_stream_t *data_stream ) { uint8_t buffer[ FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE ]; libcerror_error_t *error = NULL; time_t timestamp = 0; size64_t data_size = 0; size64_t remaining_data_size = 0; size_t read_size = 0; ssize_t read_count = 0; off64_t offset = 0; off64_t read_offset = 0; int number_of_tests = 1024; int random_number = 0; int result = 0; int test_number = 0; /* Determine size */ result = libfsntfs_data_stream_get_size( data_stream, &data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Reset offset to 0 */ offset = libfsntfs_data_stream_seek_offset( data_stream, 0, SEEK_SET, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ read_size = FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE; if( data_size < FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE ) { read_size = (size_t) data_size; } read_count = libfsntfs_data_stream_read_buffer( data_stream, buffer, FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) read_size ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); if( data_size > 8 ) { /* Set offset to data_size - 8 */ offset = libfsntfs_data_stream_seek_offset( data_stream, -8, SEEK_END, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) data_size - 8 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Read buffer on data_size boundary */ read_count = libfsntfs_data_stream_read_buffer( data_stream, buffer, FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) 8 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Read buffer beyond data_size boundary */ read_count = libfsntfs_data_stream_read_buffer( data_stream, buffer, FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } /* Stress test read buffer */ timestamp = time( NULL ); srand( (unsigned int) timestamp ); offset = libfsntfs_data_stream_seek_offset( data_stream, 0, SEEK_SET, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); remaining_data_size = data_size; for( test_number = 0; test_number < number_of_tests; test_number++ ) { random_number = rand(); FSNTFS_TEST_ASSERT_GREATER_THAN_INT( "random_number", random_number, -1 ); read_size = (size_t) random_number % FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE; #if defined( FSNTFS_TEST_DATA_STREAM_VERBOSE ) fprintf( stdout, "libfsntfs_data_stream_read_buffer: at offset: %" PRIi64 " (0x%08" PRIx64 ") of size: %" PRIzd "\n", read_offset, read_offset, read_size ); #endif read_count = libfsntfs_data_stream_read_buffer( data_stream, buffer, read_size, &error ); if( read_size > remaining_data_size ) { read_size = (size_t) remaining_data_size; } FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) read_size ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); read_offset += read_count; result = libfsntfs_data_stream_get_offset( data_stream, &offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, read_offset ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); remaining_data_size -= read_count; if( remaining_data_size == 0 ) { offset = libfsntfs_data_stream_seek_offset( data_stream, 0, SEEK_SET, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); read_offset = 0; remaining_data_size = data_size; } } /* Reset offset to 0 */ offset = libfsntfs_data_stream_seek_offset( data_stream, 0, SEEK_SET, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ read_count = libfsntfs_data_stream_read_buffer( NULL, buffer, FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_data_stream_read_buffer( data_stream, NULL, FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_data_stream_read_buffer( data_stream, buffer, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_data_stream_read_buffer with pthread_rwlock_wrlock failing in libcthreads_read_write_lock_grab_for_write */ fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = 0; read_count = libfsntfs_data_stream_read_buffer( data_stream, buffer, FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE, &error ); if( fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_data_stream_read_buffer with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_write */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; read_count = libfsntfs_data_stream_read_buffer( data_stream, buffer, FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_data_stream_read_buffer_at_offset function * Returns 1 if successful or 0 if not */ int fsntfs_test_data_stream_read_buffer_at_offset( libfsntfs_data_stream_t *data_stream ) { uint8_t buffer[ FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE ]; libcerror_error_t *error = NULL; time_t timestamp = 0; size64_t data_size = 0; size64_t remaining_data_size = 0; size_t read_size = 0; ssize_t read_count = 0; off64_t offset = 0; off64_t read_offset = 0; int number_of_tests = 1024; int random_number = 0; int result = 0; int test_number = 0; /* Determine size */ result = libfsntfs_data_stream_get_size( data_stream, &data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ read_size = FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE; if( data_size < FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE ) { read_size = (size_t) data_size; } read_count = libfsntfs_data_stream_read_buffer_at_offset( data_stream, buffer, FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) read_size ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); if( data_size > 8 ) { /* Read buffer on data_size boundary */ read_count = libfsntfs_data_stream_read_buffer_at_offset( data_stream, buffer, FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE, data_size - 8, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) 8 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Read buffer beyond data_size boundary */ read_count = libfsntfs_data_stream_read_buffer_at_offset( data_stream, buffer, FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE, data_size + 8, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } /* Stress test read buffer */ timestamp = time( NULL ); srand( (unsigned int) timestamp ); for( test_number = 0; test_number < number_of_tests; test_number++ ) { random_number = rand(); FSNTFS_TEST_ASSERT_GREATER_THAN_INT( "random_number", random_number, -1 ); if( data_size > 0 ) { read_offset = (off64_t) random_number % data_size; } read_size = (size_t) random_number % FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE; #if defined( FSNTFS_TEST_DATA_STREAM_VERBOSE ) fprintf( stdout, "libfsntfs_data_stream_read_buffer_at_offset: at offset: %" PRIi64 " (0x%08" PRIx64 ") of size: %" PRIzd "\n", read_offset, read_offset, read_size ); #endif read_count = libfsntfs_data_stream_read_buffer_at_offset( data_stream, buffer, read_size, read_offset, &error ); remaining_data_size = data_size - read_offset; if( read_size > remaining_data_size ) { read_size = (size_t) remaining_data_size; } FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) read_size ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); read_offset += read_count; result = libfsntfs_data_stream_get_offset( data_stream, &offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, read_offset ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } /* Test error cases */ read_count = libfsntfs_data_stream_read_buffer_at_offset( NULL, buffer, FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_data_stream_read_buffer_at_offset( data_stream, NULL, FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_data_stream_read_buffer_at_offset( data_stream, buffer, (size_t) SSIZE_MAX + 1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_data_stream_read_buffer_at_offset( data_stream, buffer, FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE, -1, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_data_stream_read_buffer_at_offset with pthread_rwlock_wrlock failing in libcthreads_read_write_lock_grab_for_write */ fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = 0; read_count = libfsntfs_data_stream_read_buffer_at_offset( data_stream, buffer, FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE, 0, &error ); if( fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_data_stream_read_buffer_at_offset with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_write */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; read_count = libfsntfs_data_stream_read_buffer_at_offset( data_stream, buffer, FSNTFS_TEST_DATA_STREAM_READ_BUFFER_SIZE, 0, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_data_stream_seek_offset function * Returns 1 if successful or 0 if not */ int fsntfs_test_data_stream_seek_offset( libfsntfs_data_stream_t *data_stream ) { libcerror_error_t *error = NULL; size64_t size = 0; off64_t offset = 0; /* Test regular cases */ offset = libfsntfs_data_stream_seek_offset( data_stream, 0, SEEK_END, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); size = (size64_t) offset; offset = libfsntfs_data_stream_seek_offset( data_stream, 1024, SEEK_SET, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 1024 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); offset = libfsntfs_data_stream_seek_offset( data_stream, -512, SEEK_CUR, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 512 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); offset = libfsntfs_data_stream_seek_offset( data_stream, (off64_t) ( size + 512 ), SEEK_SET, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) ( size + 512 ) ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Reset offset to 0 */ offset = libfsntfs_data_stream_seek_offset( data_stream, 0, SEEK_SET, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ offset = libfsntfs_data_stream_seek_offset( NULL, 0, SEEK_SET, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); offset = libfsntfs_data_stream_seek_offset( data_stream, -1, SEEK_SET, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); offset = libfsntfs_data_stream_seek_offset( data_stream, -1, SEEK_CUR, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); offset = libfsntfs_data_stream_seek_offset( data_stream, (off64_t) ( -1 * ( size + 1 ) ), SEEK_END, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_data_stream_seek_offset with pthread_rwlock_wrlock failing in libcthreads_read_write_lock_grab_for_write */ fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = 0; offset = libfsntfs_data_stream_seek_offset( data_stream, 0, SEEK_SET, &error ); if( fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", (int64_t) offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_data_stream_seek_offset with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_write */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; offset = libfsntfs_data_stream_seek_offset( data_stream, 0, SEEK_SET, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", (int64_t) offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_data_stream_get_offset function * Returns 1 if successful or 0 if not */ int fsntfs_test_data_stream_get_offset( libfsntfs_data_stream_t *data_stream ) { libcerror_error_t *error = NULL; off64_t offset = 0; int result = 0; /* Test regular cases */ result = libfsntfs_data_stream_get_offset( data_stream, &offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_data_stream_get_offset( NULL, &offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_data_stream_get_offset( data_stream, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_data_stream_get_offset with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_data_stream_get_offset( data_stream, &offset, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_data_stream_get_offset with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_data_stream_get_offset( data_stream, &offset, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_data_stream_get_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_data_stream_get_size( libfsntfs_data_stream_t *data_stream ) { libcerror_error_t *error = NULL; size64_t size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_data_stream_get_size( data_stream, &size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_data_stream_get_size( NULL, &size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_data_stream_get_size( data_stream, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_data_stream_get_size with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_data_stream_get_size( data_stream, &size, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_data_stream_get_size with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_data_stream_get_size( data_stream, &size, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_data_stream_get_number_of_extents function * Returns 1 if successful or 0 if not */ int fsntfs_test_data_stream_get_number_of_extents( libfsntfs_data_stream_t *data_stream ) { libcerror_error_t *error = NULL; int number_of_extents = 0; int result = 0; /* Test regular cases */ result = libfsntfs_data_stream_get_number_of_extents( data_stream, &number_of_extents, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "number_of_extents", number_of_extents, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_data_stream_get_number_of_extents( NULL, &number_of_extents, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_data_stream_get_number_of_extents( data_stream, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_data_stream_get_number_of_extents with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_data_stream_get_number_of_extents( data_stream, &number_of_extents, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_data_stream_get_number_of_extents with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_data_stream_get_number_of_extents( data_stream, &number_of_extents, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_data_stream_get_extent_by_index function * Returns 1 if successful or 0 if not */ int fsntfs_test_data_stream_get_extent_by_index( libfsntfs_data_stream_t *data_stream ) { libcerror_error_t *error = NULL; size64_t extent_size = 0; off64_t extent_offset = 0; uint32_t extent_flags = 0; int result = 0; /* Test regular cases */ result = libfsntfs_data_stream_get_extent_by_index( data_stream, 0, &extent_offset, &extent_size, &extent_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_data_stream_get_extent_by_index( NULL, 0, &extent_offset, &extent_size, &extent_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_data_stream_get_extent_by_index( data_stream, -1, &extent_offset, &extent_size, &extent_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_data_stream_get_extent_by_index( data_stream, 0, NULL, &extent_size, &extent_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_data_stream_get_extent_by_index( data_stream, 0, &extent_offset, NULL, &extent_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_data_stream_get_extent_by_index( data_stream, 0, &extent_offset, &extent_size, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_data_stream_get_extent_by_index with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_data_stream_get_extent_by_index( data_stream, 0, &extent_offset, &extent_size, &extent_flags, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_data_stream_get_extent_by_index with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_data_stream_get_extent_by_index( data_stream, 0, &extent_offset, &extent_size, &extent_flags, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_data_stream_t *data_stream = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; #endif FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( HAVE_DEBUG_OUTPUT ) && defined( FSNTFS_TEST_DATA_STREAM_VERBOSE ) libfsntfs_notify_set_verbose( 1 ); libfsntfs_notify_set_stream( stderr, NULL ); #endif #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_data_stream_initialize", fsntfs_test_data_stream_initialize ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_RUN( "libfsntfs_data_stream_free", fsntfs_test_data_stream_free ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize data stream for tests */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_data_stream_data1, 112, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_data_stream_data2, 24576, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_data_stream_initialize( &data_stream, io_handle, file_io_handle, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "data_stream", data_stream ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_data_stream_get_utf8_name_size", fsntfs_test_data_stream_get_utf8_name_size, data_stream ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_data_stream_get_utf8_name", fsntfs_test_data_stream_get_utf8_name, data_stream ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_data_stream_get_utf16_name_size", fsntfs_test_data_stream_get_utf16_name_size, data_stream ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_data_stream_get_utf16_name", fsntfs_test_data_stream_get_utf16_name, data_stream ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_data_stream_read_buffer", fsntfs_test_data_stream_read_buffer, data_stream ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_data_stream_read_buffer_at_offset", fsntfs_test_data_stream_read_buffer_at_offset, data_stream ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_data_stream_seek_offset", fsntfs_test_data_stream_seek_offset, data_stream ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_data_stream_get_offset", fsntfs_test_data_stream_get_offset, data_stream ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_data_stream_get_size", fsntfs_test_data_stream_get_size, data_stream ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_data_stream_get_number_of_extents", fsntfs_test_data_stream_get_number_of_extents, data_stream ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_data_stream_get_extent_by_index", fsntfs_test_data_stream_get_extent_by_index, data_stream ); /* Clean up */ result = libfsntfs_data_stream_free( &data_stream, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "data_stream", data_stream ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); on_error: #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) if( error != NULL ) { libcerror_error_free( &error ); } if( data_stream != NULL ) { libfsntfs_data_stream_free( &data_stream, &error ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, &error ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_FAILURE ); } ================================================ FILE: tests/fsntfs_test_directory_entries_tree.c ================================================ /* * Library directory_entries_tree type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_definitions.h" #include "../libfsntfs/libfsntfs_directory_entries_tree.h" #include "../libfsntfs/libfsntfs_directory_entry.h" #include "../libfsntfs/libfsntfs_index.h" #include "../libfsntfs/libfsntfs_index_node.h" #include "../libfsntfs/libfsntfs_index_value.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_entry.h" #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_directory_entries_tree_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entries_tree_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_directory_entries_tree_t *directory_entries_tree = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_directory_entries_tree_initialize( &directory_entries_tree, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "directory_entries_tree", directory_entries_tree ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_directory_entries_tree_free( &directory_entries_tree, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "directory_entries_tree", directory_entries_tree ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_directory_entries_tree_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); directory_entries_tree = (libfsntfs_directory_entries_tree_t *) 0x12345678UL; result = libfsntfs_directory_entries_tree_initialize( &directory_entries_tree, &error ); directory_entries_tree = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_directory_entries_tree_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_directory_entries_tree_initialize( &directory_entries_tree, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( directory_entries_tree != NULL ) { libfsntfs_directory_entries_tree_free( &directory_entries_tree, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "directory_entries_tree", directory_entries_tree ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_directory_entries_tree_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_directory_entries_tree_initialize( &directory_entries_tree, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( directory_entries_tree != NULL ) { libfsntfs_directory_entries_tree_free( &directory_entries_tree, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "directory_entries_tree", directory_entries_tree ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( directory_entries_tree != NULL ) { libfsntfs_directory_entries_tree_free( &directory_entries_tree, NULL ); } return( 0 ); } /* Tests the libfsntfs_directory_entries_tree_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entries_tree_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_directory_entries_tree_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_directory_entries_tree_insert_index_value function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entries_tree_insert_index_value( void ) { libcerror_error_t *error = NULL; libfsntfs_directory_entries_tree_t *directory_entries_tree = NULL; libfsntfs_index_value_t *index_value = NULL; int result = 0; /* Initialize test */ result = libfsntfs_directory_entries_tree_initialize( &directory_entries_tree, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "directory_entries_tree", directory_entries_tree ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ /* TODO implement */ /* Test error cases */ result = libfsntfs_directory_entries_tree_insert_index_value( NULL, 0, index_value, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_insert_index_value( directory_entries_tree, 0, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_directory_entries_tree_free( &directory_entries_tree, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "directory_entries_tree", directory_entries_tree ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( directory_entries_tree != NULL ) { libfsntfs_directory_entries_tree_free( &directory_entries_tree, NULL ); } return( 0 ); } /* Tests the libfsntfs_directory_entries_tree_read_from_index_node function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entries_tree_read_from_index_node( void ) { libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_directory_entries_tree_t *directory_entries_tree = NULL; libfsntfs_index_node_t *index_node = NULL; int result = 0; /* Initialize test */ result = libfsntfs_directory_entries_tree_initialize( &directory_entries_tree, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "directory_entries_tree", directory_entries_tree ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ /* TODO implement */ /* Test error cases */ result = libfsntfs_directory_entries_tree_read_from_index_node( NULL, file_io_handle, index_node, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_read_from_index_node( directory_entries_tree, NULL, index_node, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_read_from_index_node( directory_entries_tree, file_io_handle, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_read_from_index_node( directory_entries_tree, file_io_handle, index_node, LIBFSNTFS_MAXIMUM_RECURSION_DEPTH + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_directory_entries_tree_free( &directory_entries_tree, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "directory_entries_tree", directory_entries_tree ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( directory_entries_tree != NULL ) { libfsntfs_directory_entries_tree_free( &directory_entries_tree, NULL ); } return( 0 ); } /* Tests the libfsntfs_directory_entries_tree_read_from_i30_index function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entries_tree_read_from_i30_index( void ) { libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_directory_entries_tree_t *directory_entries_tree = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; int result = 0; /* Initialize test */ result = libfsntfs_directory_entries_tree_initialize( &directory_entries_tree, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "directory_entries_tree", directory_entries_tree ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ /* TODO implement */ /* TODO implement test with LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY */ /* Test error cases */ result = libfsntfs_directory_entries_tree_read_from_i30_index( NULL, io_handle, file_io_handle, mft_entry, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_read_from_i30_index( directory_entries_tree, NULL, file_io_handle, mft_entry, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_read_from_i30_index( directory_entries_tree, io_handle, NULL, mft_entry, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_read_from_i30_index( directory_entries_tree, io_handle, file_io_handle, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_directory_entries_tree_free( &directory_entries_tree, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "directory_entries_tree", directory_entries_tree ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( directory_entries_tree != NULL ) { libfsntfs_directory_entries_tree_free( &directory_entries_tree, NULL ); } return( 0 ); } /* Tests the libfsntfs_directory_entries_tree_get_number_of_entries function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entries_tree_get_number_of_entries( libfsntfs_directory_entries_tree_t *directory_entries_tree ) { libcerror_error_t *error = NULL; int number_of_entries = 0; int result = 0; /* Test regular cases */ result = libfsntfs_directory_entries_tree_get_number_of_entries( directory_entries_tree, &number_of_entries, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "number_of_entries", number_of_entries, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_directory_entries_tree_get_number_of_entries( NULL, &number_of_entries, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_get_number_of_entries( directory_entries_tree, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_directory_entries_tree_get_entry_by_index function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entries_tree_get_entry_by_index( libfsntfs_directory_entries_tree_t *directory_entries_tree ) { libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_directory_entry_t *directory_entry = NULL; int result = 0; /* Test regular cases */ /* TODO implement file IO handle result = libfsntfs_directory_entries_tree_get_entry_by_index( directory_entries_tree, file_io_handle, 0, &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); */ /* Test error cases */ result = libfsntfs_directory_entries_tree_get_entry_by_index( NULL, file_io_handle, 0, &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_get_entry_by_index( directory_entries_tree, NULL, 0, &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_get_entry_by_index( directory_entries_tree, file_io_handle, -1, &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_get_entry_by_index( directory_entries_tree, file_io_handle, 0, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entries_tree_get_entry_from_index_node_by_utf8_name( libfsntfs_directory_entries_tree_t *directory_entries_tree ) { uint8_t name[ 5 ] = { 'n', 'a', 'm', 'e', 0 }; libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_directory_entry_t *directory_entry = NULL; libfsntfs_index_node_t *index_node = NULL; int result = 0; /* Test regular cases */ /* TODO implement file IO handle result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name( directory_entries_tree, file_io_handle, index_node, name, 4, &directory_entry, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); */ /* Test error cases */ result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name( NULL, file_io_handle, index_node, name, 4, &directory_entry, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name( directory_entries_tree, NULL, index_node, name, 4, &directory_entry, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name( directory_entries_tree, file_io_handle, NULL, name, 4, &directory_entry, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name( directory_entries_tree, file_io_handle, index_node, NULL, 4, &directory_entry, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name( directory_entries_tree, file_io_handle, index_node, name, (size_t) SSIZE_MAX + 1, &directory_entry, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name( directory_entries_tree, file_io_handle, index_node, name, 4, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name( directory_entries_tree, file_io_handle, index_node, name, 4, &directory_entry, LIBFSNTFS_MAXIMUM_RECURSION_DEPTH + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_directory_entries_tree_get_entry_by_utf8_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entries_tree_get_entry_by_utf8_name( libfsntfs_directory_entries_tree_t *directory_entries_tree ) { uint8_t name[ 5 ] = { 'n', 'a', 'm', 'e', 0 }; libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_directory_entry_t *directory_entry = NULL; libfsntfs_index_t *i30_index = NULL; int result = 0; /* Test regular cases */ /* TODO implement file IO handle result = libfsntfs_directory_entries_tree_get_entry_by_utf8_name( directory_entries_tree, file_io_handle, name, 4, &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); */ /* Test error cases */ result = libfsntfs_directory_entries_tree_get_entry_by_utf8_name( NULL, file_io_handle, name, 4, &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); i30_index = directory_entries_tree->i30_index; directory_entries_tree->i30_index = NULL; result = libfsntfs_directory_entries_tree_get_entry_by_utf8_name( directory_entries_tree, file_io_handle, name, 4, &directory_entry, &error ); directory_entries_tree->i30_index = i30_index; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_get_entry_by_utf8_name( directory_entries_tree, file_io_handle, name, 4, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entries_tree_get_entry_from_index_node_by_utf16_name( libfsntfs_directory_entries_tree_t *directory_entries_tree ) { uint16_t name[ 5 ] = { 'n', 'a', 'm', 'e', 0 }; libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_directory_entry_t *directory_entry = NULL; libfsntfs_index_node_t *index_node = NULL; int result = 0; /* Test regular cases */ /* TODO implement file IO handle result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name( directory_entries_tree, file_io_handle, index_node, name, 4, &directory_entry, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); */ /* Test error cases */ result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name( NULL, file_io_handle, index_node, name, 4, &directory_entry, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name( directory_entries_tree, NULL, index_node, name, 4, &directory_entry, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name( directory_entries_tree, file_io_handle, NULL, name, 4, &directory_entry, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name( directory_entries_tree, file_io_handle, index_node, NULL, 4, &directory_entry, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name( directory_entries_tree, file_io_handle, index_node, name, (size_t) SSIZE_MAX + 1, &directory_entry, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name( directory_entries_tree, file_io_handle, index_node, name, 4, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name( directory_entries_tree, file_io_handle, index_node, name, 4, &directory_entry, LIBFSNTFS_MAXIMUM_RECURSION_DEPTH + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_directory_entries_tree_get_entry_by_utf16_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entries_tree_get_entry_by_utf16_name( libfsntfs_directory_entries_tree_t *directory_entries_tree ) { uint16_t name[ 5 ] = { 'n', 'a', 'm', 'e', 0 }; libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_directory_entry_t *directory_entry = NULL; libfsntfs_index_t *i30_index = NULL; int result = 0; /* Test regular cases */ /* TODO implement file IO handle result = libfsntfs_directory_entries_tree_get_entry_by_utf16_name( directory_entries_tree, file_io_handle, name, 4, &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); */ /* Test error cases */ result = libfsntfs_directory_entries_tree_get_entry_by_utf16_name( NULL, file_io_handle, name, 4, &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); i30_index = directory_entries_tree->i30_index; directory_entries_tree->i30_index = NULL; result = libfsntfs_directory_entries_tree_get_entry_by_utf16_name( directory_entries_tree, file_io_handle, name, 4, &directory_entry, &error ); directory_entries_tree->i30_index = i30_index; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entries_tree_get_entry_by_utf16_name( directory_entries_tree, file_io_handle, name, 4, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_directory_entries_tree_t *directory_entries_tree = NULL; int result = 0; #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_directory_entries_tree_initialize", fsntfs_test_directory_entries_tree_initialize ); FSNTFS_TEST_RUN( "libfsntfs_directory_entries_tree_free", fsntfs_test_directory_entries_tree_free ); FSNTFS_TEST_RUN( "libfsntfs_directory_entries_tree_insert_index_value", fsntfs_test_directory_entries_tree_insert_index_value ); FSNTFS_TEST_RUN( "libfsntfs_directory_entries_tree_read_from_index_node", fsntfs_test_directory_entries_tree_read_from_index_node ); FSNTFS_TEST_RUN( "libfsntfs_directory_entries_tree_read_from_i30_index", fsntfs_test_directory_entries_tree_read_from_i30_index ); #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize data stream for tests */ result = libfsntfs_directory_entries_tree_initialize( &directory_entries_tree, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "directory_entries_tree", directory_entries_tree ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_directory_entries_tree_get_number_of_entries", fsntfs_test_directory_entries_tree_get_number_of_entries, directory_entries_tree ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_directory_entries_tree_get_entry_by_index", fsntfs_test_directory_entries_tree_get_entry_by_index, directory_entries_tree ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name", fsntfs_test_directory_entries_tree_get_entry_from_index_node_by_utf8_name, directory_entries_tree ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_directory_entries_tree_get_entry_by_utf8_name", fsntfs_test_directory_entries_tree_get_entry_by_utf8_name, directory_entries_tree ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name", fsntfs_test_directory_entries_tree_get_entry_from_index_node_by_utf16_name, directory_entries_tree ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_directory_entries_tree_get_entry_by_utf16_name", fsntfs_test_directory_entries_tree_get_entry_by_utf16_name, directory_entries_tree ); /* TODO add tests for libfsntfs_directory_entries_tree_read_element_data */ /* Clean up */ result = libfsntfs_directory_entries_tree_free( &directory_entries_tree, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "directory_entries_tree", directory_entries_tree ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( directory_entries_tree != NULL ) { libfsntfs_directory_entries_tree_free( &directory_entries_tree, NULL ); } return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_directory_entry.c ================================================ /* * Library directory_entry type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcdata.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_directory_entry.h" #include "../libfsntfs/libfsntfs_file_name_values.h" uint8_t fsntfs_test_directory_entry_data1[ 74 ] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x24, 0x00, 0x4d, 0x00, 0x46, 0x00, 0x54, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_directory_entry_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entry_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_directory_entry_t *directory_entry = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_directory_entry_initialize( &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "directory_entry", directory_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_directory_entry_free( &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "directory_entry", directory_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_directory_entry_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); directory_entry = (libfsntfs_directory_entry_t *) 0x12345678UL; result = libfsntfs_directory_entry_initialize( &directory_entry, &error ); directory_entry = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_directory_entry_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_directory_entry_initialize( &directory_entry, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( directory_entry != NULL ) { libfsntfs_directory_entry_free( &directory_entry, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "directory_entry", directory_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_directory_entry_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_directory_entry_initialize( &directory_entry, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( directory_entry != NULL ) { libfsntfs_directory_entry_free( &directory_entry, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "directory_entry", directory_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( directory_entry != NULL ) { libfsntfs_directory_entry_free( &directory_entry, NULL ); } return( 0 ); } /* Tests the libfsntfs_directory_entry_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entry_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_directory_entry_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_directory_entry_clone function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entry_clone( void ) { libcerror_error_t *error = NULL; libfsntfs_directory_entry_t *destination_directory_entry = NULL; libfsntfs_directory_entry_t *source_directory_entry = NULL; int result = 0; /* Initialize test */ result = libfsntfs_directory_entry_initialize( &source_directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "source_directory_entry", source_directory_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* TODO add file name values */ /* Test regular cases */ result = libfsntfs_directory_entry_clone( &destination_directory_entry, source_directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "destination_directory_entry", destination_directory_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_directory_entry_free( &destination_directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "destination_directory_entry", destination_directory_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_directory_entry_clone( &destination_directory_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "destination_directory_entry", destination_directory_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_directory_entry_clone( NULL, source_directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_directory_entry_free( &source_directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "source_directory_entry", source_directory_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( destination_directory_entry != NULL ) { libfsntfs_directory_entry_free( &destination_directory_entry, NULL ); } if( source_directory_entry != NULL ) { libfsntfs_directory_entry_free( &source_directory_entry, NULL ); } return( 0 ); } /* Tests the libfsntfs_directory_entry_compare_by_file_reference function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entry_compare_by_file_reference( void ) { libcerror_error_t *error = NULL; libfsntfs_directory_entry_t *first_directory_entry = NULL; libfsntfs_directory_entry_t *second_directory_entry = NULL; int result = 0; /* Initialize test */ result = libfsntfs_directory_entry_initialize( &first_directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "first_directory_entry", first_directory_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_directory_entry_initialize( &second_directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "second_directory_entry", second_directory_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_directory_entry_compare_by_file_reference( first_directory_entry, second_directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBCDATA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_directory_entry_compare_by_file_reference( NULL, second_directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entry_compare_by_file_reference( first_directory_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_directory_entry_free( &second_directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "second_directory_entry", second_directory_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_directory_entry_free( &first_directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "first_directory_entry", first_directory_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( second_directory_entry != NULL ) { libfsntfs_directory_entry_free( &second_directory_entry, NULL ); } if( first_directory_entry != NULL ) { libfsntfs_directory_entry_free( &first_directory_entry, NULL ); } return( 0 ); } /* Tests the libfsntfs_directory_entry_get_mft_entry_index function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entry_get_mft_entry_index( libfsntfs_directory_entry_t *directory_entry ) { libcerror_error_t *error = NULL; uint64_t mft_entry_index = 0; int result = 0; /* Test regular cases */ result = libfsntfs_directory_entry_get_mft_entry_index( directory_entry, &mft_entry_index, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_directory_entry_get_mft_entry_index( NULL, &mft_entry_index, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entry_get_mft_entry_index( directory_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_directory_entry_get_file_reference function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entry_get_file_reference( libfsntfs_directory_entry_t *directory_entry ) { libcerror_error_t *error = NULL; uint64_t file_reference = 0; int result = 0; /* Test regular cases */ result = libfsntfs_directory_entry_get_file_reference( directory_entry, &file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_directory_entry_get_file_reference( NULL, &file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entry_get_file_reference( directory_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_directory_entry_get_parent_file_reference function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entry_get_parent_file_reference( libfsntfs_directory_entry_t *directory_entry ) { libcerror_error_t *error = NULL; uint64_t parent_file_reference = 0; int result = 0; /* Test regular cases */ /* TODO initialize directory_entry with file_name_values result = libfsntfs_directory_entry_get_parent_file_reference( directory_entry, &parent_file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); */ /* Test error cases */ result = libfsntfs_directory_entry_get_parent_file_reference( NULL, &parent_file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entry_get_parent_file_reference( directory_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_directory_entry_get_utf8_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entry_get_utf8_name_size( libfsntfs_directory_entry_t *directory_entry ) { libcerror_error_t *error = NULL; size_t utf8_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_directory_entry_get_utf8_name_size( directory_entry, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_directory_entry_get_utf8_name_size( NULL, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entry_get_utf8_name_size( directory_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_directory_entry_get_utf8_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entry_get_utf8_name( libfsntfs_directory_entry_t *directory_entry ) { uint8_t utf8_name[ 16 ]; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_directory_entry_get_utf8_name( directory_entry, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_directory_entry_get_utf8_name( NULL, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entry_get_utf8_name( directory_entry, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entry_get_utf8_name( directory_entry, utf8_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entry_get_utf8_name( directory_entry, utf8_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_directory_entry_get_utf16_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entry_get_utf16_name_size( libfsntfs_directory_entry_t *directory_entry ) { libcerror_error_t *error = NULL; size_t utf16_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_directory_entry_get_utf16_name_size( directory_entry, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_directory_entry_get_utf16_name_size( NULL, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entry_get_utf16_name_size( directory_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_directory_entry_get_utf16_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_directory_entry_get_utf16_name( libfsntfs_directory_entry_t *directory_entry ) { uint16_t utf16_name[ 16 ]; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_directory_entry_get_utf16_name( directory_entry, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_directory_entry_get_utf16_name( NULL, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entry_get_utf16_name( directory_entry, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entry_get_utf16_name( directory_entry, utf16_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_directory_entry_get_utf16_name( directory_entry, utf16_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_directory_entry_t *directory_entry = NULL; int result = 0; #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_directory_entry_initialize", fsntfs_test_directory_entry_initialize ); FSNTFS_TEST_RUN( "libfsntfs_directory_entry_free", fsntfs_test_directory_entry_free ); FSNTFS_TEST_RUN( "libfsntfs_directory_entry_clone", fsntfs_test_directory_entry_clone ); FSNTFS_TEST_RUN( "libfsntfs_directory_entry_compare_by_file_reference", fsntfs_test_directory_entry_compare_by_file_reference ); #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize test */ result = libfsntfs_directory_entry_initialize( &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "directory_entry", directory_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_name_values_initialize( &( directory_entry->file_name_values ), &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "directory_entry->file_name_values", directory_entry->file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_name_values_read_data( directory_entry->file_name_values, fsntfs_test_directory_entry_data1, 74, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Run tests */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_directory_entry_get_mft_entry_index", fsntfs_test_directory_entry_get_mft_entry_index, directory_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_directory_entry_get_file_reference", fsntfs_test_directory_entry_get_file_reference, directory_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_directory_entry_get_parent_file_reference", fsntfs_test_directory_entry_get_parent_file_reference, directory_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_directory_entry_get_utf8_name_size", fsntfs_test_directory_entry_get_utf8_name_size, directory_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_directory_entry_get_utf8_name", fsntfs_test_directory_entry_get_utf8_name, directory_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_directory_entry_get_utf16_name_size", fsntfs_test_directory_entry_get_utf16_name_size, directory_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_directory_entry_get_utf16_name", fsntfs_test_directory_entry_get_utf16_name, directory_entry ); /* Clean up */ result = libfsntfs_directory_entry_free( &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "directory_entry", directory_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( directory_entry != NULL ) { libfsntfs_directory_entry_free( &directory_entry, NULL ); } return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_error.c ================================================ /* * Library error functions test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_unused.h" /* Tests the libfsntfs_error_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_error_free( void ) { /* Test invocation of function only */ libfsntfs_error_free( NULL ); return( 1 ); } /* Tests the libfsntfs_error_fprint function * Returns 1 if successful or 0 if not */ int fsntfs_test_error_fprint( void ) { /* Test invocation of function only */ libfsntfs_error_fprint( NULL, NULL ); return( 1 ); } /* Tests the libfsntfs_error_sprint function * Returns 1 if successful or 0 if not */ int fsntfs_test_error_sprint( void ) { /* Test invocation of function only */ libfsntfs_error_sprint( NULL, NULL, 0 ); return( 1 ); } /* Tests the libfsntfs_error_backtrace_fprint function * Returns 1 if successful or 0 if not */ int fsntfs_test_error_backtrace_fprint( void ) { /* Test invocation of function only */ libfsntfs_error_backtrace_fprint( NULL, NULL ); return( 1 ); } /* Tests the libfsntfs_error_backtrace_sprint function * Returns 1 if successful or 0 if not */ int fsntfs_test_error_backtrace_sprint( void ) { /* Test invocation of function only */ libfsntfs_error_backtrace_sprint( NULL, NULL, 0 ); return( 1 ); } /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) FSNTFS_TEST_RUN( "libfsntfs_error_free", fsntfs_test_error_free ); FSNTFS_TEST_RUN( "libfsntfs_error_fprint", fsntfs_test_error_fprint ); FSNTFS_TEST_RUN( "libfsntfs_error_sprint", fsntfs_test_error_sprint ); FSNTFS_TEST_RUN( "libfsntfs_error_backtrace_fprint", fsntfs_test_error_backtrace_fprint ); FSNTFS_TEST_RUN( "libfsntfs_error_backtrace_sprint", fsntfs_test_error_backtrace_sprint ); return( EXIT_SUCCESS ); on_error: return( EXIT_FAILURE ); } ================================================ FILE: tests/fsntfs_test_extent.c ================================================ /* * Library extent type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_extent.h" #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_extent_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_extent_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_extent_t *extent = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_extent_initialize( &extent, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "extent", extent ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_extent_free( &extent, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "extent", extent ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_extent_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); extent = (libfsntfs_extent_t *) 0x12345678UL; result = libfsntfs_extent_initialize( &extent, &error ); extent = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_extent_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_extent_initialize( &extent, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( extent != NULL ) { libfsntfs_extent_free( &extent, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "extent", extent ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_extent_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_extent_initialize( &extent, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( extent != NULL ) { libfsntfs_extent_free( &extent, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "extent", extent ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( extent != NULL ) { libfsntfs_extent_free( &extent, NULL ); } return( 0 ); } /* Tests the libfsntfs_extent_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_extent_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_extent_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_extent_get_values function * Returns 1 if successful or 0 if not */ int fsntfs_test_extent_get_values( void ) { libcerror_error_t *error = NULL; libfsntfs_extent_t *extent = NULL; size64_t extent_size = 0; off64_t extent_offset = 0; uint32_t extent_flags = 0; int result = 0; /* Initialize test */ result = libfsntfs_extent_initialize( &extent, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "extent", extent ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_extent_get_values( extent, &extent_offset, &extent_size, &extent_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_extent_get_values( NULL, &extent_offset, &extent_size, &extent_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_extent_get_values( extent, NULL, &extent_size, &extent_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_extent_get_values( extent, &extent_offset, NULL, &extent_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_extent_get_values( extent, &extent_offset, &extent_size, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_extent_free( &extent, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "extent", extent ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_extent_initialize", fsntfs_test_extent_initialize ); FSNTFS_TEST_RUN( "libfsntfs_extent_free", fsntfs_test_extent_free ); FSNTFS_TEST_RUN( "libfsntfs_extent_get_values", fsntfs_test_extent_get_values ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_file_entry.c ================================================ /* * Library file_entry type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #if defined( HAVE_SYS_TIME_H ) #include #endif #include #include "fsntfs_test_functions.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_rwlock.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_attribute.h" #include "../libfsntfs/libfsntfs_definitions.h" #include "../libfsntfs/libfsntfs_directory_entry.h" #include "../libfsntfs/libfsntfs_file_entry.h" #include "../libfsntfs/libfsntfs_file_name_values.h" #include "../libfsntfs/libfsntfs_file_system.h" #include "../libfsntfs/libfsntfs_io_handle.h" /* Define to make fsntfs_test_file generate verbose output #define FSNTFS_TEST_FILE_ENTRY_VERBOSE */ #define FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE 4096 uint8_t fsntfs_test_file_entry_data1[ 16384 ] = { 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0xb7, 0x4e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0xa8, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x24, 0x00, 0x4d, 0x00, 0x46, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0xf9, 0x00, 0x21, 0x01, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, 0xfa, 0x00, 0x21, 0x3c, 0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0xf9, 0x00, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0xfd, 0x4e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x58, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x52, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x24, 0x00, 0x4d, 0x00, 0x46, 0x00, 0x54, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x72, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x43, 0x4f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x60, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x52, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x24, 0x00, 0x4c, 0x00, 0x6f, 0x00, 0x67, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x80, 0x01, 0xfe, 0x00, 0x22, 0x80, 0x00, 0x7b, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x80, 0x01, 0xfe, 0x00, 0x22, 0x80, 0x00, 0x7b, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0xc0, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x78, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x50, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x56, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x56, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x56, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0xa2, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x52, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x24, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x44, 0x00, 0x65, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x64, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x80, 0x48, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x89, 0x00, 0x12, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x89, 0x00, 0x12, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x39, 0x64, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x38, 0x00, 0x03, 0x00, 0xb8, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x80, 0xf8, 0x0d, 0x5e, 0xeb, 0xa4, 0xd4, 0x01, 0x80, 0xf8, 0x0d, 0x5e, 0xeb, 0xa4, 0xd4, 0x01, 0x80, 0xf8, 0x0d, 0x5e, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x80, 0xcc, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb8, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xff, 0x01, 0x1f, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xff, 0x01, 0x1f, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xbf, 0x01, 0x13, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x14, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xa9, 0x00, 0x12, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x18, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x00, 0x06, 0x00, 0x38, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x49, 0x00, 0x33, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x49, 0x00, 0x33, 0x00, 0x30, 0x00, 0x11, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x49, 0x00, 0x33, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x89, 0x4f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x50, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x50, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x42, 0x00, 0x69, 0x00, 0x74, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x70, 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x7e, 0x02, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x7e, 0x02, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x24, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x64, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x80, 0x48, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x89, 0x00, 0x12, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x89, 0x00, 0x12, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0xcf, 0x4f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x78, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x52, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x24, 0x00, 0x42, 0x00, 0x61, 0x00, 0x64, 0x00, 0x43, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x42, 0x00, 0x61, 0x00, 0x64, 0x00, 0x02, 0xef, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x42, 0x00, 0x61, 0x00, 0x64, 0x00, 0x02, 0xef, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x7c, 0x63, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x38, 0x00, 0x09, 0x00, 0xb8, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0xfe, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x50, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x53, 0x00, 0x65, 0x00, 0x63, 0x00, 0x75, 0x00, 0x72, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x53, 0x00, 0x44, 0x00, 0x53, 0x00, 0x11, 0x41, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x38, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x53, 0x00, 0x44, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x70, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x53, 0x00, 0x49, 0x00, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xcb, 0xc6, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0xf7, 0xc8, 0x14, 0x34, 0x01, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x19, 0x22, 0x76, 0x20, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x14, 0x38, 0x78, 0x2c, 0x03, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0xda, 0xc7, 0x23, 0x87, 0x04, 0x01, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0xb5, 0x87, 0xd3, 0x23, 0x05, 0x01, 0x00, 0x00, 0x50, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x62, 0x9b, 0xa3, 0x0a, 0x06, 0x01, 0x00, 0x00, 0xb0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0xf5, 0x06, 0xd3, 0x23, 0x07, 0x01, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x53, 0x00, 0x44, 0x00, 0x48, 0x00, 0x11, 0x01, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x53, 0x00, 0x44, 0x00, 0x48, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x6c, 0x51, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x98, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x50, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x55, 0x00, 0x70, 0x00, 0x43, 0x00, 0x61, 0x00, 0x73, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x24, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x69, 0x1b, 0x6b, 0x77, 0x7e, 0xdc, 0xda, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x24, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x69, 0x1b, 0x6b, 0x77, 0x7e, 0xdc, 0xda, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0xe0, 0x50, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x38, 0x00, 0x03, 0x00, 0x50, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x45, 0x00, 0x78, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x90, 0x00, 0x00, 0x00, 0x48, 0x02, 0x00, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x28, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x49, 0x00, 0x33, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x24, 0x00, 0x44, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x74, 0x00, 0x65, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x60, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x24, 0x00, 0x4f, 0x00, 0x02, 0x00, 0x6a, 0x00, 0x49, 0x00, 0x64, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x60, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x24, 0x00, 0x51, 0x00, 0x75, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x61, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x24, 0x00, 0x52, 0x00, 0x65, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x73, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x24, 0x00, 0x52, 0x00, 0x6d, 0x00, 0x4d, 0x00, 0x65, 0x00, 0x74, 0x00, 0x61, 0x00, 0x64, 0x00, 0x61, 0x00, 0x74, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x24, 0x00, 0x52, 0x00, 0x6d, 0x00, 0x4d, 0x00, 0x65, 0x00, 0x74, 0x00, 0x61, 0x00, 0x64, 0x00, 0x61, 0x00, 0x74, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x80, 0x48, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x9f, 0x01, 0x12, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x9f, 0x01, 0x12, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x80, 0x48, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x9f, 0x01, 0x12, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x9f, 0x01, 0x12, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x80, 0x48, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x9f, 0x01, 0x12, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x9f, 0x01, 0x12, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x80, 0x48, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x9f, 0x01, 0x12, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x9f, 0x01, 0x12, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 }; uint8_t fsntfs_test_file_entry_data2[ 74 ] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x24, 0x00, 0x4d, 0x00, 0x46, 0x00, 0x54, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_file_entry_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_initialize( void ) { libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_file_entry_t *file_entry = NULL; libfsntfs_file_system_t *file_system = NULL; libfsntfs_io_handle_t *io_handle = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; io_handle->mft_entry_size = 1024; result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_file_entry_data1, 16384, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_system_initialize( &file_system, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_system", file_system ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_system_read_mft( file_system, io_handle, file_io_handle, 0, LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_file_entry_initialize( &file_entry, io_handle, file_io_handle, file_system, LIBFSNTFS_MFT_ENTRY_INDEX_MFT, NULL, LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_entry_free( &file_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_initialize( NULL, io_handle, file_io_handle, file_system, LIBFSNTFS_MFT_ENTRY_INDEX_MFT, NULL, LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); file_entry = (libfsntfs_file_entry_t *) 0x12345678UL; result = libfsntfs_file_entry_initialize( &file_entry, io_handle, file_io_handle, file_system, LIBFSNTFS_MFT_ENTRY_INDEX_MFT, NULL, LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY, &error ); file_entry = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_initialize( &file_entry, NULL, file_io_handle, file_system, LIBFSNTFS_MFT_ENTRY_INDEX_MFT, NULL, LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_initialize( &file_entry, io_handle, file_io_handle, NULL, LIBFSNTFS_MFT_ENTRY_INDEX_MFT, NULL, LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_initialize( &file_entry, io_handle, file_io_handle, file_system, (uint64_t) -1, NULL, LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_file_entry_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_file_entry_initialize( &file_entry, io_handle, file_io_handle, file_system, LIBFSNTFS_MFT_ENTRY_INDEX_MFT, NULL, LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( file_entry != NULL ) { libfsntfs_file_entry_free( &file_entry, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_file_entry_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_file_entry_initialize( &file_entry, io_handle, file_io_handle, file_system, LIBFSNTFS_MFT_ENTRY_INDEX_MFT, NULL, LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( file_entry != NULL ) { libfsntfs_file_entry_free( &file_entry, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_file_system_free( &file_system, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_system", file_system ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_entry != NULL ) { libfsntfs_file_entry_free( &file_entry, NULL ); } if( file_system != NULL ) { libfsntfs_file_system_free( &file_system, NULL ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* Tests the libfsntfs_file_entry_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_file_entry_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_is_empty function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_is_empty( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_is_empty( file_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_is_empty( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); mft_entry = ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry; ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry = NULL; result = libfsntfs_file_entry_is_empty( file_entry, &error ); ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry = mft_entry; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_is_empty with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_is_empty( file_entry, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_is_empty with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_is_empty( file_entry, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_is_allocated function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_is_allocated( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_is_allocated( file_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_is_allocated( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); mft_entry = ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry; ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry = NULL; result = libfsntfs_file_entry_is_allocated( file_entry, &error ); ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry = mft_entry; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_is_allocated with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_is_allocated( file_entry, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_is_allocated with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_is_allocated( file_entry, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_internal_file_entry_get_attribute_by_index function * Returns 1 if successful or 0 if not */ int fsntfs_test_internal_file_entry_get_attribute_by_index( libfsntfs_internal_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; libfsntfs_attribute_t *attribute = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_internal_file_entry_get_attribute_by_index( (libfsntfs_internal_file_entry_t *) file_entry, ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry, 0, &attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_attribute_free( &attribute, &error ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute", attribute ); /* Test error cases */ result = libfsntfs_internal_file_entry_get_attribute_by_index( NULL, ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry, 0, &attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_internal_file_entry_get_attribute_by_index( (libfsntfs_internal_file_entry_t *) file_entry, NULL, 0, &attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_internal_file_entry_get_attribute_by_index( (libfsntfs_internal_file_entry_t *) file_entry, ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry, -1, &attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_internal_file_entry_get_attribute_by_index( (libfsntfs_internal_file_entry_t *) file_entry, ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry, 0, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* TODO: add tests for libfsntfs_internal_file_entry_get_reparse_point_attribute */ /* TODO: add tests for libfsntfs_internal_file_entry_get_security_descriptor_attribute */ /* TODO: add tests for libfsntfs_internal_file_entry_get_standard_information_attribute */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* Tests the libfsntfs_file_entry_get_file_reference function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_file_reference( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; uint64_t file_reference = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_file_reference( file_entry, &file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_file_reference( NULL, &file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_file_reference( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_file_reference with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_file_reference( file_entry, &file_reference, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_file_reference with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_file_reference( file_entry, &file_reference, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_base_record_file_reference function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_base_record_file_reference( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; uint64_t base_record_file_reference = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_base_record_file_reference( file_entry, &base_record_file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_base_record_file_reference( NULL, &base_record_file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_base_record_file_reference( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_base_record_file_reference with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_base_record_file_reference( file_entry, &base_record_file_reference, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_base_record_file_reference with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_base_record_file_reference( file_entry, &base_record_file_reference, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_parent_file_reference function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_parent_file_reference( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; uint64_t parent_file_reference = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_parent_file_reference( file_entry, &parent_file_reference, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_parent_file_reference( NULL, &parent_file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_parent_file_reference( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_parent_file_reference with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_parent_file_reference( file_entry, &parent_file_reference, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_parent_file_reference with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_parent_file_reference( file_entry, &parent_file_reference, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_parent_file_reference_by_attribute_index function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_parent_file_reference_by_attribute_index( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; uint64_t parent_file_reference = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_parent_file_reference_by_attribute_index( file_entry, 1, &parent_file_reference, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_parent_file_reference_by_attribute_index( NULL, 1, &parent_file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_parent_file_reference_by_attribute_index( file_entry, -1, &parent_file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_parent_file_reference_by_attribute_index( file_entry, 1, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_parent_file_reference_by_attribute_index( file_entry, 0, &parent_file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_parent_file_reference_by_attribute_index with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_parent_file_reference_by_attribute_index( file_entry, 1, &parent_file_reference, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_parent_file_reference_by_attribute_index with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_parent_file_reference_by_attribute_index( file_entry, 1, &parent_file_reference, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_journal_sequence_number function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_journal_sequence_number( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; uint64_t journal_sequence_number = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_journal_sequence_number( file_entry, &journal_sequence_number, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_journal_sequence_number( NULL, &journal_sequence_number, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_journal_sequence_number( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_journal_sequence_number with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_journal_sequence_number( file_entry, &journal_sequence_number, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_journal_sequence_number with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_journal_sequence_number( file_entry, &journal_sequence_number, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_creation_time function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_creation_time( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; uint64_t creation_time = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_creation_time( file_entry, &creation_time, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_creation_time( NULL, &creation_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_creation_time( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_creation_time with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_creation_time( file_entry, &creation_time, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_creation_time with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_creation_time( file_entry, &creation_time, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_modification_time function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_modification_time( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; uint64_t modification_time = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_modification_time( file_entry, &modification_time, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_modification_time( NULL, &modification_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_modification_time( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_modification_time with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_modification_time( file_entry, &modification_time, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_modification_time with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_modification_time( file_entry, &modification_time, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_access_time function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_access_time( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; uint64_t access_time = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_access_time( file_entry, &access_time, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_access_time( NULL, &access_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_access_time( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_access_time with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_access_time( file_entry, &access_time, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_access_time with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_access_time( file_entry, &access_time, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_entry_modification_time function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_entry_modification_time( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; uint64_t entry_modification_time = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_entry_modification_time( file_entry, &entry_modification_time, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_entry_modification_time( NULL, &entry_modification_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_entry_modification_time( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_entry_modification_time with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_entry_modification_time( file_entry, &entry_modification_time, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_entry_modification_time with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_entry_modification_time( file_entry, &entry_modification_time, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_file_attribute_flags function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_file_attribute_flags( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; uint32_t file_attribute_flags = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_file_attribute_flags( file_entry, &file_attribute_flags, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_file_attribute_flags( NULL, &file_attribute_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_file_attribute_flags( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_file_attribute_flags with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_file_attribute_flags( file_entry, &file_attribute_flags, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_file_attribute_flags with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_file_attribute_flags( file_entry, &file_attribute_flags, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_utf8_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_utf8_name_size( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; size_t utf8_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_utf8_name_size( file_entry, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf8_name_size", utf8_name_size, (size_t) 5 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_utf8_name_size( NULL, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf8_name_size( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_utf8_name_size with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf8_name_size( file_entry, &utf8_name_size, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_utf8_name_size with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf8_name_size( file_entry, &utf8_name_size, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_utf8_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_utf8_name( libfsntfs_file_entry_t *file_entry ) { uint8_t utf8_name[ 16 ]; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_utf8_name( file_entry, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_utf8_name( NULL, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf8_name( file_entry, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf8_name( file_entry, utf8_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf8_name( file_entry, utf8_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_utf8_name with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf8_name( file_entry, utf8_name, 16, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_utf8_name with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf8_name( file_entry, utf8_name, 16, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_utf16_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_utf16_name_size( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; size_t utf16_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_utf16_name_size( file_entry, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf16_name_size", utf16_name_size, (size_t) 5 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_utf16_name_size( NULL, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf16_name_size( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_utf16_name_size with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf16_name_size( file_entry, &utf16_name_size, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_utf16_name_size with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf16_name_size( file_entry, &utf16_name_size, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_utf16_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_utf16_name( libfsntfs_file_entry_t *file_entry ) { uint16_t utf16_name[ 16 ]; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_utf16_name( file_entry, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_utf16_name( NULL, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf16_name( file_entry, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf16_name( file_entry, utf16_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf16_name( file_entry, utf16_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_utf16_name with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf16_name( file_entry, utf16_name, 16, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_utf16_name with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf16_name( file_entry, utf16_name, 16, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_name_attribute_index function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_name_attribute_index( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; int attribute_index = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_name_attribute_index( file_entry, &attribute_index, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "attribute_index", attribute_index, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_name_attribute_index( NULL, &attribute_index, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_name_attribute_index( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); mft_entry = ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry; ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry = NULL; result = libfsntfs_file_entry_get_name_attribute_index( file_entry, &attribute_index, &error ); ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry = mft_entry; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* TODO implement RW lock support */ #if defined( HAVE_FSNTFS_TEST_RWLOCK ) && defined( TODO ) /* Test libfsntfs_file_entry_get_name_attribute_index with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_name_attribute_index( file_entry, &attribute_index, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_name_attribute_index with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_name_attribute_index( file_entry, &attribute_index, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_utf8_name_size_by_attribute_index function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_utf8_name_size_by_attribute_index( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; size_t utf8_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_utf8_name_size_by_attribute_index( file_entry, 1, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf8_name_size", utf8_name_size, (size_t) 5 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_utf8_name_size_by_attribute_index( NULL, 1, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf8_name_size_by_attribute_index( file_entry, -1, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf8_name_size_by_attribute_index( file_entry, 1, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf8_name_size_by_attribute_index( file_entry, 0, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_utf8_name_size_by_attribute_index with pthread_rwlock_wrlock failing in libcthreads_read_write_lock_grab_for_write */ fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf8_name_size_by_attribute_index( file_entry, 1, &utf8_name_size, &error ); if( fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_utf8_name_size_by_attribute_index with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_write */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf8_name_size_by_attribute_index( file_entry, 1, &utf8_name_size, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_utf8_name_by_attribute_index function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_utf8_name_by_attribute_index( libfsntfs_file_entry_t *file_entry ) { uint8_t utf8_name[ 16 ]; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_utf8_name_by_attribute_index( file_entry, 1, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_utf8_name_by_attribute_index( NULL, 1, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf8_name_by_attribute_index( file_entry, -1, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf8_name_by_attribute_index( file_entry, 1, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf8_name_by_attribute_index( file_entry, 1, utf8_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf8_name_by_attribute_index( file_entry, 1, utf8_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf8_name_by_attribute_index( file_entry, 0, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_utf8_name_by_attribute_index with pthread_rwlock_wrlock failing in libcthreads_read_write_lock_grab_for_write */ fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf8_name_by_attribute_index( file_entry, 1, utf8_name, 16, &error ); if( fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_utf8_name_by_attribute_index with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_write */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf8_name_by_attribute_index( file_entry, 1, utf8_name, 16, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_utf16_name_size_by_attribute_index function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_utf16_name_size_by_attribute_index( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; size_t utf16_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_utf16_name_size_by_attribute_index( file_entry, 1, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf16_name_size", utf16_name_size, (size_t) 5 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_utf16_name_size_by_attribute_index( NULL, 1, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf16_name_size_by_attribute_index( file_entry, -1, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf16_name_size_by_attribute_index( file_entry, 1, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf16_name_size_by_attribute_index( file_entry, 0, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_utf16_name_size_by_attribute_index with pthread_rwlock_wrlock failing in libcthreads_read_write_lock_grab_for_write */ fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf16_name_size_by_attribute_index( file_entry, 1, &utf16_name_size, &error ); if( fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_utf16_name_size_by_attribute_index with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_write */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf16_name_size_by_attribute_index( file_entry, 1, &utf16_name_size, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_utf16_name_by_attribute_index function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_utf16_name_by_attribute_index( libfsntfs_file_entry_t *file_entry ) { uint16_t utf16_name[ 16 ]; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_utf16_name_by_attribute_index( file_entry, 1, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_utf16_name_by_attribute_index( NULL, 1, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf16_name_by_attribute_index( file_entry, -1, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf16_name_by_attribute_index( file_entry, 1, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf16_name_by_attribute_index( file_entry, 1, utf16_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf16_name_by_attribute_index( file_entry, 1, utf16_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf16_name_by_attribute_index( file_entry, 0, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_utf16_name_by_attribute_index with pthread_rwlock_wrlock failing in libcthreads_read_write_lock_grab_for_write */ fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf16_name_by_attribute_index( file_entry, 1, utf16_name, 16, &error ); if( fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_utf16_name_by_attribute_index with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_write */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf16_name_by_attribute_index( file_entry, 1, utf16_name, 16, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_utf8_symbolic_link_target_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_utf8_symbolic_link_target_size( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; size_t utf8_string_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_utf8_symbolic_link_target_size( file_entry, &utf8_string_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_utf8_symbolic_link_target_size( NULL, &utf8_string_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); mft_entry = ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry; ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry = NULL; result = libfsntfs_file_entry_get_utf8_symbolic_link_target_size( file_entry, &utf8_string_size, &error ); ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry = mft_entry; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* TODO test with file entry that has a reparse point with a substitute name result = libfsntfs_file_entry_get_utf8_symbolic_link_target_size( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); */ #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_utf8_symbolic_link_target_size with pthread_rwlock_wrlock failing in libcthreads_read_write_lock_grab_for_write */ fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf8_symbolic_link_target_size( file_entry, &utf8_string_size, &error ); if( fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_utf8_symbolic_link_target_size with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_write */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf8_symbolic_link_target_size( file_entry, &utf8_string_size, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_utf8_symbolic_link_target function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_utf8_symbolic_link_target( libfsntfs_file_entry_t *file_entry ) { uint8_t utf8_string[ 16 ]; libcerror_error_t *error = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_utf8_symbolic_link_target( file_entry, utf8_string, 16, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_utf8_symbolic_link_target( NULL, utf8_string, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); mft_entry = ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry; ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry = NULL; result = libfsntfs_file_entry_get_utf8_symbolic_link_target( file_entry, utf8_string, 16, &error ); ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry = mft_entry; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* TODO test with file entry that has a reparse point with a substitute name result = libfsntfs_file_entry_get_utf8_symbolic_link_target( file_entry, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf8_symbolic_link_target( file_entry, utf8_string, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf8_symbolic_link_target( file_entry, utf8_string, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); */ #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_utf8_symbolic_link_target with pthread_rwlock_wrlock failing in libcthreads_read_write_lock_grab_for_write */ fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf8_symbolic_link_target( file_entry, utf8_string, 16, &error ); if( fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_utf8_symbolic_link_target with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_write */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf8_symbolic_link_target( file_entry, utf8_string, 16, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_utf16_symbolic_link_target_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_utf16_symbolic_link_target_size( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; size_t utf16_string_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_utf16_symbolic_link_target_size( file_entry, &utf16_string_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_utf16_symbolic_link_target_size( NULL, &utf16_string_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); mft_entry = ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry; ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry = NULL; result = libfsntfs_file_entry_get_utf16_symbolic_link_target_size( file_entry, &utf16_string_size, &error ); ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry = mft_entry; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* TODO test with file entry that has a reparse point with a substitute name result = libfsntfs_file_entry_get_utf16_symbolic_link_target_size( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); */ #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_utf16_symbolic_link_target_size with pthread_rwlock_wrlock failing in libcthreads_read_write_lock_grab_for_write */ fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf16_symbolic_link_target_size( file_entry, &utf16_string_size, &error ); if( fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_utf16_symbolic_link_target_size with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_write */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf16_symbolic_link_target_size( file_entry, &utf16_string_size, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_utf16_symbolic_link_target function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_utf16_symbolic_link_target( libfsntfs_file_entry_t *file_entry ) { uint16_t utf16_string[ 16 ]; libcerror_error_t *error = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_utf16_symbolic_link_target( file_entry, utf16_string, 16, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_utf16_symbolic_link_target( NULL, utf16_string, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); mft_entry = ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry; ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry = NULL; result = libfsntfs_file_entry_get_utf16_symbolic_link_target( file_entry, utf16_string, 16, &error ); ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry = mft_entry; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* TODO test with file entry that has a reparse point with a substitute name result = libfsntfs_file_entry_get_utf16_symbolic_link_target( file_entry, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf16_symbolic_link_target( file_entry, utf16_string, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_utf16_symbolic_link_target( file_entry, utf16_string, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); */ #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_utf16_symbolic_link_target with pthread_rwlock_wrlock failing in libcthreads_read_write_lock_grab_for_write */ fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf16_symbolic_link_target( file_entry, utf16_string, 16, &error ); if( fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_utf16_symbolic_link_target with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_write */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_utf16_symbolic_link_target( file_entry, utf16_string, 16, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_security_descriptor_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_security_descriptor_size( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; size_t security_descriptor_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_security_descriptor_size( file_entry, &security_descriptor_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "security_descriptor_size", security_descriptor_size, (size_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_security_descriptor_size( NULL, &security_descriptor_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* TODO test with file entry that has a security descriptor result = libfsntfs_file_entry_get_security_descriptor_size( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); */ /* TODO implement RW lock support */ #if defined( HAVE_FSNTFS_TEST_RWLOCK ) && defined( TODO ) /* Test libfsntfs_file_entry_get_security_descriptor_size with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_security_descriptor_size( file_entry, &security_descriptor_size, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_security_descriptor_size with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_security_descriptor_size( file_entry, &security_descriptor_size, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_security_descriptor function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_security_descriptor( libfsntfs_file_entry_t *file_entry ) { uint8_t security_descriptor[ 16 ]; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_security_descriptor( file_entry, security_descriptor, 16, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_security_descriptor( NULL, security_descriptor, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* TODO test with file entry that has a security descriptor result = libfsntfs_file_entry_get_security_descriptor( file_entry, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_security_descriptor( file_entry, security_descriptor, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_security_descriptor( file_entry, security_descriptor, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); */ /* TODO implement RW lock support */ #if defined( HAVE_FSNTFS_TEST_RWLOCK ) && defined( TODO ) /* Test libfsntfs_file_entry_get_security_descriptor with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_security_descriptor( file_entry, security_descriptor, 16, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_security_descriptor with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_security_descriptor( file_entry, security_descriptor, 16, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_number_of_attributes function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_number_of_attributes( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; int number_of_attributes = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_number_of_attributes( file_entry, &number_of_attributes, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "number_of_attributes", number_of_attributes, 4 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_number_of_attributes( NULL, &number_of_attributes, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_number_of_attributes( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_number_of_attributes with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_number_of_attributes( file_entry, &number_of_attributes, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_number_of_attributes with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_number_of_attributes( file_entry, &number_of_attributes, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_attribute_by_index function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_attribute_by_index( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; libfsntfs_attribute_t *attribute = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_attribute_by_index( file_entry, 0, &attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_attribute_free( &attribute, &error ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute", attribute ); /* Test error cases */ result = libfsntfs_file_entry_get_attribute_by_index( NULL, 0, &attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_attribute_by_index( file_entry, -1, &attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_attribute_by_index( file_entry, 0, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); attribute = (libfsntfs_attribute_t *) 0x12345678UL; result = libfsntfs_file_entry_get_attribute_by_index( file_entry, 0, &attribute, &error ); attribute = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_attribute_by_index with pthread_rwlock_wrlock failing in libcthreads_read_write_lock_grab_for_write */ fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_attribute_by_index( file_entry, 0, &attribute, &error ); if( fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_attribute_by_index with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_write */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_attribute_by_index( file_entry, 0, &attribute, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_has_directory_entries_index function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_has_directory_entries_index( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_has_directory_entries_index( file_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_has_directory_entries_index( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); mft_entry = ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry; ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry = NULL; result = libfsntfs_file_entry_has_directory_entries_index( file_entry, &error ); ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry = mft_entry; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_has_directory_entries_index with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_has_directory_entries_index( file_entry, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_has_directory_entries_index with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_has_directory_entries_index( file_entry, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_has_default_data_stream function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_has_default_data_stream( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_has_default_data_stream( file_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_has_default_data_stream( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); mft_entry = ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry; ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry = NULL; result = libfsntfs_file_entry_has_default_data_stream( file_entry, &error ); ( (libfsntfs_internal_file_entry_t *) file_entry )->mft_entry = mft_entry; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_has_default_data_stream with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_has_default_data_stream( file_entry, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_has_default_data_stream with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_has_default_data_stream( file_entry, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_number_of_alternate_data_streams function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_number_of_alternate_data_streams( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; int number_of_data_streams = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_number_of_alternate_data_streams( file_entry, &number_of_data_streams, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "number_of_data_streams", number_of_data_streams, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_number_of_alternate_data_streams( NULL, &number_of_data_streams, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_number_of_alternate_data_streams( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_number_of_alternate_data_streams with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_number_of_alternate_data_streams( file_entry, &number_of_data_streams, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_number_of_alternate_data_streams with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_number_of_alternate_data_streams( file_entry, &number_of_data_streams, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* TODO: add tests for libfsntfs_file_entry_get_alternate_data_stream_by_index */ /* TODO: add tests for libfsntfs_file_entry_has_alternate_data_stream_by_utf8_name */ /* TODO: add tests for libfsntfs_file_entry_has_alternate_data_stream_by_utf16_name */ /* TODO: add tests for libfsntfs_file_entry_get_alternate_data_stream_by_utf8_name */ /* TODO: add tests for libfsntfs_file_entry_get_alternate_data_stream_by_utf16_name */ /* Tests the libfsntfs_file_entry_get_number_of_sub_file_entries function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_number_of_sub_file_entries( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; int number_of_file_entries = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_number_of_sub_file_entries( file_entry, &number_of_file_entries, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "number_of_file_entries", number_of_file_entries, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_number_of_sub_file_entries( NULL, &number_of_file_entries, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_number_of_sub_file_entries( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_number_of_sub_file_entries with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_number_of_sub_file_entries( file_entry, &number_of_file_entries, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_number_of_sub_file_entries with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_number_of_sub_file_entries( file_entry, &number_of_file_entries, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* TODO: add tests for libfsntfs_file_entry_get_sub_file_entry_by_index */ /* TODO: add tests for libfsntfs_file_entry_get_sub_file_entry_by_utf8_name */ /* TODO: add tests for libfsntfs_file_entry_get_sub_file_entry_by_utf16_name */ /* Tests the libfsntfs_data_stream_read_buffer function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_read_buffer( libfsntfs_file_entry_t *file_entry ) { uint8_t buffer[ FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE ]; libcerror_error_t *error = NULL; time_t timestamp = 0; size64_t data_size = 0; size64_t remaining_data_size = 0; size_t read_size = 0; ssize_t read_count = 0; off64_t offset = 0; off64_t read_offset = 0; int number_of_tests = 1024; int random_number = 0; int result = 0; int test_number = 0; /* Determine size */ result = libfsntfs_file_entry_get_size( file_entry, &data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Reset offset to 0 */ offset = libfsntfs_file_entry_seek_offset( file_entry, 0, SEEK_SET, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ read_size = FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE; if( data_size < FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE ) { read_size = (size_t) data_size; } read_count = libfsntfs_file_entry_read_buffer( file_entry, buffer, FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) read_size ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); if( data_size > 8 ) { /* Set offset to data_size - 8 */ offset = libfsntfs_file_entry_seek_offset( file_entry, -8, SEEK_END, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) data_size - 8 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Read buffer on data_size boundary */ read_count = libfsntfs_file_entry_read_buffer( file_entry, buffer, FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) 8 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Read buffer beyond data_size boundary */ read_count = libfsntfs_file_entry_read_buffer( file_entry, buffer, FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } /* Stress test read buffer */ timestamp = time( NULL ); srand( (unsigned int) timestamp ); offset = libfsntfs_file_entry_seek_offset( file_entry, 0, SEEK_SET, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); remaining_data_size = data_size; for( test_number = 0; test_number < number_of_tests; test_number++ ) { random_number = rand(); FSNTFS_TEST_ASSERT_GREATER_THAN_INT( "random_number", random_number, -1 ); read_size = (size_t) random_number % FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE; #if defined( FSNTFS_TEST_FILE_ENTRY_VERBOSE ) fprintf( stdout, "libfsntfs_file_entry_read_buffer: at offset: %" PRIi64 " (0x%08" PRIx64 ") of size: %" PRIzd "\n", read_offset, read_offset, read_size ); #endif read_count = libfsntfs_file_entry_read_buffer( file_entry, buffer, read_size, &error ); if( read_size > remaining_data_size ) { read_size = (size_t) remaining_data_size; } FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) read_size ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); read_offset += read_count; result = libfsntfs_file_entry_get_offset( file_entry, &offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, read_offset ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); remaining_data_size -= read_count; if( remaining_data_size == 0 ) { offset = libfsntfs_file_entry_seek_offset( file_entry, 0, SEEK_SET, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); read_offset = 0; remaining_data_size = data_size; } } /* Reset offset to 0 */ offset = libfsntfs_file_entry_seek_offset( file_entry, 0, SEEK_SET, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ read_count = libfsntfs_file_entry_read_buffer( NULL, buffer, FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_file_entry_read_buffer( file_entry, NULL, FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_file_entry_read_buffer( file_entry, buffer, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_read_buffer with pthread_rwlock_wrlock failing in libcthreads_read_write_lock_grab_for_write */ fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = 0; read_count = libfsntfs_file_entry_read_buffer( file_entry, buffer, FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE, &error ); if( fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_read_buffer with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_write */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; read_count = libfsntfs_file_entry_read_buffer( file_entry, buffer, FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_read_buffer_at_offset function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_read_buffer_at_offset( libfsntfs_file_entry_t *file_entry ) { uint8_t buffer[ FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE ]; libcerror_error_t *error = NULL; time_t timestamp = 0; size64_t data_size = 0; size64_t remaining_data_size = 0; size_t read_size = 0; ssize_t read_count = 0; off64_t offset = 0; off64_t read_offset = 0; int number_of_tests = 1024; int random_number = 0; int result = 0; int test_number = 0; /* Determine size */ result = libfsntfs_file_entry_get_size( file_entry, &data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ read_size = FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE; if( data_size < FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE ) { read_size = (size_t) data_size; } read_count = libfsntfs_file_entry_read_buffer_at_offset( file_entry, buffer, FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) read_size ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); if( data_size > 8 ) { /* Read buffer on data_size boundary */ read_count = libfsntfs_file_entry_read_buffer_at_offset( file_entry, buffer, FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE, data_size - 8, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) 8 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Read buffer beyond data_size boundary */ read_count = libfsntfs_file_entry_read_buffer_at_offset( file_entry, buffer, FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE, data_size + 8, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } /* Stress test read buffer */ timestamp = time( NULL ); srand( (unsigned int) timestamp ); for( test_number = 0; test_number < number_of_tests; test_number++ ) { random_number = rand(); FSNTFS_TEST_ASSERT_GREATER_THAN_INT( "random_number", random_number, -1 ); if( data_size > 0 ) { read_offset = (off64_t) random_number % data_size; } read_size = (size_t) random_number % FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE; #if defined( FSNTFS_TEST_FILE_ENTRY_VERBOSE ) fprintf( stdout, "libfsntfs_file_entry_read_buffer_at_offset: at offset: %" PRIi64 " (0x%08" PRIx64 ") of size: %" PRIzd "\n", read_offset, read_offset, read_size ); #endif read_count = libfsntfs_file_entry_read_buffer_at_offset( file_entry, buffer, read_size, read_offset, &error ); remaining_data_size = data_size - read_offset; if( read_size > remaining_data_size ) { read_size = (size_t) remaining_data_size; } FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) read_size ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); read_offset += read_count; result = libfsntfs_file_entry_get_offset( file_entry, &offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, read_offset ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } /* Test error cases */ read_count = libfsntfs_file_entry_read_buffer_at_offset( NULL, buffer, FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_file_entry_read_buffer_at_offset( file_entry, NULL, FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_file_entry_read_buffer_at_offset( file_entry, buffer, (size_t) SSIZE_MAX + 1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_file_entry_read_buffer_at_offset( file_entry, buffer, FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE, -1, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_read_buffer_at_offset with pthread_rwlock_wrlock failing in libcthreads_read_write_lock_grab_for_write */ fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = 0; read_count = libfsntfs_file_entry_read_buffer_at_offset( file_entry, buffer, FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE, 0, &error ); if( fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_read_buffer_at_offset with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_write */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; read_count = libfsntfs_file_entry_read_buffer_at_offset( file_entry, buffer, FSNTFS_TEST_FILE_ENTRY_READ_BUFFER_SIZE, 0, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_seek_offset function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_seek_offset( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; size64_t size = 0; off64_t offset = 0; /* Test regular cases */ offset = libfsntfs_file_entry_seek_offset( file_entry, 0, SEEK_END, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); size = (size64_t) offset; offset = libfsntfs_file_entry_seek_offset( file_entry, 1024, SEEK_SET, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 1024 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); offset = libfsntfs_file_entry_seek_offset( file_entry, -512, SEEK_CUR, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 512 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); offset = libfsntfs_file_entry_seek_offset( file_entry, (off64_t) ( size + 512 ), SEEK_SET, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) ( size + 512 ) ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Reset offset to 0 */ offset = libfsntfs_file_entry_seek_offset( file_entry, 0, SEEK_SET, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ offset = libfsntfs_file_entry_seek_offset( NULL, 0, SEEK_SET, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); offset = libfsntfs_file_entry_seek_offset( file_entry, -1, SEEK_SET, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); offset = libfsntfs_file_entry_seek_offset( file_entry, -1, SEEK_CUR, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); offset = libfsntfs_file_entry_seek_offset( file_entry, (off64_t) ( -1 * ( size + 1 ) ), SEEK_END, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_seek_offset with pthread_rwlock_wrlock failing in libcthreads_read_write_lock_grab_for_write */ fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = 0; offset = libfsntfs_file_entry_seek_offset( file_entry, 0, SEEK_SET, &error ); if( fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", (int64_t) offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_seek_offset with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_write */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; offset = libfsntfs_file_entry_seek_offset( file_entry, 0, SEEK_SET, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT64( "offset", (int64_t) offset, (int64_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_offset function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_offset( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; off64_t offset = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_offset( file_entry, &offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_offset( NULL, &offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_offset( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_offset with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_offset( file_entry, &offset, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_offset with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_offset( file_entry, &offset, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_size( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; size64_t size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_size( file_entry, &size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_size( NULL, &size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_size( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_size with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_size( file_entry, &size, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_size with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_size( file_entry, &size, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_number_of_extents function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_number_of_extents( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; int number_of_extents = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_number_of_extents( file_entry, &number_of_extents, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "number_of_extents", number_of_extents, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_number_of_extents( NULL, &number_of_extents, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_number_of_extents( file_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_number_of_extents with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_number_of_extents( file_entry, &number_of_extents, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_number_of_extents with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_number_of_extents( file_entry, &number_of_extents, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_entry_get_extent_by_index function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_entry_get_extent_by_index( libfsntfs_file_entry_t *file_entry ) { libcerror_error_t *error = NULL; size64_t extent_size = 0; off64_t extent_offset = 0; uint32_t extent_flags = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_entry_get_extent_by_index( file_entry, 0, &extent_offset, &extent_size, &extent_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_entry_get_extent_by_index( NULL, 0, &extent_offset, &extent_size, &extent_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_extent_by_index( file_entry, -1, &extent_offset, &extent_size, &extent_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_extent_by_index( file_entry, 0, NULL, &extent_size, &extent_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_extent_by_index( file_entry, 0, &extent_offset, NULL, &extent_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_entry_get_extent_by_index( file_entry, 0, &extent_offset, &extent_size, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_RWLOCK ) /* Test libfsntfs_file_entry_get_extent_by_index with pthread_rwlock_rdlock failing in libcthreads_read_write_lock_grab_for_read */ fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_extent_by_index( file_entry, 0, &extent_offset, &extent_size, &extent_flags, &error ); if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Test libfsntfs_file_entry_get_extent_by_index with pthread_rwlock_unlock failing in libcthreads_read_write_lock_release_for_read */ fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = 0; result = libfsntfs_file_entry_get_extent_by_index( file_entry, 0, &extent_offset, &extent_size, &extent_flags, &error ); if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail != -1 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_directory_entry_t *directory_entry = NULL; libfsntfs_file_entry_t *file_entry = NULL; libfsntfs_file_system_t *file_system = NULL; libfsntfs_io_handle_t *io_handle = NULL; int result = 0; #endif FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( HAVE_DEBUG_OUTPUT ) && defined( FSNTFS_TEST_FILE_ENTRY_VERBOSE ) libfsntfs_notify_set_verbose( 1 ); libfsntfs_notify_set_stream( stderr, NULL ); #endif #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_file_entry_initialize", fsntfs_test_file_entry_initialize ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_RUN( "libfsntfs_file_entry_free", fsntfs_test_file_entry_free ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize data stream for tests */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; io_handle->mft_entry_size = 1024; result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_file_entry_data1, 16384, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_system_initialize( &file_system, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_system", file_system ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_system_read_mft( file_system, io_handle, file_io_handle, 0, LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_directory_entry_initialize( &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "directory_entry", directory_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_name_values_initialize( &( directory_entry->file_name_values ), &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "directory_entry->file_name_values", directory_entry->file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_name_values_read_data( directory_entry->file_name_values, fsntfs_test_file_entry_data2, 74, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_entry_initialize( &file_entry, io_handle, file_io_handle, file_system, LIBFSNTFS_MFT_ENTRY_INDEX_MFT, directory_entry, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); directory_entry = NULL; FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_is_empty", fsntfs_test_file_entry_is_empty, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_is_allocated", fsntfs_test_file_entry_is_allocated, file_entry ); /* TODO: add tests for libfsntfs_internal_file_entry_get_attribute_by_index */ /* TODO: add tests for libfsntfs_internal_file_entry_get_reparse_point_attribute */ /* TODO: add tests for libfsntfs_internal_file_entry_get_security_descriptor_attribute */ /* TODO: add tests for libfsntfs_internal_file_entry_get_standard_information_attribute */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_file_reference", fsntfs_test_file_entry_get_file_reference, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_base_record_file_reference", fsntfs_test_file_entry_get_base_record_file_reference, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_parent_file_reference", fsntfs_test_file_entry_get_parent_file_reference, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_parent_file_reference_by_attribute_index", fsntfs_test_file_entry_get_parent_file_reference_by_attribute_index, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_journal_sequence_number", fsntfs_test_file_entry_get_journal_sequence_number, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_creation_time", fsntfs_test_file_entry_get_creation_time, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_modification_time", fsntfs_test_file_entry_get_modification_time, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_access_time", fsntfs_test_file_entry_get_access_time, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_entry_modification_time", fsntfs_test_file_entry_get_entry_modification_time, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_file_atttribute_flags", fsntfs_test_file_entry_get_file_attribute_flags, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_utf8_name_size", fsntfs_test_file_entry_get_utf8_name_size, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_utf8_name", fsntfs_test_file_entry_get_utf8_name, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_utf16_name_size", fsntfs_test_file_entry_get_utf16_name_size, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_utf16_name", fsntfs_test_file_entry_get_utf16_name, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_name_attribute_index", fsntfs_test_file_entry_get_name_attribute_index, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_utf8_name_size_by_attribute_index", fsntfs_test_file_entry_get_utf8_name_size_by_attribute_index, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_utf8_name_by_attribute_index", fsntfs_test_file_entry_get_utf8_name_by_attribute_index, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_utf16_name_size_by_attribute_index", fsntfs_test_file_entry_get_utf16_name_size_by_attribute_index, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_utf16_name_by_attribute_index", fsntfs_test_file_entry_get_utf16_name_by_attribute_index, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_utf8_symbolic_link_target_size", fsntfs_test_file_entry_get_utf8_symbolic_link_target_size, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_utf8_symbolic_link_target", fsntfs_test_file_entry_get_utf8_symbolic_link_target, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_utf16_symbolic_link_target_size", fsntfs_test_file_entry_get_utf16_symbolic_link_target_size, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_utf16_symbolic_link_target", fsntfs_test_file_entry_get_utf16_symbolic_link_target, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_security_descriptor_size", fsntfs_test_file_entry_get_security_descriptor_size, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_security_descriptor", fsntfs_test_file_entry_get_security_descriptor, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_number_of_attributes", fsntfs_test_file_entry_get_number_of_attributes, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_attribute_by_index", fsntfs_test_file_entry_get_attribute_by_index, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_has_directory_entries_index", fsntfs_test_file_entry_has_directory_entries_index, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_has_default_data_stream", fsntfs_test_file_entry_has_default_data_stream, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_number_of_alternate_data_streams", fsntfs_test_file_entry_get_number_of_alternate_data_streams, file_entry ); /* TODO: add tests for libfsntfs_file_entry_get_alternate_data_stream_by_index */ /* TODO: add tests for libfsntfs_file_entry_has_alternate_data_stream_by_utf8_name */ /* TODO: add tests for libfsntfs_file_entry_has_alternate_data_stream_by_utf16_name */ /* TODO: add tests for libfsntfs_file_entry_get_alternate_data_stream_by_utf8_name */ /* TODO: add tests for libfsntfs_file_entry_get_alternate_data_stream_by_utf16_name */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_number_of_sub_file_entries", fsntfs_test_file_entry_get_number_of_sub_file_entries, file_entry ); /* TODO: add tests for libfsntfs_file_entry_get_sub_file_entry_by_index */ /* TODO: add tests for libfsntfs_file_entry_get_sub_file_entry_by_utf8_name */ /* TODO: add tests for libfsntfs_file_entry_get_sub_file_entry_by_utf16_name */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_read_buffer", fsntfs_test_file_entry_read_buffer, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_read_buffer_at_offset", fsntfs_test_file_entry_read_buffer_at_offset, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_seek_offset", fsntfs_test_file_entry_seek_offset, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_offset", fsntfs_test_file_entry_get_offset, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_size", fsntfs_test_file_entry_get_size, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_number_of_extents", fsntfs_test_file_entry_get_number_of_extents, file_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_entry_get_extent_by_index", fsntfs_test_file_entry_get_extent_by_index, file_entry ); /* Clean up */ result = libfsntfs_file_entry_free( &file_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_system_free( &file_system, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_system", file_system ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); on_error: #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) if( error != NULL ) { libcerror_error_free( &error ); } if( file_entry != NULL ) { libfsntfs_file_entry_free( &file_entry, &error ); } if( directory_entry != NULL ) { libfsntfs_directory_entry_free( &directory_entry, NULL ); } if( file_system != NULL ) { libfsntfs_file_system_free( &file_system, &error ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_FAILURE ); } ================================================ FILE: tests/fsntfs_test_file_name_attribute.c ================================================ /* * Library file_name_attributes functions test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_attribute.h" #include "../libfsntfs/libfsntfs_file_name_attribute.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" uint8_t fsntfs_test_file_name_attribute_data1[ 104 ] = { 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x80, 0xab, 0x8a, 0x57, 0x7c, 0xad, 0xd0, 0x01, 0x80, 0xab, 0x8a, 0x57, 0x7c, 0xad, 0xd0, 0x01, 0x80, 0xab, 0x8a, 0x57, 0x7c, 0xad, 0xd0, 0x01, 0x80, 0xab, 0x8a, 0x57, 0x7c, 0xad, 0xd0, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x24, 0x00, 0x4d, 0x00, 0x46, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_file_name_attribute_get_parent_file_reference function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_attribute_get_parent_file_reference( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; uint64_t parent_file_reference = 0; uint32_t type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_attribute_get_parent_file_reference( attribute, &parent_file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_attribute_get_parent_file_reference( NULL, &parent_file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_attribute_get_parent_file_reference( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); type = ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type; ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = 0; result = libfsntfs_file_name_attribute_get_parent_file_reference( attribute, &parent_file_reference, &error ); ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = type; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_attribute_get_creation_time function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_attribute_get_creation_time( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; uint64_t creation_time = 0; uint32_t type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_attribute_get_creation_time( attribute, &creation_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_attribute_get_creation_time( NULL, &creation_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_attribute_get_creation_time( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); type = ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type; ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = 0; result = libfsntfs_file_name_attribute_get_creation_time( attribute, &creation_time, &error ); ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = type; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_attribute_get_modification_time function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_attribute_get_modification_time( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; uint64_t modification_time = 0; uint32_t type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_attribute_get_modification_time( attribute, &modification_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_attribute_get_modification_time( NULL, &modification_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_attribute_get_modification_time( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); type = ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type; ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = 0; result = libfsntfs_file_name_attribute_get_modification_time( attribute, &modification_time, &error ); ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = type; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_attribute_get_access_time function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_attribute_get_access_time( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; uint64_t access_time = 0; uint32_t type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_attribute_get_access_time( attribute, &access_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_attribute_get_access_time( NULL, &access_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_attribute_get_access_time( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); type = ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type; ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = 0; result = libfsntfs_file_name_attribute_get_access_time( attribute, &access_time, &error ); ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = type; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_attribute_get_entry_modification_time function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_attribute_get_entry_modification_time( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; uint64_t entry_modification_time = 0; uint32_t type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_attribute_get_entry_modification_time( attribute, &entry_modification_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_attribute_get_entry_modification_time( NULL, &entry_modification_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_attribute_get_entry_modification_time( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); type = ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type; ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = 0; result = libfsntfs_file_name_attribute_get_entry_modification_time( attribute, &entry_modification_time, &error ); ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = type; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_attribute_get_file_attribute_flags function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_attribute_get_file_attribute_flags( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; uint32_t file_attribute_flags = 0; uint32_t type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_attribute_get_file_attribute_flags( attribute, &file_attribute_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_attribute_get_file_attribute_flags( NULL, &file_attribute_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_attribute_get_file_attribute_flags( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); type = ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type; ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = 0; result = libfsntfs_file_name_attribute_get_file_attribute_flags( attribute, &file_attribute_flags, &error ); ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = type; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_attribute_get_utf8_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_attribute_get_utf8_name_size( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; size_t utf8_name_size = 0; uint32_t type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_attribute_get_utf8_name_size( attribute, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf8_name_size", utf8_name_size, (size_t) 5 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_attribute_get_utf8_name_size( NULL, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_attribute_get_utf8_name_size( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); type = ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type; ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = 0; result = libfsntfs_file_name_attribute_get_utf8_name_size( attribute, &utf8_name_size, &error ); ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = type; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_attribute_get_utf8_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_attribute_get_utf8_name( libfsntfs_attribute_t *attribute ) { uint8_t utf8_name[ 16 ]; libcerror_error_t *error = NULL; uint32_t type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_attribute_get_utf8_name( attribute, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_attribute_get_utf8_name( NULL, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_attribute_get_utf8_name( attribute, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_attribute_get_utf8_name( attribute, utf8_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_attribute_get_utf8_name( attribute, utf8_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); type = ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type; ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = 0; result = libfsntfs_file_name_attribute_get_utf8_name( attribute, utf8_name, 16, &error ); ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = type; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_attribute_get_utf16_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_attribute_get_utf16_name_size( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; size_t utf16_name_size = 0; uint32_t type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_attribute_get_utf16_name_size( attribute, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf16_name_size", utf16_name_size, (size_t) 5 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_attribute_get_utf16_name_size( NULL, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_attribute_get_utf16_name_size( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); type = ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type; ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = 0; result = libfsntfs_file_name_attribute_get_utf16_name_size( attribute, &utf16_name_size, &error ); ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = type; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_attribute_get_utf16_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_attribute_get_utf16_name( libfsntfs_attribute_t *attribute ) { uint16_t utf16_name[ 16 ]; libcerror_error_t *error = NULL; uint32_t type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_attribute_get_utf16_name( attribute, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_attribute_get_utf16_name( NULL, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_attribute_get_utf16_name( attribute, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_attribute_get_utf16_name( attribute, utf16_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_attribute_get_utf16_name( attribute, utf16_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); type = ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type; ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = 0; result = libfsntfs_file_name_attribute_get_utf16_name( attribute, utf16_name, 16, &error ); ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = type; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_attribute_t *attribute = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; #endif FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize attribute for tests */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_file_name_attribute_data1, 104, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_attribute_initialize( &attribute, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_internal_attribute_read_value( (libfsntfs_internal_attribute_t *) attribute, io_handle, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_attribute_get_parent_file_reference", fsntfs_test_file_name_attribute_get_parent_file_reference, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_attribute_get_creation_time", fsntfs_test_file_name_attribute_get_creation_time, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_attribute_get_modification_time", fsntfs_test_file_name_attribute_get_modification_time, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_attribute_get_access_time", fsntfs_test_file_name_attribute_get_access_time, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_attribute_get_entry_modification_time", fsntfs_test_file_name_attribute_get_entry_modification_time, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_attribute_get_file_attribute_flags", fsntfs_test_file_name_attribute_get_file_attribute_flags, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_attribute_get_utf8_name_size", fsntfs_test_file_name_attribute_get_utf8_name_size, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_attribute_get_utf8_name", fsntfs_test_file_name_attribute_get_utf8_name, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_attribute_get_utf16_name_size", fsntfs_test_file_name_attribute_get_utf16_name_size, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_attribute_get_utf16_name", fsntfs_test_file_name_attribute_get_utf16_name, attribute ); /* Clean up */ result = libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( attribute != NULL ) { libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &attribute, &error ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, &error ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_file_name_values.c ================================================ /* * Library file_name_values type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_file_name_values.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" uint8_t fsntfs_test_file_name_values_data1[ 104 ] = { 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xad, 0xca, 0xbc, 0x0c, 0xdc, 0x8e, 0xd0, 0x01, 0xad, 0xca, 0xbc, 0x0c, 0xdc, 0x8e, 0xd0, 0x01, 0xad, 0xca, 0xbc, 0x0c, 0xdc, 0x8e, 0xd0, 0x01, 0xad, 0xca, 0xbc, 0x0c, 0xdc, 0x8e, 0xd0, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x24, 0x00, 0x4d, 0x00, 0x46, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_file_name_values_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_values_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_file_name_values_t *file_name_values = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_file_name_values_initialize( &file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_name_values", file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_name_values_free( &file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_name_values", file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_values_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); file_name_values = (libfsntfs_file_name_values_t *) 0x12345678UL; result = libfsntfs_file_name_values_initialize( &file_name_values, &error ); file_name_values = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_file_name_values_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_file_name_values_initialize( &file_name_values, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( file_name_values != NULL ) { libfsntfs_file_name_values_free( &file_name_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_name_values", file_name_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_file_name_values_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_file_name_values_initialize( &file_name_values, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( file_name_values != NULL ) { libfsntfs_file_name_values_free( &file_name_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_name_values", file_name_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_name_values != NULL ) { libfsntfs_file_name_values_free( &file_name_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_file_name_values_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_values_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_file_name_values_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_values_clone function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_values_clone( void ) { uint8_t name_utf16_stream[ 10 ] = { 't', 0, 'e', 0, 's', 0, 't', 0, 0, 0 }; libcerror_error_t *error = NULL; libfsntfs_file_name_values_t *destination_file_name_values = NULL; libfsntfs_file_name_values_t *source_file_name_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_file_name_values_initialize( &source_file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "source_file_name_values", source_file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_name_values_set_name( source_file_name_values, name_utf16_stream, 10, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_file_name_values_clone( &destination_file_name_values, source_file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "destination_file_name_values", destination_file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_name_values_free( &destination_file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "destination_file_name_values", destination_file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_name_values_clone( &destination_file_name_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "destination_file_name_values", destination_file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_values_clone( NULL, source_file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); destination_file_name_values = (libfsntfs_file_name_values_t *) 0x12345678UL; result = libfsntfs_file_name_values_clone( &destination_file_name_values, source_file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); destination_file_name_values = NULL; #if defined( HAVE_FSNTFS_TEST_MEMORY ) /* Test libfsntfs_file_name_values_clone with malloc failing */ fsntfs_test_malloc_attempts_before_fail = 0; result = libfsntfs_file_name_values_clone( &destination_file_name_values, source_file_name_values, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( destination_file_name_values != NULL ) { libfsntfs_file_name_values_free( &destination_file_name_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "destination_file_name_values", destination_file_name_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #if defined( OPTIMIZATION_DISABLED ) /* Test libfsntfs_file_name_values_clone with memcpy failing */ fsntfs_test_memcpy_attempts_before_fail = 0; result = libfsntfs_file_name_values_clone( &destination_file_name_values, source_file_name_values, &error ); if( fsntfs_test_memcpy_attempts_before_fail != -1 ) { fsntfs_test_memcpy_attempts_before_fail = -1; if( destination_file_name_values != NULL ) { libfsntfs_file_name_values_free( &destination_file_name_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "destination_file_name_values", destination_file_name_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( OPTIMIZATION_DISABLED ) */ #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_file_name_values_free( &source_file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "source_file_name_values", source_file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( destination_file_name_values != NULL ) { libfsntfs_file_name_values_free( &destination_file_name_values, NULL ); } if( source_file_name_values != NULL ) { libfsntfs_file_name_values_free( &source_file_name_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_file_name_values_set_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_values_set_name( void ) { uint8_t name_utf16_stream[ 10 ] = { 't', 0, 'e', 0, 's', 0, 't', 0, 0, 0 }; libcerror_error_t *error = NULL; libfsntfs_file_name_values_t *file_name_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_file_name_values_initialize( &file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_name_values", file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_file_name_values_set_name( file_name_values, name_utf16_stream, 10, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_values_set_name( file_name_values, name_utf16_stream, 10, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_file_name_values_free( &file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_name_values", file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ result = libfsntfs_file_name_values_initialize( &file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_name_values", file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_values_set_name( NULL, name_utf16_stream, 10, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_set_name( file_name_values, NULL, 10, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_set_name( file_name_values, name_utf16_stream, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) /* Test libfsntfs_file_name_values_set_name with malloc failing */ fsntfs_test_malloc_attempts_before_fail = 0; result = libfsntfs_file_name_values_set_name( file_name_values, name_utf16_stream, 10, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #if defined( OPTIMIZATION_DISABLED ) /* Test libfsntfs_file_name_values_set_name with memcpy failing */ fsntfs_test_memcpy_attempts_before_fail = 0; result = libfsntfs_file_name_values_set_name( file_name_values, name_utf16_stream, 10, &error ); if( fsntfs_test_memcpy_attempts_before_fail != -1 ) { fsntfs_test_memcpy_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( OPTIMIZATION_DISABLED ) */ #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_file_name_values_free( &file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_name_values", file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_name_values != NULL ) { libfsntfs_file_name_values_free( &file_name_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_file_name_values_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_values_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_file_name_values_t *file_name_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_file_name_values_initialize( &file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_name_values", file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_file_name_values_read_data( file_name_values, &( fsntfs_test_file_name_values_data1[ 24 ] ), 74, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_values_read_data( file_name_values, &( fsntfs_test_file_name_values_data1[ 24 ] ), 74, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_file_name_values_free( &file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_name_values", file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ result = libfsntfs_file_name_values_initialize( &file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_name_values", file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_values_read_data( NULL, &( fsntfs_test_file_name_values_data1[ 24 ] ), 74, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_read_data( file_name_values, NULL, 74, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_read_data( file_name_values, &( fsntfs_test_file_name_values_data1[ 24 ] ), (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_read_data( file_name_values, &( fsntfs_test_file_name_values_data1[ 24 ] ), 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) /* Test libfsntfs_file_name_values_read_data with malloc failing in libfsntfs_file_name_values_set_name */ fsntfs_test_malloc_attempts_before_fail = 0; result = libfsntfs_file_name_values_read_data( file_name_values, &( fsntfs_test_file_name_values_data1[ 24 ] ), 74, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_file_name_values_free( &file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_name_values", file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_name_values != NULL ) { libfsntfs_file_name_values_free( &file_name_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_file_name_values_read_from_mft_attribute function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_values_read_from_mft_attribute( void ) { libcerror_error_t *error = NULL; libfsntfs_file_name_values_t *file_name_values = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_file_name_values_data1, 104, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_name_values_initialize( &file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_name_values", file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_file_name_values_read_from_mft_attribute( file_name_values, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_values_read_from_mft_attribute( NULL, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_read_from_mft_attribute( file_name_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_file_name_values_free( &file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_name_values", file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_name_values != NULL ) { libfsntfs_file_name_values_free( &file_name_values, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_file_name_values_get_parent_file_reference function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_values_get_parent_file_reference( libfsntfs_file_name_values_t *file_name_values ) { libcerror_error_t *error = NULL; uint64_t parent_file_reference = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_values_get_parent_file_reference( file_name_values, &parent_file_reference, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_values_get_parent_file_reference( NULL, &parent_file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_get_parent_file_reference( file_name_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_values_get_creation_time function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_values_get_creation_time( libfsntfs_file_name_values_t *file_name_values ) { libcerror_error_t *error = NULL; uint64_t creation_time = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_values_get_creation_time( file_name_values, &creation_time, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_values_get_creation_time( NULL, &creation_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_get_creation_time( file_name_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_values_get_modification_time function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_values_get_modification_time( libfsntfs_file_name_values_t *file_name_values ) { libcerror_error_t *error = NULL; uint64_t modification_time = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_values_get_modification_time( file_name_values, &modification_time, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_values_get_modification_time( NULL, &modification_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_get_modification_time( file_name_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_values_get_access_time function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_values_get_access_time( libfsntfs_file_name_values_t *file_name_values ) { libcerror_error_t *error = NULL; uint64_t access_time = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_values_get_access_time( file_name_values, &access_time, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_values_get_access_time( NULL, &access_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_get_access_time( file_name_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_values_get_entry_modification_time function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_values_get_entry_modification_time( libfsntfs_file_name_values_t *file_name_values ) { libcerror_error_t *error = NULL; uint64_t entry_modification_time = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_values_get_entry_modification_time( file_name_values, &entry_modification_time, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_values_get_entry_modification_time( NULL, &entry_modification_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_get_entry_modification_time( file_name_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_values_get_file_attribute_flags function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_values_get_file_attribute_flags( libfsntfs_file_name_values_t *file_name_values ) { libcerror_error_t *error = NULL; uint32_t file_attribute_flags = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_values_get_file_attribute_flags( file_name_values, &file_attribute_flags, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_values_get_file_attribute_flags( NULL, &file_attribute_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_get_file_attribute_flags( file_name_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_values_get_utf8_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_values_get_utf8_name_size( libfsntfs_file_name_values_t *file_name_values ) { libcerror_error_t *error = NULL; size_t utf8_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_values_get_utf8_name_size( file_name_values, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_values_get_utf8_name_size( NULL, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_get_utf8_name_size( file_name_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_values_get_utf8_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_values_get_utf8_name( libfsntfs_file_name_values_t *file_name_values ) { uint8_t utf8_name[ 16 ]; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_values_get_utf8_name( file_name_values, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_values_get_utf8_name( NULL, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_get_utf8_name( file_name_values, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_get_utf8_name( file_name_values, utf8_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_get_utf8_name( file_name_values, utf8_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_values_get_utf16_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_values_get_utf16_name_size( libfsntfs_file_name_values_t *file_name_values ) { libcerror_error_t *error = NULL; size_t utf16_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_values_get_utf16_name_size( file_name_values, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_values_get_utf16_name_size( NULL, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_get_utf16_name_size( file_name_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_name_values_get_utf16_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_name_values_get_utf16_name( libfsntfs_file_name_values_t *file_name_values ) { uint16_t utf16_name[ 16 ]; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_file_name_values_get_utf16_name( file_name_values, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_name_values_get_utf16_name( NULL, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_get_utf16_name( file_name_values, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_get_utf16_name( file_name_values, utf16_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_name_values_get_utf16_name( file_name_values, utf16_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_file_name_values_t *file_name_values = NULL; int result = 0; #endif FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_file_name_values_initialize", fsntfs_test_file_name_values_initialize ); FSNTFS_TEST_RUN( "libfsntfs_file_name_values_free", fsntfs_test_file_name_values_free ); FSNTFS_TEST_RUN( "libfsntfs_file_name_values_clone", fsntfs_test_file_name_values_clone ); FSNTFS_TEST_RUN( "libfsntfs_file_name_values_set_name", fsntfs_test_file_name_values_set_name ); FSNTFS_TEST_RUN( "libfsntfs_file_name_values_read_data", fsntfs_test_file_name_values_read_data ); FSNTFS_TEST_RUN( "libfsntfs_file_name_values_read_from_mft_attribute", fsntfs_test_file_name_values_read_from_mft_attribute ); #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize file_name_values for tests */ result = libfsntfs_file_name_values_initialize( &file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_name_values", file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_name_values_read_data( file_name_values, &( fsntfs_test_file_name_values_data1[ 24 ] ), 74, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_values_get_parent_file_reference", fsntfs_test_file_name_values_get_parent_file_reference, file_name_values ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_values_get_creation_time", fsntfs_test_file_name_values_get_creation_time, file_name_values ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_values_get_modification_time", fsntfs_test_file_name_values_get_modification_time, file_name_values ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_values_get_access_time", fsntfs_test_file_name_values_get_access_time, file_name_values ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_values_get_entry_modification_time", fsntfs_test_file_name_values_get_entry_modification_time, file_name_values ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_values_get_file_attribute_flags", fsntfs_test_file_name_values_get_file_attribute_flags, file_name_values ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_values_get_utf8_name_size", fsntfs_test_file_name_values_get_utf8_name_size, file_name_values ) FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_values_get_utf8_name", fsntfs_test_file_name_values_get_utf8_name, file_name_values ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_values_get_utf16_name_size", fsntfs_test_file_name_values_get_utf16_name_size, file_name_values ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_file_name_values_get_utf16_name", fsntfs_test_file_name_values_get_utf16_name, file_name_values ); /* Clean up */ result = libfsntfs_file_name_values_free( &file_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_name_values", file_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_name_values != NULL ) { libfsntfs_file_name_values_free( &file_name_values, NULL ); } return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_file_system.c ================================================ /* * Library file_system type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_functions.h" #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_definitions.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_file_system.h" uint8_t fsntfs_test_file_system_data1[ 16384 ] = { 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0xb7, 0x4e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0xa8, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x24, 0x00, 0x4d, 0x00, 0x46, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, 0xfa, 0x00, 0x21, 0x3c, 0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0xf9, 0x00, 0x21, 0x01, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, 0xfa, 0x00, 0x21, 0x3c, 0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0xf9, 0x00, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0xfd, 0x4e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x58, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x52, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x24, 0x00, 0x4d, 0x00, 0x46, 0x00, 0x54, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x72, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x43, 0x4f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x60, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x52, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x24, 0x00, 0x4c, 0x00, 0x6f, 0x00, 0x67, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x80, 0x01, 0xfe, 0x00, 0x22, 0x80, 0x00, 0x7b, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x80, 0x01, 0xfe, 0x00, 0x22, 0x80, 0x00, 0x7b, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0xc0, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x78, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x50, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x56, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x56, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x56, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0xa2, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x52, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x24, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x44, 0x00, 0x65, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x64, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x80, 0x48, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x89, 0x00, 0x12, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x89, 0x00, 0x12, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x39, 0x64, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x38, 0x00, 0x03, 0x00, 0xb8, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x80, 0xf8, 0x0d, 0x5e, 0xeb, 0xa4, 0xd4, 0x01, 0x80, 0xf8, 0x0d, 0x5e, 0xeb, 0xa4, 0xd4, 0x01, 0x80, 0xf8, 0x0d, 0x5e, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x80, 0xcc, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb8, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xff, 0x01, 0x1f, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xff, 0x01, 0x1f, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xbf, 0x01, 0x13, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x14, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xa9, 0x00, 0x12, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x18, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x00, 0x06, 0x00, 0x38, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x49, 0x00, 0x33, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x49, 0x00, 0x33, 0x00, 0x30, 0x00, 0x11, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x49, 0x00, 0x33, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x89, 0x4f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x50, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x50, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x42, 0x00, 0x69, 0x00, 0x74, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x70, 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x7e, 0x02, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x7e, 0x02, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x24, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x64, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x80, 0x48, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x89, 0x00, 0x12, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x89, 0x00, 0x12, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0xcf, 0x4f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x78, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x52, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x24, 0x00, 0x42, 0x00, 0x61, 0x00, 0x64, 0x00, 0x43, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x42, 0x00, 0x61, 0x00, 0x64, 0x00, 0x02, 0xef, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x42, 0x00, 0x61, 0x00, 0x64, 0x00, 0x02, 0xef, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x7c, 0x63, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x38, 0x00, 0x09, 0x00, 0xb8, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0xfe, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x50, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x53, 0x00, 0x65, 0x00, 0x63, 0x00, 0x75, 0x00, 0x72, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x53, 0x00, 0x44, 0x00, 0x53, 0x00, 0x11, 0x41, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x38, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x53, 0x00, 0x44, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x70, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x53, 0x00, 0x49, 0x00, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xcb, 0xc6, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0xf7, 0xc8, 0x14, 0x34, 0x01, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x19, 0x22, 0x76, 0x20, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x14, 0x38, 0x78, 0x2c, 0x03, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0xda, 0xc7, 0x23, 0x87, 0x04, 0x01, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0xb5, 0x87, 0xd3, 0x23, 0x05, 0x01, 0x00, 0x00, 0x50, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x62, 0x9b, 0xa3, 0x0a, 0x06, 0x01, 0x00, 0x00, 0xb0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0xf5, 0x06, 0xd3, 0x23, 0x07, 0x01, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x53, 0x00, 0x44, 0x00, 0x48, 0x00, 0x11, 0x01, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x53, 0x00, 0x44, 0x00, 0x48, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x6c, 0x51, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x98, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x50, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x55, 0x00, 0x70, 0x00, 0x43, 0x00, 0x61, 0x00, 0x73, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x24, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x69, 0x1b, 0x6b, 0x77, 0x7e, 0xdc, 0xda, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x24, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x69, 0x1b, 0x6b, 0x77, 0x7e, 0xdc, 0xda, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0xe0, 0x50, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x38, 0x00, 0x03, 0x00, 0x50, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x45, 0x00, 0x78, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x90, 0x00, 0x00, 0x00, 0x48, 0x02, 0x00, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x28, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x49, 0x00, 0x33, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x24, 0x00, 0x44, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x74, 0x00, 0x65, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x60, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x24, 0x00, 0x4f, 0x00, 0x02, 0x00, 0x6a, 0x00, 0x49, 0x00, 0x64, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x60, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x24, 0x00, 0x51, 0x00, 0x75, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x61, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x24, 0x00, 0x52, 0x00, 0x65, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x73, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x24, 0x00, 0x52, 0x00, 0x6d, 0x00, 0x4d, 0x00, 0x65, 0x00, 0x74, 0x00, 0x61, 0x00, 0x64, 0x00, 0x61, 0x00, 0x74, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x05, 0xbb, 0xa0, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x24, 0x00, 0x52, 0x00, 0x6d, 0x00, 0x4d, 0x00, 0x65, 0x00, 0x74, 0x00, 0x61, 0x00, 0x64, 0x00, 0x61, 0x00, 0x74, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x80, 0x48, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x9f, 0x01, 0x12, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x9f, 0x01, 0x12, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x80, 0x48, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x9f, 0x01, 0x12, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x9f, 0x01, 0x12, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x80, 0x48, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x9f, 0x01, 0x12, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x9f, 0x01, 0x12, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x73, 0xbc, 0x83, 0x5d, 0xeb, 0xa4, 0xd4, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x80, 0x48, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x9f, 0x01, 0x12, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x9f, 0x01, 0x12, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_file_system_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_system_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_file_system_t *file_system = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_file_system_initialize( &file_system, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_system", file_system ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_system_free( &file_system, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_system", file_system ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_system_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); file_system = (libfsntfs_file_system_t *) 0x12345678UL; result = libfsntfs_file_system_initialize( &file_system, &error ); file_system = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_file_system_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_file_system_initialize( &file_system, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( file_system != NULL ) { libfsntfs_file_system_free( &file_system, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_system", file_system ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_file_system_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_file_system_initialize( &file_system, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( file_system != NULL ) { libfsntfs_file_system_free( &file_system, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_system", file_system ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_system != NULL ) { libfsntfs_file_system_free( &file_system, NULL ); } return( 0 ); } /* Tests the libfsntfs_file_system_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_system_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_file_system_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_file_system_read_mft function * Returns 1 if successful or 0 if not */ int fsntfs_test_file_system_read_mft( void ) { libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_file_system_t *file_system = NULL; libfsntfs_io_handle_t *io_handle = NULL; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; io_handle->mft_entry_size = 1024; result = libfsntfs_file_system_initialize( &file_system, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_system", file_system ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize file IO handle */ result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_file_system_data1, 16384, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_file_system_read_mft( file_system, io_handle, file_io_handle, 0, LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_file_system_read_mft( NULL, io_handle, file_io_handle, 0, LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_system_read_mft( file_system, NULL, file_io_handle, 0, LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_system_read_mft( file_system, io_handle, NULL, 0, LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_file_system_read_mft( file_system, io_handle, file_io_handle, -1, LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up file IO handle */ result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfsntfs_file_system_free( &file_system, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_system", file_system ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } if( file_system != NULL ) { libfsntfs_file_system_free( &file_system, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_file_system_initialize", fsntfs_test_file_system_initialize ); FSNTFS_TEST_RUN( "libfsntfs_file_system_free", fsntfs_test_file_system_free ); FSNTFS_TEST_RUN( "libfsntfs_file_system_read_mft", fsntfs_test_file_system_read_mft ); /* TODO add tests for libfsntfs_file_system_read_bitmap */ /* TODO add tests for libfsntfs_file_system_read_security_descriptors */ /* TODO add tests for libfsntfs_file_system_get_number_of_mft_entries */ /* TODO add tests for libfsntfs_file_system_get_mft_entry_by_index */ /* TODO add tests for libfsntfs_file_system_get_mft_entry_by_index_no_cache */ /* TODO add tests for libfsntfs_file_system_get_security_descriptor_values_by_identifier */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_fixup_values.c ================================================ /* * Library fix-up values functions test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_fixup_values.h" uint8_t fsntfs_test_fixup_values_data1[ 1024 ] = { 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x52, 0x51, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0xa8, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x96, 0xd5, 0x86, 0xa0, 0x08, 0x60, 0xd5, 0x01, 0x96, 0xd5, 0x86, 0xa0, 0x08, 0x60, 0xd5, 0x01, 0x96, 0xd5, 0x86, 0xa0, 0x08, 0x60, 0xd5, 0x01, 0x96, 0xd5, 0x86, 0xa0, 0x08, 0x60, 0xd5, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x96, 0xd5, 0x86, 0xa0, 0x08, 0x60, 0xd5, 0x01, 0x96, 0xd5, 0x86, 0xa0, 0x08, 0x60, 0xd5, 0x01, 0x96, 0xd5, 0x86, 0xa0, 0x08, 0x60, 0xd5, 0x01, 0x96, 0xd5, 0x86, 0xa0, 0x08, 0x60, 0xd5, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x24, 0x00, 0x4d, 0x00, 0x46, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, 0xfa, 0x00, 0x21, 0x3c, 0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0xf9, 0x00, 0x21, 0x01, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, 0xfa, 0x00, 0x21, 0x3c, 0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0xf9, 0x00, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_fixup_values_apply function * Returns 1 if successful or 0 if not */ int fsntfs_test_fixup_values_apply( void ) { uint8_t mft_entry_data[ 1024 ]; libcerror_error_t *error = NULL; void *memcpy_result = NULL; int result = 0; /* Initialize test */ memcpy_result = memory_copy( mft_entry_data, fsntfs_test_fixup_values_data1, sizeof( uint8_t ) * 1024 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "memcpy_result", memcpy_result ); /* Test regular cases */ result = libfsntfs_fixup_values_apply( mft_entry_data, 1024, 48, 3, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* TODO check if fix-up values have been applied */ /* Initialize test */ memcpy_result = memory_copy( mft_entry_data, fsntfs_test_fixup_values_data1, sizeof( uint8_t ) * 1024 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "memcpy_result", memcpy_result ); /* Test error case where fix-up value is invalid */ byte_stream_copy_from_uint16_little_endian( &( mft_entry_data[ 510 ] ), 0xffff ); result = libfsntfs_fixup_values_apply( mft_entry_data, 1024, 48, 3, &error ); byte_stream_copy_from_uint16_little_endian( &( mft_entry_data[ 510 ] ), 0x0200 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* TODO check if fix-up values have been applied */ /* Initialize test */ memcpy_result = memory_copy( mft_entry_data, fsntfs_test_fixup_values_data1, sizeof( uint8_t ) * 1024 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "memcpy_result", memcpy_result ); /* Test error cases */ result = libfsntfs_fixup_values_apply( NULL, 1024, 48, 3, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_fixup_values_apply( mft_entry_data, (size_t) SSIZE_MAX + 1, 48, 3, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_fixup_values_apply( mft_entry_data, 1024, 0xffff, 3, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_fixup_values_apply( mft_entry_data, 1024, 48, 0xffff, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_fixup_values_apply", fsntfs_test_fixup_values_apply ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_functions.c ================================================ /* * Functions for testing * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libclocale.h" #include "fsntfs_test_libuna.h" /* Retrieves source as a narrow string * Returns 1 if successful or -1 on error */ int fsntfs_test_get_narrow_source( const system_character_t *source, char *narrow_string, size_t narrow_string_size, libcerror_error_t **error ) { static char *function = "fsntfs_test_get_narrow_source"; size_t narrow_source_size = 0; size_t source_length = 0; #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int result = 0; #endif if( source == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid source.", function ); return( -1 ); } if( narrow_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid narrow string.", function ); return( -1 ); } if( narrow_string_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid narrow string size value exceeds maximum.", function ); return( -1 ); } source_length = system_string_length( source ); if( source_length > (size_t) ( SSIZE_MAX - 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid source length value out of bounds.", function ); return( -1 ); } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) if( libclocale_codepage == 0 ) { #if SIZEOF_WCHAR_T == 4 result = libuna_utf8_string_size_from_utf32( (libuna_utf32_character_t *) source, source_length + 1, &narrow_source_size, error ); #elif SIZEOF_WCHAR_T == 2 result = libuna_utf8_string_size_from_utf16( (libuna_utf16_character_t *) source, source_length + 1, &narrow_source_size, error ); #endif } else { #if SIZEOF_WCHAR_T == 4 result = libuna_byte_stream_size_from_utf32( (libuna_utf32_character_t *) source, source_length + 1, libclocale_codepage, &narrow_source_size, error ); #elif SIZEOF_WCHAR_T == 2 result = libuna_byte_stream_size_from_utf16( (libuna_utf16_character_t *) source, source_length + 1, libclocale_codepage, &narrow_source_size, error ); #endif } if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_GENERIC, "%s: unable to determine narrow string size.", function ); return( -1 ); } #else narrow_source_size = source_length + 1; #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */ if( narrow_string_size < narrow_source_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: narrow string too small.", function ); return( -1 ); } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) if( libclocale_codepage == 0 ) { #if SIZEOF_WCHAR_T == 4 result = libuna_utf8_string_copy_from_utf32( (libuna_utf8_character_t *) narrow_string, narrow_string_size, (libuna_utf32_character_t *) source, source_length + 1, error ); #elif SIZEOF_WCHAR_T == 2 result = libuna_utf8_string_copy_from_utf16( (libuna_utf8_character_t *) narrow_string, narrow_string_size, (libuna_utf16_character_t *) source, source_length + 1, error ); #endif } else { #if SIZEOF_WCHAR_T == 4 result = libuna_byte_stream_copy_from_utf32( (uint8_t *) narrow_string, narrow_string_size, libclocale_codepage, (libuna_utf32_character_t *) source, source_length + 1, error ); #elif SIZEOF_WCHAR_T == 2 result = libuna_byte_stream_copy_from_utf16( (uint8_t *) narrow_string, narrow_string_size, libclocale_codepage, (libuna_utf16_character_t *) source, source_length + 1, error ); #endif } if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_GENERIC, "%s: unable to set narrow string.", function ); return( -1 ); } #else if( system_string_copy( narrow_string, source, source_length ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to set narrow string.", function ); return( -1 ); } narrow_string[ source_length ] = 0; #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */ return( 1 ); } #if defined( HAVE_WIDE_CHARACTER_TYPE ) /* Retrieves source as a wide string * Returns 1 if successful or -1 on error */ int fsntfs_test_get_wide_source( const system_character_t *source, wchar_t *wide_string, size_t wide_string_size, libcerror_error_t **error ) { static char *function = "fsntfs_test_get_wide_source"; size_t wide_source_size = 0; size_t source_length = 0; #if !defined( HAVE_WIDE_SYSTEM_CHARACTER ) int result = 0; #endif if( source == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid source.", function ); return( -1 ); } if( wide_string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid wide string.", function ); return( -1 ); } if( wide_string_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid wide string size value exceeds maximum.", function ); return( -1 ); } source_length = system_string_length( source ); if( source_length > (size_t) ( SSIZE_MAX - 1 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid source length value out of bounds.", function ); return( -1 ); } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) wide_source_size = source_length + 1; #else if( libclocale_codepage == 0 ) { #if SIZEOF_WCHAR_T == 4 result = libuna_utf32_string_size_from_utf8( (libuna_utf8_character_t *) source, source_length + 1, &wide_source_size, error ); #elif SIZEOF_WCHAR_T == 2 result = libuna_utf16_string_size_from_utf8( (libuna_utf8_character_t *) source, source_length + 1, &wide_source_size, error ); #endif } else { #if SIZEOF_WCHAR_T == 4 result = libuna_utf32_string_size_from_byte_stream( (uint8_t *) source, source_length + 1, libclocale_codepage, &wide_source_size, error ); #elif SIZEOF_WCHAR_T == 2 result = libuna_utf16_string_size_from_byte_stream( (uint8_t *) source, source_length + 1, libclocale_codepage, &wide_source_size, error ); #endif } if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_GENERIC, "%s: unable to determine wide string size.", function ); return( -1 ); } #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */ if( wide_string_size < wide_source_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, "%s: wide string too small.", function ); return( -1 ); } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) if( system_string_copy( wide_string, source, source_length ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_COPY_FAILED, "%s: unable to set wide string.", function ); return( -1 ); } wide_string[ source_length ] = 0; #else if( libclocale_codepage == 0 ) { #if SIZEOF_WCHAR_T == 4 result = libuna_utf32_string_copy_from_utf8( (libuna_utf32_character_t *) wide_string, wide_string_size, (uint8_t *) source, source_length + 1, error ); #elif SIZEOF_WCHAR_T == 2 result = libuna_utf16_string_copy_from_utf8( (libuna_utf16_character_t *) wide_string, wide_string_size, (uint8_t *) source, source_length + 1, error ); #endif } else { #if SIZEOF_WCHAR_T == 4 result = libuna_utf32_string_copy_from_byte_stream( (libuna_utf32_character_t *) wide_string, wide_string_size, (uint8_t *) source, source_length + 1, libclocale_codepage, error ); #elif SIZEOF_WCHAR_T == 2 result = libuna_utf16_string_copy_from_byte_stream( (libuna_utf16_character_t *) wide_string, wide_string_size, (uint8_t *) source, source_length + 1, libclocale_codepage, error ); #endif } if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_GENERIC, "%s: unable to set wide string.", function ); return( -1 ); } #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */ return( 1 ); } #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */ /* Copies a string of a decimal value to a 64-bit value * Returns 1 if successful or -1 on error */ int fsntfs_test_system_string_copy_from_64_bit_in_decimal( const system_character_t *string, size_t string_size, uint64_t *value_64bit, libcerror_error_t **error ) { static char *function = "fsntfs_test_system_string_copy_from_64_bit_in_decimal"; size_t string_index = 0; system_character_t character_value = 0; uint8_t maximum_string_index = 20; int8_t sign = 1; if( string == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid string.", function ); return( -1 ); } if( string_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid string size value exceeds maximum.", function ); return( -1 ); } if( value_64bit == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid value 64-bit.", function ); return( -1 ); } *value_64bit = 0; if( string[ string_index ] == (system_character_t) '-' ) { string_index++; maximum_string_index++; sign = -1; } else if( string[ string_index ] == (system_character_t) '+' ) { string_index++; maximum_string_index++; } while( string_index < string_size ) { if( string[ string_index ] == 0 ) { break; } if( string_index > (size_t) maximum_string_index ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_LARGE, "%s: string too large.", function ); return( -1 ); } *value_64bit *= 10; if( ( string[ string_index ] >= (system_character_t) '0' ) && ( string[ string_index ] <= (system_character_t) '9' ) ) { character_value = (system_character_t) ( string[ string_index ] - (system_character_t) '0' ); } else { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported character value: %" PRIc_SYSTEM " at index: %d.", function, string[ string_index ], string_index ); return( -1 ); } *value_64bit += character_value; string_index++; } if( sign == -1 ) { *value_64bit *= (uint64_t) -1; } return( 1 ); } /* Creates a file IO handle for test data * Returns 1 if successful or -1 on error */ int fsntfs_test_open_file_io_handle( libbfio_handle_t **file_io_handle, uint8_t *data, size_t data_size, libcerror_error_t **error ) { static char *function = "fsntfs_test_open_file_io_handle"; if( file_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file IO handle.", function ); return( -1 ); } if( libbfio_memory_range_initialize( file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file IO handle.", function ); goto on_error; } if( libbfio_memory_range_set( *file_io_handle, data, data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set memory range of file IO handle.", function ); goto on_error; } if( libbfio_handle_open( *file_io_handle, LIBBFIO_OPEN_READ, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open file IO handle.", function ); goto on_error; } return( 1 ); on_error: if( *file_io_handle != NULL ) { libbfio_handle_free( file_io_handle, NULL ); } return( -1 ); } /* Closes a file IO handle for test data * Returns 0 if successful or -1 on error */ int fsntfs_test_close_file_io_handle( libbfio_handle_t **file_io_handle, libcerror_error_t **error ) { static char *function = "fsntfs_test_close_file_io_handle"; int result = 0; if( file_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file IO handle.", function ); return( -1 ); } if( libbfio_handle_close( *file_io_handle, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close file IO handle.", function ); result = -1; } if( libbfio_handle_free( file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file IO handle.", function ); result = -1; } return( result ); } ================================================ FILE: tests/fsntfs_test_functions.h ================================================ /* * Functions for testing * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_TEST_FUNCTIONS_H ) #define _FSNTFS_TEST_FUNCTIONS_H #include #include #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #if defined( __cplusplus ) extern "C" { #endif int fsntfs_test_get_narrow_source( const system_character_t *source, char *narrow_string, size_t narrow_string_size, libcerror_error_t **error ); #if defined( HAVE_WIDE_CHARACTER_TYPE ) int fsntfs_test_get_wide_source( const system_character_t *source, wchar_t *wide_string, size_t wide_string_size, libcerror_error_t **error ); #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */ int fsntfs_test_system_string_copy_from_64_bit_in_decimal( const system_character_t *string, size_t string_size, uint64_t *value_64bit, libcerror_error_t **error ); int fsntfs_test_open_file_io_handle( libbfio_handle_t **file_io_handle, uint8_t *data, size_t data_size, libcerror_error_t **error ); int fsntfs_test_close_file_io_handle( libbfio_handle_t **file_io_handle, libcerror_error_t **error ); #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFS_TEST_FUNCTIONS_H ) */ ================================================ FILE: tests/fsntfs_test_getopt.c ================================================ /* * GetOpt functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_getopt.h" #include "fsntfs_test_libcnotify.h" #if !defined( HAVE_GETOPT ) /* The option index * Start with argument 1 (argument 0 is the program name) */ int optind = 1; /* The current option argument */ system_character_t *optarg = NULL; /* Value to indicate the current option */ system_integer_t optopt = 0; /* The next option in a group */ system_character_t *next_option = NULL; /* Get the program options * Function for platforms that do not have the getopt function * Returns the option character processed, or -1 on error, * ? if the option was not in the options string, : if the option argument was missing */ system_integer_t fsntfs_test_getopt( int argument_count, system_character_t * const argument_values[], const system_character_t *options_string ) { system_character_t *argument_value = NULL; system_character_t *option_value = NULL; static char *function = "fsntfs_test_getopt"; size_t options_string_length = 0; if( next_option != NULL ) { argument_value = next_option; next_option = NULL; } else if( optind >= argument_count ) { return( (system_integer_t) -1 ); } else { argument_value = argument_values[ optind ]; /* Check if the argument value is not an empty string */ if( *argument_value == (system_character_t) '\0' ) { return( (system_integer_t) -1 ); } /* Check if the first character is a option marker '-' */ if( *argument_value != (system_character_t) '-' ) { return( (system_integer_t) -1 ); } argument_value++; /* Check if long options are provided '--' */ if( *argument_value == (system_character_t) '-' ) { optind++; return( (system_integer_t) -1 ); } } options_string_length = system_string_length( options_string ); optopt = *argument_value; option_value = system_string_search_character( options_string, optopt, options_string_length ); argument_value++; /* Check if an argument was specified or that the option was not found * in the option string */ if( ( optopt == (system_integer_t) ':' ) || ( option_value == NULL ) ) { if( *argument_value == (system_character_t) '\0' ) { optind++; } if( ( *options_string != (system_character_t) ':' ) && ( optopt != (system_integer_t) '?' ) ) { libcnotify_printf( "%s: no such option: %" PRIc_SYSTEM ".\n", function, optopt ); } return( (system_integer_t) '?' ); } option_value++; /* Check if no option argument is required */ if( *option_value != (system_character_t) ':' ) { optarg = NULL; if( *argument_value == (system_character_t) '\0' ) { optind++; } else { /* Multiple options are grouped */ next_option = argument_value; } } /* Check if the argument is right after the option flag with no space in between */ else if( *argument_value != (system_character_t) '\0' ) { optarg = argument_value; optind++; } else { optind++; /* Check if the argument was provided as the next argument value */ if( argument_count <= optind ) { if( *option_value == ':' ) { return( (system_integer_t) ':' ); } libcnotify_printf( "%s: option: %" PRIc_SYSTEM " requires an argument.\n", function, optopt ); return( (system_integer_t) '?' ); } optarg = argument_values[ optind ]; optind++; } return( optopt ); } #endif /* !defined( HAVE_GETOPT ) */ ================================================ FILE: tests/fsntfs_test_getopt.h ================================================ /* * GetOpt functions * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_TEST_GETOPT_H ) #define _FSNTFS_TEST_GETOPT_H #include #include /* unistd.h is included here to export getopt, optarg, optind and optopt */ #if defined( HAVE_UNISTD_H ) #include #endif #if defined( __cplusplus ) extern "C" { #endif #if defined( HAVE_GETOPT ) #define fsntfs_test_getopt( argument_count, argument_values, options_string ) \ getopt( argument_count, argument_values, options_string ) #else #if !defined( __CYGWIN__ ) extern int optind; extern system_character_t *optarg; extern system_integer_t optopt; #else int optind; system_character_t *optarg; system_integer_t optopt; #endif /* !defined( __CYGWIN__ ) */ system_integer_t fsntfs_test_getopt( int argument_count, system_character_t * const argument_values[], const system_character_t *options_string ); #endif /* defined( HAVE_GETOPT ) */ #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFS_TEST_GETOPT_H ) */ ================================================ FILE: tests/fsntfs_test_index.c ================================================ /* * Library index type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_index.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" uint8_t fsntfs_test_index_data1[ 88 ] = { 0x90, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x04, 0x18, 0x00, 0x01, 0x00, 0x06, 0x00, 0x38, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x49, 0x00, 0x33, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_index_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_index_t *index = NULL; libfsntfs_io_handle_t *io_handle = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 3; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; /* Test regular cases */ result = libfsntfs_index_initialize( &index, io_handle, (uint8_t *) "$I30", 5, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index", index ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_index_free( &index, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index", index ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_initialize( NULL, io_handle, (uint8_t *) "$I30", 5, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); index = (libfsntfs_index_t *) 0x12345678UL; result = libfsntfs_index_initialize( &index, io_handle, (uint8_t *) "$I30", 5, &error ); index = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_initialize( &index, NULL, (uint8_t *) "$I30", 5, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_initialize( &index, io_handle, NULL, 5, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_initialize( &index, io_handle, (uint8_t *) "$I30", (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_index_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_index_initialize( &index, io_handle, (uint8_t *) "$I30", 5, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( index != NULL ) { libfsntfs_index_free( &index, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index", index ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_index_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_index_initialize( &index, io_handle, (uint8_t *) "$I30", 5, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( index != NULL ) { libfsntfs_index_free( &index, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index", index ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #if defined( OPTIMIZATION_DISABLED ) /* Test libfsntfs_index_initialize with memcpy failing */ fsntfs_test_memset_attempts_before_fail = 0; result = libfsntfs_index_initialize( &index, io_handle, (uint8_t *) "$I30", 5, &error ); if( fsntfs_test_memcpy_attempts_before_fail != -1 ) { fsntfs_test_memcpy_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index", index ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( OPTIMIZATION_DISABLED ) */ #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( index != NULL ) { libfsntfs_index_free( &index, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_index_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_index_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_index_initialize", fsntfs_test_index_initialize ); FSNTFS_TEST_RUN( "libfsntfs_index_free", fsntfs_test_index_free ); /* TODO: add tests for libfsntfs_index_read */ /* TODO: add tests for libfsntfs_index_read_root */ /* TODO: add tests for libfsntfs_index_read_bitmap */ /* TODO: add tests for libfsntfs_index_get_index_entry_size */ /* TODO: add tests for libfsntfs_index_get_attribute_type */ /* TODO: add tests for libfsntfs_index_get_collation_type */ /* TODO: add tests for libfsntfs_index_get_sub_node */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_index_entry.c ================================================ /* * Library index_entry type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_functions.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_index_entry.h" uint8_t fsntfs_test_index_entry_data1[ 4096 ] = { 0x49, 0x4e, 0x44, 0x58, 0x28, 0x00, 0x09, 0x00, 0x39, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x0a, 0x00, 0x00, 0xe8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0xd5, 0x01, 0x6c, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x68, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x24, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x44, 0x00, 0x65, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x68, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x24, 0x00, 0x42, 0x00, 0x61, 0x00, 0x64, 0x00, 0x43, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x42, 0x00, 0x69, 0x00, 0x74, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x70, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x60, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x24, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x60, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x45, 0x00, 0x78, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x68, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x24, 0x00, 0x4c, 0x00, 0x6f, 0x00, 0x67, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x60, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x24, 0x00, 0x4d, 0x00, 0x46, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x24, 0x00, 0x4d, 0x00, 0x46, 0x00, 0x54, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x72, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x60, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x53, 0x00, 0x65, 0x00, 0x63, 0x00, 0x75, 0x00, 0x72, 0x00, 0x65, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x60, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x55, 0x00, 0x70, 0x00, 0x43, 0x00, 0x61, 0x00, 0x73, 0x00, 0x65, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x60, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x56, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x58, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xc1, 0x7d, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xc1, 0x7d, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xc1, 0x7d, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x70, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x63, 0x09, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x63, 0x09, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xc1, 0x7d, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x64, 0x00, 0x69, 0x00, 0x72, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x79, 0x00, 0x5f, 0x00, 0x61, 0x00, 0x64, 0x00, 0x73, 0x00, 0x31, 0x00, 0x74, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x78, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x03, 0x00, 0x00, 0xa0, 0x13, 0x00, 0x64, 0x00, 0x69, 0x00, 0x72, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x79, 0x00, 0x5f, 0x00, 0x6a, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x31, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0x0a, 0x00, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x0c, 0x00, 0x00, 0xa0, 0x17, 0x00, 0x64, 0x00, 0x69, 0x00, 0x72, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x79, 0x00, 0x5f, 0x00, 0x73, 0x00, 0x79, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x6b, 0x00, 0x31, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xe5, 0xae, 0xac, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xe5, 0xae, 0xac, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xe5, 0xae, 0xac, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xe5, 0xae, 0xac, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x74, 0x00, 0x79, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x5f, 0x00, 0x61, 0x00, 0x64, 0x00, 0x73, 0x00, 0x31, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x70, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xe5, 0xae, 0xac, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xe5, 0xae, 0xac, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x5b, 0x14, 0xdd, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xb4, 0x6c, 0xad, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x5f, 0x00, 0x68, 0x00, 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x6b, 0x00, 0x31, 0x00, 0x6c, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x78, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x2f, 0x4e, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x2f, 0x4e, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x2f, 0x4e, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x2f, 0x4e, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xa0, 0x12, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x5f, 0x00, 0x73, 0x00, 0x79, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x6f, 0x00, 0x0a, 0x00, 0x69, 0x00, 0x63, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x6b, 0x00, 0x31, 0x00, 0x20, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa8, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb7, 0x57, 0xae, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xb7, 0x57, 0xae, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xb7, 0x57, 0xae, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xb7, 0x57, 0xae, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x4d, 0x00, 0x79, 0x00, 0x20, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x79, 0x00, 0x20, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x79, 0x00, 0x20, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x67, 0x00, 0xd5, 0x01, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x88, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xe0, 0x72, 0x6b, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xe0, 0x72, 0x6b, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xe0, 0x72, 0x6b, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xe0, 0x72, 0x6b, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x56, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xe5, 0xae, 0xac, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x2a, 0xa0, 0xd4, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x2a, 0xa0, 0xd4, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x2a, 0xa0, 0xd4, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x64, 0x00, 0x69, 0x00, 0x72, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xc1, 0x7d, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xc1, 0x7d, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xc1, 0x7d, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xc1, 0x7d, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x74, 0x00, 0x65, 0x00, 0x0a, 0x00, 0x74, 0x00, 0x64, 0x00, 0x69, 0x00, 0x72, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_index_entry_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_entry_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_index_entry_t *index_entry = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_index_entry_initialize( &index_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index_entry", index_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_index_entry_free( &index_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_entry", index_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_entry_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); index_entry = (libfsntfs_index_entry_t *) 0x12345678UL; result = libfsntfs_index_entry_initialize( &index_entry, &error ); index_entry = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_index_entry_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_index_entry_initialize( &index_entry, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( index_entry != NULL ) { libfsntfs_index_entry_free( &index_entry, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_entry", index_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_index_entry_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_index_entry_initialize( &index_entry, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( index_entry != NULL ) { libfsntfs_index_entry_free( &index_entry, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_entry", index_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( index_entry != NULL ) { libfsntfs_index_entry_free( &index_entry, NULL ); } return( 0 ); } /* Tests the libfsntfs_index_entry_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_entry_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_index_entry_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_index_entry_read_file_io_handle function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_entry_read_file_io_handle( void ) { libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_index_entry_t *index_entry = NULL; int result = 0; /* Initialize test */ result = libfsntfs_index_entry_initialize( &index_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index_entry", index_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize file IO handle */ result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_index_entry_data1, 4096, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_index_entry_read_file_io_handle( index_entry, file_io_handle, 0, 4096, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_entry_read_file_io_handle( NULL, file_io_handle, 0, 4096, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_entry_read_file_io_handle( index_entry, NULL, 0, 4096, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_entry_read_file_io_handle( index_entry, file_io_handle, -1, 4096, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up file IO handle */ result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test data too small */ result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_index_entry_data1, 8, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_index_entry_read_file_io_handle( index_entry, file_io_handle, 0, 4096, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test data invalid */ result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_index_entry_data1, 4096, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); byte_stream_copy_from_uint32_little_endian( fsntfs_test_index_entry_data1, 0xffffffffUL ); result = libfsntfs_index_entry_read_file_io_handle( index_entry, file_io_handle, 0, 4096, 0, &error ); byte_stream_copy_from_uint32_little_endian( fsntfs_test_index_entry_data1, 0x58444e49UL ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfsntfs_index_entry_free( &index_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_entry", index_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } if( index_entry != NULL ) { libfsntfs_index_entry_free( &index_entry, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_index_entry_initialize", fsntfs_test_index_entry_initialize ); FSNTFS_TEST_RUN( "libfsntfs_index_entry_free", fsntfs_test_index_entry_free ); FSNTFS_TEST_RUN( "libfsntfs_index_entry_read_file_io_handle", fsntfs_test_index_entry_read_file_io_handle ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_index_entry_header.c ================================================ /* * Library index_entry_header type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_index_entry_header.h" uint8_t fsntfs_test_index_entry_header_data1[ 24 ] = { 0x49, 0x4e, 0x44, 0x58, 0x28, 0x00, 0x09, 0x00, 0xc1, 0xa9, 0x1b, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_index_entry_header_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_entry_header_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_index_entry_header_t *index_entry_header = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_index_entry_header_initialize( &index_entry_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index_entry_header", index_entry_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_index_entry_header_free( &index_entry_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_entry_header", index_entry_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_entry_header_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); index_entry_header = (libfsntfs_index_entry_header_t *) 0x12345678UL; result = libfsntfs_index_entry_header_initialize( &index_entry_header, &error ); index_entry_header = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_index_entry_header_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_index_entry_header_initialize( &index_entry_header, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( index_entry_header != NULL ) { libfsntfs_index_entry_header_free( &index_entry_header, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_entry_header", index_entry_header ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_index_entry_header_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_index_entry_header_initialize( &index_entry_header, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( index_entry_header != NULL ) { libfsntfs_index_entry_header_free( &index_entry_header, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_entry_header", index_entry_header ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( index_entry_header != NULL ) { libfsntfs_index_entry_header_free( &index_entry_header, NULL ); } return( 0 ); } /* Tests the libfsntfs_index_entry_header_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_entry_header_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_index_entry_header_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_index_entry_header_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_entry_header_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_index_entry_header_t *index_entry_header = NULL; int result = 0; /* Initialize test */ result = libfsntfs_index_entry_header_initialize( &index_entry_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index_entry_header", index_entry_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_index_entry_header_read_data( index_entry_header, fsntfs_test_index_entry_header_data1, 24, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_entry_header_read_data( NULL, fsntfs_test_index_entry_header_data1, 24, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_entry_header_read_data( index_entry_header, NULL, 24, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_entry_header_read_data( index_entry_header, fsntfs_test_index_entry_header_data1, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_entry_header_read_data( index_entry_header, fsntfs_test_index_entry_header_data1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_index_entry_header_free( &index_entry_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_entry_header", index_entry_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( index_entry_header != NULL ) { libfsntfs_index_entry_header_free( &index_entry_header, NULL ); } return( 0 ); } /* Tests the libfsntfs_index_entry_header_get_fixup_values_offset function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_entry_header_get_fixup_values_offset( libfsntfs_index_entry_header_t *index_entry_header ) { libcerror_error_t *error = NULL; uint16_t fixup_values_offset = 0; int result = 0; /* Test regular cases */ result = libfsntfs_index_entry_header_get_fixup_values_offset( index_entry_header, &fixup_values_offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT16( "fixup_values_offset", fixup_values_offset, 40 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_entry_header_get_fixup_values_offset( NULL, &fixup_values_offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_entry_header_get_fixup_values_offset( index_entry_header, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_index_entry_header_get_number_of_fixup_values function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_entry_header_get_number_of_fixup_values( libfsntfs_index_entry_header_t *index_entry_header ) { libcerror_error_t *error = NULL; uint16_t number_of_fixup_values = 0; int result = 0; /* Test regular cases */ result = libfsntfs_index_entry_header_get_number_of_fixup_values( index_entry_header, &number_of_fixup_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT16( "number_of_fixup_values", number_of_fixup_values, 9 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_entry_header_get_number_of_fixup_values( NULL, &number_of_fixup_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_entry_header_get_number_of_fixup_values( index_entry_header, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_index_entry_header_t *index_entry_header = NULL; int result = 0; #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_index_entry_header_initialize", fsntfs_test_index_entry_header_initialize ); FSNTFS_TEST_RUN( "libfsntfs_index_entry_header_free", fsntfs_test_index_entry_header_free ); FSNTFS_TEST_RUN( "libfsntfs_index_entry_header_read_data", fsntfs_test_index_entry_header_read_data ); #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize test */ result = libfsntfs_index_entry_header_initialize( &index_entry_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index_entry_header", index_entry_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_index_entry_header_read_data( index_entry_header, fsntfs_test_index_entry_header_data1, 24, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Run tests */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_index_entry_header_get_fixup_values_offset", fsntfs_test_index_entry_header_get_fixup_values_offset, index_entry_header ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_index_entry_header_get_number_of_fixup_values", fsntfs_test_index_entry_header_get_number_of_fixup_values, index_entry_header ); /* Clean up */ result = libfsntfs_index_entry_header_free( &index_entry_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_entry_header", index_entry_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( index_entry_header != NULL ) { libfsntfs_index_entry_header_free( &index_entry_header, NULL ); } return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_index_entry_vector.c ================================================ /* * Library index_entry_vector type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_functions.h" #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfcache.h" #include "fsntfs_test_libfdata.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_index_entry_vector.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" uint8_t fsntfs_test_index_entry_vector_data1[ 72 ] = { 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t fsntfs_test_index_entry_vector_data2[ 8192 ] = { 0x49, 0x4e, 0x44, 0x58, 0x28, 0x00, 0x09, 0x00, 0x39, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x0a, 0x00, 0x00, 0xe8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0xd5, 0x01, 0x6c, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x68, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x24, 0x00, 0x41, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x44, 0x00, 0x65, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x68, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x24, 0x00, 0x42, 0x00, 0x61, 0x00, 0x64, 0x00, 0x43, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x42, 0x00, 0x69, 0x00, 0x74, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x70, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x60, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x24, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x60, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x45, 0x00, 0x78, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x68, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x24, 0x00, 0x4c, 0x00, 0x6f, 0x00, 0x67, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x60, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x24, 0x00, 0x4d, 0x00, 0x46, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x24, 0x00, 0x4d, 0x00, 0x46, 0x00, 0x54, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x72, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x60, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x53, 0x00, 0x65, 0x00, 0x63, 0x00, 0x75, 0x00, 0x72, 0x00, 0x65, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x60, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x55, 0x00, 0x70, 0x00, 0x43, 0x00, 0x61, 0x00, 0x73, 0x00, 0x65, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x60, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x24, 0x00, 0x56, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x58, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x51, 0x72, 0x11, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xc1, 0x7d, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xc1, 0x7d, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xc1, 0x7d, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x70, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x63, 0x09, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x63, 0x09, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xc1, 0x7d, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x64, 0x00, 0x69, 0x00, 0x72, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x79, 0x00, 0x5f, 0x00, 0x61, 0x00, 0x64, 0x00, 0x73, 0x00, 0x31, 0x00, 0x74, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x78, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x03, 0x00, 0x00, 0xa0, 0x13, 0x00, 0x64, 0x00, 0x69, 0x00, 0x72, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x79, 0x00, 0x5f, 0x00, 0x6a, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x31, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0x0a, 0x00, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x0c, 0x00, 0x00, 0xa0, 0x17, 0x00, 0x64, 0x00, 0x69, 0x00, 0x72, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x79, 0x00, 0x5f, 0x00, 0x73, 0x00, 0x79, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x6b, 0x00, 0x31, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xe5, 0xae, 0xac, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xe5, 0xae, 0xac, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xe5, 0xae, 0xac, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xe5, 0xae, 0xac, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x74, 0x00, 0x79, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xa7, 0xbf, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x5f, 0x00, 0x61, 0x00, 0x64, 0x00, 0x73, 0x00, 0x31, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x70, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xe5, 0xae, 0xac, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xe5, 0xae, 0xac, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x5b, 0x14, 0xdd, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xb4, 0x6c, 0xad, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x5f, 0x00, 0x68, 0x00, 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x6b, 0x00, 0x31, 0x00, 0x6c, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x78, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x2f, 0x4e, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x2f, 0x4e, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x2f, 0x4e, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x2f, 0x4e, 0xde, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xa0, 0x12, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x5f, 0x00, 0x73, 0x00, 0x79, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x6f, 0x00, 0x0a, 0x00, 0x69, 0x00, 0x63, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x6b, 0x00, 0x31, 0x00, 0x20, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa8, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb7, 0x57, 0xae, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xb7, 0x57, 0xae, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xb7, 0x57, 0xae, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xb7, 0x57, 0xae, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x4d, 0x00, 0x79, 0x00, 0x20, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x79, 0x00, 0x20, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x79, 0x00, 0x20, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x67, 0x00, 0xd5, 0x01, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x88, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xe0, 0x72, 0x6b, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xe0, 0x72, 0x6b, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xe0, 0x72, 0x6b, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xe0, 0x72, 0x6b, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x56, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xe5, 0xae, 0xac, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x2a, 0xa0, 0xd4, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x2a, 0xa0, 0xd4, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x2a, 0xa0, 0xd4, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x64, 0x00, 0x69, 0x00, 0x72, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xc1, 0x7d, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xc1, 0x7d, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xc1, 0x7d, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xc1, 0x7d, 0xe0, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x74, 0x00, 0x65, 0x00, 0x0a, 0x00, 0x74, 0x00, 0x64, 0x00, 0x69, 0x00, 0x72, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x49, 0x4e, 0x44, 0x58, 0x28, 0x00, 0x09, 0x00, 0x37, 0x75, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x00, 0x00, 0xe8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x19, 0xa4, 0xcb, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x07, 0xdd, 0xd2, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x07, 0xdd, 0xd2, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x07, 0xdd, 0xd2, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, 0x17, 0x00, 0x00, 0x80, 0x17, 0x00, 0x6c, 0x00, 0x7a, 0x00, 0x78, 0x00, 0x70, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x31, 0x00, 0x36, 0x00, 0x6b, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x65, 0x00, 0x64, 0x00, 0x31, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb7, 0x57, 0xae, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xbb, 0x00, 0xc1, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xbb, 0x00, 0xc1, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xbb, 0x00, 0xc1, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, 0x17, 0x00, 0x00, 0x80, 0x16, 0x00, 0x6c, 0x00, 0x7a, 0x00, 0x78, 0x00, 0x70, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x34, 0x00, 0x6b, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x65, 0x00, 0x64, 0x00, 0x31, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xe8, 0xeb, 0xc1, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x19, 0xa4, 0xcb, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x19, 0xa4, 0xcb, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x19, 0xa4, 0xcb, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, 0x17, 0x00, 0x00, 0x80, 0x16, 0x00, 0x6c, 0x00, 0x7a, 0x00, 0x78, 0x00, 0x70, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x38, 0x00, 0x6b, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x65, 0x00, 0x64, 0x00, 0x31, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x70, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x93, 0x63, 0xd4, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x5b, 0x14, 0xdd, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x5b, 0x14, 0xdd, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x5b, 0x14, 0xdd, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xd6, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, 0x17, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x6c, 0x00, 0x7a, 0x00, 0x78, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x65, 0x00, 0x64, 0x00, 0x31, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xe5, 0xae, 0xac, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xe5, 0xae, 0xac, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x5b, 0x14, 0xdd, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0xb4, 0x6c, 0xad, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x6c, 0xad, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x39, 0x6b, 0x96, 0x51, 0x4e, 0xa1, 0xd5, 0x01, 0x39, 0x6b, 0x96, 0x51, 0x4e, 0xa1, 0xd5, 0x01, 0xb4, 0x6c, 0xad, 0x59, 0x4e, 0xa1, 0xd5, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_index_entry_vector_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_entry_vector_initialize( void ) { libcerror_error_t *error = NULL; libfdata_vector_t *index_entry_vector = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; io_handle->index_entry_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_index_entry_vector_data1, 72, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_index_entry_vector_initialize( &index_entry_vector, io_handle, mft_attribute, 4096, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index_entry_vector", index_entry_vector ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfdata_vector_free( &index_entry_vector, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_entry_vector", index_entry_vector ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_entry_vector_initialize( NULL, io_handle, mft_attribute, 4096, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); index_entry_vector = (libfdata_vector_t *) 0x12345678UL; result = libfsntfs_index_entry_vector_initialize( &index_entry_vector, io_handle, mft_attribute, 4096, &error ); index_entry_vector = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); io_handle->cluster_block_size = 0; result = libfsntfs_index_entry_vector_initialize( &index_entry_vector, io_handle, mft_attribute, 4096, &error ); io_handle->cluster_block_size = 4096; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_entry_vector_initialize( &index_entry_vector, io_handle, mft_attribute, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_entry_vector_initialize( &index_entry_vector, NULL, mft_attribute, 4096, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_entry_vector_initialize( &index_entry_vector, io_handle, NULL, 4096, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* TODO test with LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK set */ #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_index_entry_vector_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_index_entry_vector_initialize( &index_entry_vector, io_handle, mft_attribute, 4096, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( index_entry_vector != NULL ) { libfdata_vector_free( &index_entry_vector, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_entry_vector", index_entry_vector ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_index_entry_vector_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_index_entry_vector_initialize( &index_entry_vector, io_handle, mft_attribute, 4096, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( index_entry_vector != NULL ) { libfdata_vector_free( &index_entry_vector, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_entry_vector", index_entry_vector ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( index_entry_vector != NULL ) { libfdata_vector_free( &index_entry_vector, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_index_entry_vector_read_element_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_entry_vector_read_element_data( void ) { libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfcache_cache_t *cache = NULL; libfdata_vector_t *index_entry_vector = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; io_handle->index_entry_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_index_entry_vector_data1, 72, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_index_entry_vector_initialize( &index_entry_vector, io_handle, mft_attribute, 4096, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index_entry_vector", index_entry_vector ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfcache_cache_initialize( &cache, 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "cache", cache ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize file IO handle */ result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_index_entry_vector_data2, 8192, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_index_entry_vector_read_element_data( NULL, file_io_handle, index_entry_vector, (libfdata_cache_t *) cache, 0, 0, 0, 4096, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_entry_vector_read_element_data( NULL, file_io_handle, index_entry_vector, (libfdata_cache_t *) cache, 0, 0, 0, 0, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_entry_vector_read_element_data( NULL, file_io_handle, index_entry_vector, (libfdata_cache_t *) cache, 0, 0, 0, (size64_t) SSIZE_MAX + 1, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_entry_vector_read_element_data( NULL, file_io_handle, NULL, (libfdata_cache_t *) cache, 0, 0, 0, 4096, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* TODO implement read from file IO handle failing */ #if defined( HAVE_FSNTFS_TEST_MEMORY ) /* Test libfsntfs_index_entry_vector_read_element_data with malloc failing in libfsntfs_index_entry_initialize */ fsntfs_test_malloc_attempts_before_fail = 0; result = libfsntfs_index_entry_vector_read_element_data( NULL, file_io_handle, index_entry_vector, (libfdata_cache_t *) cache, 0, 0, 0, 4096, 0, 0, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #if defined( OPTIMIZATION_DISABLED ) /* Test libfsntfs_index_entry_vector_read_element_data with memset failing in libfsntfs_index_entry_clear */ fsntfs_test_memset_attempts_before_fail = 0; result = libfsntfs_index_entry_vector_read_element_data( NULL, file_io_handle, index_entry_vector, (libfdata_cache_t *) cache, 0, 0, 0, 4096, 0, 0, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( OPTIMIZATION_DISABLED ) */ #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up file IO handle */ result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfcache_cache_free( &cache, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "cache", cache ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfdata_vector_free( &index_entry_vector, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_entry_vector", index_entry_vector ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } if( cache != NULL ) { libfcache_cache_free( &cache, NULL ); } if( index_entry_vector != NULL ) { libfdata_vector_free( &index_entry_vector, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_index_entry_vector_initialize", fsntfs_test_index_entry_vector_initialize ); FSNTFS_TEST_RUN( "libfsntfs_index_entry_vector_read_element_data", fsntfs_test_index_entry_vector_read_element_data ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_index_node.c ================================================ /* * Library index_node type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_index_node.h" uint8_t fsntfs_test_index_node_data1[ 40 ] = { 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_index_node_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_node_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_index_node_t *index_node = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_index_node_initialize( &index_node, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index_node", index_node ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_index_node_free( &index_node, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_node", index_node ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_node_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); index_node = (libfsntfs_index_node_t *) 0x12345678UL; result = libfsntfs_index_node_initialize( &index_node, &error ); index_node = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_index_node_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_index_node_initialize( &index_node, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( index_node != NULL ) { libfsntfs_index_node_free( &index_node, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_node", index_node ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_index_node_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_index_node_initialize( &index_node, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( index_node != NULL ) { libfsntfs_index_node_free( &index_node, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_node", index_node ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( index_node != NULL ) { libfsntfs_index_node_free( &index_node, NULL ); } return( 0 ); } /* Tests the libfsntfs_index_node_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_node_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_index_node_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_index_node_read_header function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_node_read_header( void ) { libcerror_error_t *error = NULL; libfsntfs_index_node_t *index_node = NULL; int result = 0; /* Initialize test */ result = libfsntfs_index_node_initialize( &index_node, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index_node", index_node ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_index_node_read_header( index_node, fsntfs_test_index_node_data1, 40, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_node_read_header( NULL, fsntfs_test_index_node_data1, 40, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_node_read_header( index_node, NULL, 40, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_node_read_header( index_node, fsntfs_test_index_node_data1, (size_t) SSIZE_MAX + 1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_node_read_header( index_node, fsntfs_test_index_node_data1, 40, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_index_node_free( &index_node, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_node", index_node ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( index_node != NULL ) { libfsntfs_index_node_free( &index_node, NULL ); } return( 0 ); } /* Tests the libfsntfs_index_node_read_values function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_node_read_values( void ) { libcerror_error_t *error = NULL; libfsntfs_index_node_t *index_node = NULL; int result = 0; /* Initialize test */ result = libfsntfs_index_node_initialize( &index_node, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index_node", index_node ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_index_node_read_header( index_node, fsntfs_test_index_node_data1, 40, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_index_node_read_values( index_node, 0, fsntfs_test_index_node_data1, 40, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_node_read_values( NULL, 0, fsntfs_test_index_node_data1, 40, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_node_read_values( index_node, 0, NULL, 40, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_node_read_values( index_node, 0, fsntfs_test_index_node_data1, (size_t) SSIZE_MAX + 1, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_node_read_values( index_node, 0, fsntfs_test_index_node_data1, 40, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_index_node_free( &index_node, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_node", index_node ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( index_node != NULL ) { libfsntfs_index_node_free( &index_node, NULL ); } return( 0 ); } /* Tests the libfsntfs_index_node_get_number_of_values function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_node_get_number_of_values( libfsntfs_index_node_t *index_node ) { libcerror_error_t *error = NULL; int number_of_values = 0; int result = 0; /* Test regular cases */ result = libfsntfs_index_node_get_number_of_values( index_node, &number_of_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "number_of_values", number_of_values, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_node_get_number_of_values( NULL, &number_of_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_node_get_number_of_values( index_node, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_index_node_t *index_node = NULL; int result = 0; #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_index_node_initialize", fsntfs_test_index_node_initialize ); FSNTFS_TEST_RUN( "libfsntfs_index_node_free", fsntfs_test_index_node_free ); FSNTFS_TEST_RUN( "libfsntfs_index_node_read_header", fsntfs_test_index_node_read_header ); FSNTFS_TEST_RUN( "libfsntfs_index_node_read_values", fsntfs_test_index_node_read_values ); #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize test */ result = libfsntfs_index_node_initialize( &index_node, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index_node", index_node ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_index_node_read_header( index_node, fsntfs_test_index_node_data1, 40, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_index_node_read_values( index_node, 0, fsntfs_test_index_node_data1, 40, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Run tests */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_index_node_get_number_of_values", fsntfs_test_index_node_get_number_of_values, index_node ); /* TODO add tests for libfsntfs_index_node_get_value_by_index */ /* Clean up */ result = libfsntfs_index_node_free( &index_node, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_node", index_node ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( index_node != NULL ) { libfsntfs_index_node_free( &index_node, NULL ); } return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_index_node_header.c ================================================ /* * Library index_node_header type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_index_node_header.h" uint8_t fsntfs_test_index_node_header_data1[ 16 ] = { 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_index_node_header_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_node_header_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_index_node_header_t *index_node_header = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_index_node_header_initialize( &index_node_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index_node_header", index_node_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_index_node_header_free( &index_node_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_node_header", index_node_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_node_header_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); index_node_header = (libfsntfs_index_node_header_t *) 0x12345678UL; result = libfsntfs_index_node_header_initialize( &index_node_header, &error ); index_node_header = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_index_node_header_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_index_node_header_initialize( &index_node_header, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( index_node_header != NULL ) { libfsntfs_index_node_header_free( &index_node_header, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_node_header", index_node_header ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_index_node_header_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_index_node_header_initialize( &index_node_header, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( index_node_header != NULL ) { libfsntfs_index_node_header_free( &index_node_header, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_node_header", index_node_header ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( index_node_header != NULL ) { libfsntfs_index_node_header_free( &index_node_header, NULL ); } return( 0 ); } /* Tests the libfsntfs_index_node_header_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_node_header_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_index_node_header_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_index_node_header_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_node_header_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_index_node_header_t *index_node_header = NULL; int result = 0; /* Initialize test */ result = libfsntfs_index_node_header_initialize( &index_node_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index_node_header", index_node_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_index_node_header_read_data( index_node_header, fsntfs_test_index_node_header_data1, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_node_header_read_data( NULL, fsntfs_test_index_node_header_data1, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_node_header_read_data( index_node_header, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_node_header_read_data( index_node_header, fsntfs_test_index_node_header_data1, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_index_node_header_free( &index_node_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_node_header", index_node_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( index_node_header != NULL ) { libfsntfs_index_node_header_free( &index_node_header, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_index_node_header_initialize", fsntfs_test_index_node_header_initialize ); FSNTFS_TEST_RUN( "libfsntfs_index_node_header_free", fsntfs_test_index_node_header_free ); FSNTFS_TEST_RUN( "libfsntfs_index_node_header_read_data", fsntfs_test_index_node_header_read_data ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_index_root_header.c ================================================ /* * Library index_root_header type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_index_root_header.h" uint8_t fsntfs_test_index_root_header_data1[ 16 ] = { 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_index_root_header_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_root_header_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_index_root_header_t *index_root_header = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_index_root_header_initialize( &index_root_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index_root_header", index_root_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_index_root_header_free( &index_root_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_root_header", index_root_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_root_header_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); index_root_header = (libfsntfs_index_root_header_t *) 0x12345678UL; result = libfsntfs_index_root_header_initialize( &index_root_header, &error ); index_root_header = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_index_root_header_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_index_root_header_initialize( &index_root_header, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( index_root_header != NULL ) { libfsntfs_index_root_header_free( &index_root_header, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_root_header", index_root_header ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_index_root_header_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_index_root_header_initialize( &index_root_header, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( index_root_header != NULL ) { libfsntfs_index_root_header_free( &index_root_header, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_root_header", index_root_header ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( index_root_header != NULL ) { libfsntfs_index_root_header_free( &index_root_header, NULL ); } return( 0 ); } /* Tests the libfsntfs_index_root_header_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_root_header_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_index_root_header_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_index_root_header_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_root_header_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_index_root_header_t *index_root_header = NULL; int result = 0; /* Initialize test */ result = libfsntfs_index_root_header_initialize( &index_root_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index_root_header", index_root_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_index_root_header_read_data( index_root_header, fsntfs_test_index_root_header_data1, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_root_header_read_data( NULL, fsntfs_test_index_root_header_data1, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_root_header_read_data( index_root_header, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_root_header_read_data( index_root_header, fsntfs_test_index_root_header_data1, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_root_header_read_data( index_root_header, fsntfs_test_index_root_header_data1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_index_root_header_free( &index_root_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_root_header", index_root_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( index_root_header != NULL ) { libfsntfs_index_root_header_free( &index_root_header, NULL ); } return( 0 ); } /* Tests the libfsntfs_index_root_header_get_index_entry_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_root_header_get_index_entry_size( libfsntfs_index_root_header_t *index_root_header ) { libcerror_error_t *error = NULL; uint32_t index_entry_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_index_root_header_get_index_entry_size( index_root_header, &index_entry_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT32( "index_entry_size", index_entry_size, 4096 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_root_header_get_index_entry_size( NULL, &index_entry_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_root_header_get_index_entry_size( index_root_header, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_index_root_header_get_attribute_type function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_root_header_get_attribute_type( libfsntfs_index_root_header_t *index_root_header ) { libcerror_error_t *error = NULL; uint32_t attribute_type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_index_root_header_get_attribute_type( index_root_header, &attribute_type, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT32( "attribute_type", attribute_type, (uint32_t) 0x00000030UL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_root_header_get_attribute_type( NULL, &attribute_type, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_root_header_get_attribute_type( index_root_header, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_index_root_header_get_collation_type function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_root_header_get_collation_type( libfsntfs_index_root_header_t *index_root_header ) { libcerror_error_t *error = NULL; uint32_t collation_type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_index_root_header_get_collation_type( index_root_header, &collation_type, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT32( "collation_type", collation_type, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_root_header_get_collation_type( NULL, &collation_type, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_index_root_header_get_collation_type( index_root_header, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_index_root_header_t *index_root_header = NULL; int result = 0; #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_index_root_header_initialize", fsntfs_test_index_root_header_initialize ); FSNTFS_TEST_RUN( "libfsntfs_index_root_header_free", fsntfs_test_index_root_header_free ); FSNTFS_TEST_RUN( "libfsntfs_index_root_header_read_data", fsntfs_test_index_root_header_read_data ); #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize test */ result = libfsntfs_index_root_header_initialize( &index_root_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index_root_header", index_root_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_index_root_header_read_data( index_root_header, fsntfs_test_index_root_header_data1, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Run tests */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_index_root_header_get_index_entry_size", fsntfs_test_index_root_header_get_index_entry_size, index_root_header ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_index_root_header_get_attribute_type", fsntfs_test_index_root_header_get_attribute_type, index_root_header ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_index_root_header_get_collation_type", fsntfs_test_index_root_header_get_collation_type, index_root_header ); /* Clean up */ result = libfsntfs_index_root_header_free( &index_root_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_root_header", index_root_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( index_root_header != NULL ) { libfsntfs_index_root_header_free( &index_root_header, NULL ); } return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_index_value.c ================================================ /* * Library index_value type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_index_value.h" uint8_t fsntfs_test_index_value_data1[ 24 ] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_index_value_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_value_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_index_value_t *index_value = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_index_value_initialize( &index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index_value", index_value ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_index_value_free( &index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_value", index_value ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_index_value_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); index_value = (libfsntfs_index_value_t *) 0x12345678UL; result = libfsntfs_index_value_initialize( &index_value, &error ); index_value = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_index_value_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_index_value_initialize( &index_value, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( index_value != NULL ) { libfsntfs_index_value_free( &index_value, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_value", index_value ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_index_value_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_index_value_initialize( &index_value, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( index_value != NULL ) { libfsntfs_index_value_free( &index_value, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_value", index_value ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( index_value != NULL ) { libfsntfs_index_value_free( &index_value, NULL ); } return( 0 ); } /* Tests the libfsntfs_index_value_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_value_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_index_value_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_index_index_value_read function * Returns 1 if successful or 0 if not */ int fsntfs_test_index_value_read( void ) { libcerror_error_t *error = NULL; libfsntfs_index_value_t *index_value = NULL; ssize_t read_count = 0; int index_value_entry = 0; int result = 0; /* Initialize test */ result = libfsntfs_index_value_initialize( &index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "index_value", index_value ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ read_count = libfsntfs_index_value_read( index_value, 0, &index_value_entry, fsntfs_test_index_value_data1, 24, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) 24 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ read_count = libfsntfs_index_value_read( NULL, 0, &index_value_entry, fsntfs_test_index_value_data1, 24, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_index_value_read( index_value, 0, &index_value_entry, NULL, 24, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); read_count = libfsntfs_index_value_read( index_value, 0, &index_value_entry, fsntfs_test_index_value_data1, (size_t) SSIZE_MAX + 1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_SSIZE( "read_count", read_count, (ssize_t) -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_index_value_free( &index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "index_value", index_value ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( index_value != NULL ) { libfsntfs_index_value_free( &index_value, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_index_value_initialize", fsntfs_test_index_value_initialize ); FSNTFS_TEST_RUN( "libfsntfs_index_value_free", fsntfs_test_index_value_free ); FSNTFS_TEST_RUN( "libfsntfs_index_value_read", fsntfs_test_index_value_read ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_io_handle.c ================================================ /* * Library io_handle type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_io_handle.h" #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_io_handle_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_io_handle_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_io_handle_t *io_handle = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_io_handle_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); io_handle = (libfsntfs_io_handle_t *) 0x12345678UL; result = libfsntfs_io_handle_initialize( &io_handle, &error ); io_handle = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_io_handle_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_io_handle_initialize( &io_handle, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_io_handle_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_io_handle_initialize( &io_handle, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_io_handle_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_io_handle_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_io_handle_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_io_handle_clear function * Returns 1 if successful or 0 if not */ int fsntfs_test_io_handle_clear( void ) { libcerror_error_t *error = NULL; libfsntfs_io_handle_t *io_handle = NULL; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_io_handle_clear( io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_io_handle_clear( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) /* Test libfsntfs_io_handle_clear with memset failing */ fsntfs_test_memset_attempts_before_fail = 0; result = libfsntfs_io_handle_clear( io_handle, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_io_handle_initialize", fsntfs_test_io_handle_initialize ); FSNTFS_TEST_RUN( "libfsntfs_io_handle_free", fsntfs_test_io_handle_free ); FSNTFS_TEST_RUN( "libfsntfs_io_handle_clear", fsntfs_test_io_handle_clear ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_libbfio.h ================================================ /* * The libbfio header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_TEST_LIBBFIO_H ) #define _FSNTFS_TEST_LIBBFIO_H #include /* Define HAVE_LOCAL_LIBBFIO for local use of libbfio */ #if defined( HAVE_LOCAL_LIBBFIO ) #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBBFIO_DLL_IMPORT * before including libbfio.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBBFIO_DLL_IMPORT #endif #include #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( LIBBFIO_HAVE_MULTI_THREAD_SUPPORT ) #error Multi-threading support requires libbfio with multi-threading support #endif #endif /* defined( HAVE_LOCAL_LIBBFIO ) */ #endif /* !defined( _FSNTFS_TEST_LIBBFIO_H ) */ ================================================ FILE: tests/fsntfs_test_libcdata.h ================================================ /* * The libcdata header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_TEST_LIBCDATA_H ) #define _FSNTFS_TEST_LIBCDATA_H #include /* Define HAVE_LOCAL_LIBCDATA for local use of libcdata */ #if defined( HAVE_LOCAL_LIBCDATA ) #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBCDATA_DLL_IMPORT * before including libcdata.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBCDATA_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBCDATA ) */ #endif /* !defined( _FSNTFS_TEST_LIBCDATA_H ) */ ================================================ FILE: tests/fsntfs_test_libcerror.h ================================================ /* * The libcerror header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_TEST_LIBCERROR_H ) #define _FSNTFS_TEST_LIBCERROR_H #include /* Define HAVE_LOCAL_LIBCERROR for local use of libcerror */ #if defined( HAVE_LOCAL_LIBCERROR ) #include #include #include #include #else /* If libtool DLL support is enabled set LIBCERROR_DLL_IMPORT * before including libcerror.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBCERROR_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBCERROR ) */ #endif /* !defined( _FSNTFS_TEST_LIBCERROR_H ) */ ================================================ FILE: tests/fsntfs_test_libclocale.h ================================================ /* * The libclocale header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_TEST_LIBCLOCALE_H ) #define _FSNTFS_TEST_LIBCLOCALE_H #include /* Define HAVE_LOCAL_LIBCLOCALE for local use of libclocale */ #if defined( HAVE_LOCAL_LIBCLOCALE ) #include #include #include #include #else /* If libtool DLL support is enabled set LIBCLOCALE_DLL_IMPORT * before including libclocale.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBCLOCALE_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBCLOCALE ) */ #endif /* !defined( _FSNTFS_TEST_LIBCLOCALE_H ) */ ================================================ FILE: tests/fsntfs_test_libcnotify.h ================================================ /* * The libcnotify header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_TEST_LIBCNOTIFY_H ) #define _FSNTFS_TEST_LIBCNOTIFY_H #include /* Define HAVE_LOCAL_LIBCNOTIFY for local use of libcnotify */ #if defined( HAVE_LOCAL_LIBCNOTIFY ) #include #include #include #include #else /* If libtool DLL support is enabled set LIBCNOTIFY_DLL_IMPORT * before including libcnotify.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBCNOTIFY_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBCNOTIFY ) */ #endif /* !defined( _FSNTFS_TEST_LIBCNOTIFY_H ) */ ================================================ FILE: tests/fsntfs_test_libcpath.h ================================================ /* * The libcpath header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_TEST_LIBCPATH_H ) #define _FSNTFS_TEST_LIBCPATH_H #include /* Define HAVE_LOCAL_LIBCPATH for local use of libcpath */ #if defined( HAVE_LOCAL_LIBCPATH ) #include #include #else /* If libtool DLL support is enabled set LIBCPATH_DLL_IMPORT * before including libcpath.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBCPATH_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBCPATH ) */ #endif /* !defined( _FSNTFS_TEST_LIBCPATH_H ) */ ================================================ FILE: tests/fsntfs_test_libcthreads.h ================================================ /* * The internal libcthreads header * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_TEST_LIBCTHREADS_H ) #define _FSNTFS_TEST_LIBCTHREADS_H #include #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBFSNTFS ) /* Define HAVE_LOCAL_LIBCTHREADS for local use of libcthreads */ #if defined( HAVE_LOCAL_LIBCTHREADS ) #include #include #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBCTHREADS_DLL_IMPORT * before including libcthreads.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBCTHREADS_DLL_IMPORT #endif #include #endif #endif /* defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBFSNTFS ) */ #endif ================================================ FILE: tests/fsntfs_test_libfcache.h ================================================ /* * The libfcache header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_TEST_LIBFCACHE_H ) #define _FSNTFS_TEST_LIBFCACHE_H #include /* Define HAVE_LOCAL_LIBFCACHE for local use of libfcache */ #if defined( HAVE_LOCAL_LIBFCACHE ) #include #include #include #include #else /* If libtool DLL support is enabled set LIBFCACHE_DLL_IMPORT * before including libfcache.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBFCACHE_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBFCACHE ) */ #endif /* !defined( _FSNTFS_TEST_LIBFCACHE_H ) */ ================================================ FILE: tests/fsntfs_test_libfdata.h ================================================ /* * The libfdata header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_TEST_LIBFDATA_H ) #define _FSNTFS_TEST_LIBFDATA_H #include /* Define HAVE_LOCAL_LIBFDATA for local use of libfdata */ #if defined( HAVE_LOCAL_LIBFDATA ) #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBFDATA_DLL_IMPORT * before including libfdata.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBFDATA_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBFDATA ) */ #endif /* !defined( _FSNTFS_TEST_LIBFDATA_H ) */ ================================================ FILE: tests/fsntfs_test_libfsntfs.h ================================================ /* * The libfsntfs header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_TEST_LIBFSNTFS_H ) #define _FSNTFS_TEST_LIBFSNTFS_H #include #include #endif /* !defined( _FSNTFS_TEST_LIBFSNTFS_H ) */ ================================================ FILE: tests/fsntfs_test_libuna.h ================================================ /* * The libuna header wrapper * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_TEST_LIBUNA_H ) #define _FSNTFS_TEST_LIBUNA_H #include /* Define HAVE_LOCAL_LIBUNA for local use of libuna */ #if defined( HAVE_LOCAL_LIBUNA ) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #else /* If libtool DLL support is enabled set LIBUNA_DLL_IMPORT * before including libuna.h */ #if defined( _WIN32 ) && defined( DLL_IMPORT ) #define LIBUNA_DLL_IMPORT #endif #include #endif /* defined( HAVE_LOCAL_LIBUNA ) */ #endif /* !defined( _FSNTFS_TEST_LIBUNA_H ) */ ================================================ FILE: tests/fsntfs_test_logged_utility_stream_values.c ================================================ /* * Library logged_utility_stream_values type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" #include "../libfsntfs/libfsntfs_logged_utility_stream_values.h" /* TODO replace by non TxF data logged utility stream */ uint8_t fsntfs_test_logged_utility_stream_values_data1[ 104 ] = { 0x00, 0x01, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x09, 0x18, 0x00, 0x00, 0x00, 0x09, 0x00, 0x38, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x54, 0x00, 0x58, 0x00, 0x46, 0x00, 0x5f, 0x00, 0x44, 0x00, 0x41, 0x00, 0x54, 0x00, 0x41, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_logged_utility_stream_values_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_logged_utility_stream_values_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_logged_utility_stream_values_t *logged_utility_stream_values = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_logged_utility_stream_values_initialize( &logged_utility_stream_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "logged_utility_stream_values", logged_utility_stream_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_logged_utility_stream_values_free( &logged_utility_stream_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "logged_utility_stream_values", logged_utility_stream_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_logged_utility_stream_values_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); logged_utility_stream_values = (libfsntfs_logged_utility_stream_values_t *) 0x12345678UL; result = libfsntfs_logged_utility_stream_values_initialize( &logged_utility_stream_values, &error ); logged_utility_stream_values = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_logged_utility_stream_values_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_logged_utility_stream_values_initialize( &logged_utility_stream_values, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( logged_utility_stream_values != NULL ) { libfsntfs_logged_utility_stream_values_free( &logged_utility_stream_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "logged_utility_stream_values", logged_utility_stream_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_logged_utility_stream_values_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_logged_utility_stream_values_initialize( &logged_utility_stream_values, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( logged_utility_stream_values != NULL ) { libfsntfs_logged_utility_stream_values_free( &logged_utility_stream_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "logged_utility_stream_values", logged_utility_stream_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( logged_utility_stream_values != NULL ) { libfsntfs_logged_utility_stream_values_free( &logged_utility_stream_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_logged_utility_stream_values_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_logged_utility_stream_values_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_logged_utility_stream_values_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_logged_utility_stream_values_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_logged_utility_stream_values_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_logged_utility_stream_values_t *logged_utility_stream_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_logged_utility_stream_values_initialize( &logged_utility_stream_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "logged_utility_stream_values", logged_utility_stream_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_logged_utility_stream_values_read_data( logged_utility_stream_values, &( fsntfs_test_logged_utility_stream_values_data1[ 42 ] ), 56, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_logged_utility_stream_values_read_data( NULL, &( fsntfs_test_logged_utility_stream_values_data1[ 42 ] ), 56, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_logged_utility_stream_values_read_data( logged_utility_stream_values, NULL, 56, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_logged_utility_stream_values_read_data( logged_utility_stream_values, &( fsntfs_test_logged_utility_stream_values_data1[ 42 ] ), (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_logged_utility_stream_values_read_data( logged_utility_stream_values, &( fsntfs_test_logged_utility_stream_values_data1[ 42 ] ), 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_logged_utility_stream_values_free( &logged_utility_stream_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "logged_utility_stream_values", logged_utility_stream_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( logged_utility_stream_values != NULL ) { libfsntfs_logged_utility_stream_values_free( &logged_utility_stream_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_logged_utility_stream_values_read_from_mft_attribute function * Returns 1 if successful or 0 if not */ int fsntfs_test_logged_utility_stream_values_read_from_mft_attribute( void ) { libcerror_error_t *error = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_logged_utility_stream_values_t *logged_utility_stream_values = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_logged_utility_stream_values_data1, 104, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_logged_utility_stream_values_initialize( &logged_utility_stream_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "logged_utility_stream_values", logged_utility_stream_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_logged_utility_stream_values_read_from_mft_attribute( logged_utility_stream_values, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_logged_utility_stream_values_read_from_mft_attribute( NULL, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_logged_utility_stream_values_read_from_mft_attribute( logged_utility_stream_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_logged_utility_stream_values_free( &logged_utility_stream_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "logged_utility_stream_values", logged_utility_stream_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( logged_utility_stream_values != NULL ) { libfsntfs_logged_utility_stream_values_free( &logged_utility_stream_values, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_logged_utility_stream_values_initialize", fsntfs_test_logged_utility_stream_values_initialize ); FSNTFS_TEST_RUN( "libfsntfs_logged_utility_stream_values_free", fsntfs_test_logged_utility_stream_values_free ); FSNTFS_TEST_RUN( "libfsntfs_logged_utility_stream_values_read_data", fsntfs_test_logged_utility_stream_values_read_data ); FSNTFS_TEST_RUN( "libfsntfs_logged_utility_stream_values_read_from_mft_attribute", fsntfs_test_logged_utility_stream_values_read_from_mft_attribute ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_macros.h ================================================ /* * Macros for testing * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_TEST_MACROS_H ) #define _FSNTFS_TEST_MACROS_H #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #define FSNTFS_TEST_ASSERT_EQUAL_INT( name, value, expected_value ) \ if( value != expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%d) != %d\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( name, value, expected_value ) \ if( value == expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%d) == %d\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_GREATER_THAN_INT( name, value, expected_value ) \ if( value <= expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%d) <= %d\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_LESS_THAN_INT( name, value, expected_value ) \ if( value >= expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%d) >= %d\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_EQUAL_INTPTR( name, value, expected_value ) \ if( value != expected_value ) \ { \ fprintf( stdout, "%s:%d %s (0x%08x" PRIjx ") != 0x%08x" PRIjx "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_NOT_EQUAL_INTPTR( name, value, expected_value ) \ if( value == expected_value ) \ { \ fprintf( stdout, "%s:%d %s (0x%08x" PRIjx ") == 0x%08x" PRIjx "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_EQUAL_FLOAT( name, value, expected_value ) \ if( value != expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%f) != %f\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_NOT_EQUAL_FLOAT( name, value, expected_value ) \ if( value == expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%f) == %f\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_EQUAL_SIZE( name, value, expected_value ) \ if( value != expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIzd ") != %" PRIzd "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_EQUAL_SSIZE( name, value, expected_value ) \ if( value != expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIzd ") != %" PRIzd "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_NOT_EQUAL_SSIZE( name, value, expected_value ) \ if( value == expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIzd ") == %" PRIzd "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_EQUAL_INT8( name, value, expected_value ) \ if( value != expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIi8 ") != %" PRIi8 "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_NOT_EQUAL_INT8( name, value, expected_value ) \ if( value == expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIi8 ") == %" PRIi8 "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_EQUAL_UINT8( name, value, expected_value ) \ if( value != expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIi8 ") != %" PRIu8 "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_LESS_THAN_UINT8( name, value, expected_value ) \ if( value >= expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIi8 ") >= %" PRIu8 "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_EQUAL_INT16( name, value, expected_value ) \ if( value != expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIi16 ") != %" PRIi16 "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_NOT_EQUAL_INT16( name, value, expected_value ) \ if( value == expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIi16 ") == %" PRIi16 "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_EQUAL_UINT16( name, value, expected_value ) \ if( value != expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIi16 ") != %" PRIu16 "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_LESS_THAN_UINT16( name, value, expected_value ) \ if( value >= expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIi16 ") >= %" PRIu16 "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_EQUAL_INT32( name, value, expected_value ) \ if( value != expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIi32 ") != %" PRIi32 "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_NOT_EQUAL_INT32( name, value, expected_value ) \ if( value == expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIi32 ") == %" PRIi32 "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_EQUAL_UINT32( name, value, expected_value ) \ if( value != expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIu32 ") != %" PRIu32 "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_LESS_THAN_UINT32( name, value, expected_value ) \ if( value >= expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIu32 ") >= %" PRIu32 "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_EQUAL_INT64( name, value, expected_value ) \ if( value != expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIi64 ") != %" PRIi64 "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_NOT_EQUAL_INT64( name, value, expected_value ) \ if( value == expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIi64 ") == %" PRIi64 "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_EQUAL_UINT64( name, value, expected_value ) \ if( value != expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIu64 ") != %" PRIu64 "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_LESS_THAN_UINT64( name, value, expected_value ) \ if( value >= expected_value ) \ { \ fprintf( stdout, "%s:%d %s (%" PRIu64 ") >= %" PRIu64 "\n", __FILE__, __LINE__, name, value, expected_value ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_IS_NOT_NULL( name, value ) \ if( value == NULL ) \ { \ fprintf( stdout, "%s:%d %s == NULL\n", __FILE__, __LINE__, name ); \ goto on_error; \ } #define FSNTFS_TEST_ASSERT_IS_NULL( name, value ) \ if( value != NULL ) \ { \ fprintf( stdout, "%s:%d %s != NULL\n", __FILE__, __LINE__, name ); \ goto on_error; \ } #define FSNTFS_TEST_RUN( name, function ) \ if( function() != 1 ) \ { \ fprintf( stdout, "Unable to run test: %s\n", name ); \ goto on_error; \ } #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) #define FSNTFS_TEST_RUN_WITH_ARGS( name, function, ... ) \ if( function( __VA_ARGS__ ) != 1 ) \ { \ fprintf( stdout, "Unable to run test: %s\n", name ); \ goto on_error; \ } #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #define FSNTFS_TEST_FPRINT_ERROR( error ) \ libcerror_error_backtrace_fprint( error, stdout ); #endif /* !defined( _FSNTFS_TEST_MACROS_H ) */ ================================================ FILE: tests/fsntfs_test_memory.c ================================================ /* * Memory allocation functions for testing * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #if defined( HAVE_GNU_DL_DLSYM ) && defined( __GNUC__ ) #define __USE_GNU #include #undef __USE_GNU #endif #include "fsntfs_test_memory.h" #if defined( HAVE_FSNTFS_TEST_MEMORY ) static void *(*fsntfs_test_real_malloc)(size_t) = NULL; static void *(*fsntfs_test_real_memcpy)(void *, const void *, size_t) = NULL; static void *(*fsntfs_test_real_memset)(void *, int, size_t) = NULL; static void *(*fsntfs_test_real_realloc)(void *, size_t) = NULL; int fsntfs_test_malloc_attempts_before_fail = -1; int fsntfs_test_memcpy_attempts_before_fail = -1; int fsntfs_test_memset_attempts_before_fail = -1; int fsntfs_test_realloc_attempts_before_fail = -1; /* Custom malloc for testing memory error cases * Note this function might fail if compiled with optimation * Returns a pointer to newly allocated data or NULL */ void *malloc( size_t size ) { void *ptr = NULL; if( fsntfs_test_real_malloc == NULL ) { fsntfs_test_real_malloc = dlsym( RTLD_NEXT, "malloc" ); } if( fsntfs_test_malloc_attempts_before_fail == 0 ) { fsntfs_test_malloc_attempts_before_fail = -1; return( NULL ); } else if( fsntfs_test_malloc_attempts_before_fail > 0 ) { fsntfs_test_malloc_attempts_before_fail--; } ptr = fsntfs_test_real_malloc( size ); return( ptr ); } /* Custom memcpy for testing memory error cases * Note this function might fail if compiled with optimation and as a shared libary * Returns a pointer to newly allocated data or NULL */ void *memcpy( void *destination, const void *source, size_t size ) { if( fsntfs_test_real_memcpy == NULL ) { fsntfs_test_real_memcpy = dlsym( RTLD_NEXT, "memcpy" ); } if( fsntfs_test_memcpy_attempts_before_fail == 0 ) { fsntfs_test_memcpy_attempts_before_fail = -1; return( NULL ); } else if( fsntfs_test_memcpy_attempts_before_fail > 0 ) { fsntfs_test_memcpy_attempts_before_fail--; } destination = fsntfs_test_real_memcpy( destination, source, size ); return( destination ); } /* Custom memset for testing memory error cases * Note this function might fail if compiled with optimation and as a shared libary * Returns a pointer to newly allocated data or NULL */ void *memset( void *ptr, int constant, size_t size ) { if( fsntfs_test_real_memset == NULL ) { fsntfs_test_real_memset = dlsym( RTLD_NEXT, "memset" ); } if( fsntfs_test_memset_attempts_before_fail == 0 ) { fsntfs_test_memset_attempts_before_fail = -1; return( NULL ); } else if( fsntfs_test_memset_attempts_before_fail > 0 ) { fsntfs_test_memset_attempts_before_fail--; } ptr = fsntfs_test_real_memset( ptr, constant, size ); return( ptr ); } /* Custom realloc for testing memory error cases * Note this function might fail if compiled with optimation * Returns a pointer to reallocated data or NULL */ void *realloc( void *ptr, size_t size ) { if( fsntfs_test_real_realloc == NULL ) { fsntfs_test_real_realloc = dlsym( RTLD_NEXT, "realloc" ); } if( fsntfs_test_realloc_attempts_before_fail == 0 ) { fsntfs_test_realloc_attempts_before_fail = -1; return( NULL ); } else if( fsntfs_test_realloc_attempts_before_fail > 0 ) { fsntfs_test_realloc_attempts_before_fail--; } ptr = fsntfs_test_real_realloc( ptr, size ); return( ptr ); } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ ================================================ FILE: tests/fsntfs_test_memory.h ================================================ /* * Memory allocation functions for testing * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_TEST_MEMORY_H ) #define _FSNTFS_TEST_MEMORY_H #include #if defined( __cplusplus ) extern "C" { #endif #if defined( HAVE_GNU_DL_DLSYM ) && defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) && !defined( __arm__ ) && !defined( __clang__ ) && !defined( __CYGWIN__ ) && !defined( __hppa__ ) && !defined( __loongarch__ ) && !defined( __mips__ ) && !defined( __riscv ) && !defined( __sparc__ ) && !defined( HAVE_ASAN ) #define HAVE_FSNTFS_TEST_MEMORY 1 #endif #if defined( HAVE_FSNTFS_TEST_MEMORY ) extern int fsntfs_test_malloc_attempts_before_fail; extern int fsntfs_test_memcpy_attempts_before_fail; extern int fsntfs_test_memset_attempts_before_fail; extern int fsntfs_test_realloc_attempts_before_fail; #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFS_TEST_MEMORY_H ) */ ================================================ FILE: tests/fsntfs_test_mft.c ================================================ /* * Library mft type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft.h" #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_mft_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_t *mft = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 3; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; /* Test regular cases */ result = libfsntfs_mft_initialize( &mft, io_handle, 1024, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft", mft ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_free( &mft, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft", mft ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_initialize( NULL, io_handle, 1024, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); mft = (libfsntfs_mft_t *) 0x12345678UL; result = libfsntfs_mft_initialize( &mft, io_handle, 1024, 0, &error ); mft = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_initialize( &mft, NULL, 1024, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_mft_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_mft_initialize( &mft, io_handle, 1024, 0, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( mft != NULL ) { libfsntfs_mft_free( &mft, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft", mft ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_mft_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_mft_initialize( &mft, io_handle, 1024, 0, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( mft != NULL ) { libfsntfs_mft_free( &mft, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft", mft ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft != NULL ) { libfsntfs_mft_free( &mft, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_mft_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_mft_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* TODO: add tests for libfsntfs_mft_read_mft_entry */ /* Tests the libfsntfs_mft_get_number_of_entries function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_get_number_of_entries( libfsntfs_mft_t *mft ) { libcerror_error_t *error = NULL; uint64_t number_of_entries = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_get_number_of_entries( mft, &number_of_entries, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT64( "number_of_entries", number_of_entries, (uint64_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_get_number_of_entries( NULL, &number_of_entries, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_get_number_of_entries( mft, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_t *mft = NULL; int result = 0; #endif FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_mft_initialize", fsntfs_test_mft_initialize ); FSNTFS_TEST_RUN( "libfsntfs_mft_free", fsntfs_test_mft_free ); /* TODO: add tests for libfsntfs_mft_read_mft_entry */ #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize MFT for tests */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_initialize( &mft, io_handle, 1024, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft", mft ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_get_number_of_entries", fsntfs_test_mft_get_number_of_entries, mft ); /* TODO: add tests for libfsntfs_mft_get_mft_entry_by_index */ /* TODO: add tests for libfsntfs_mft_get_mft_entry_by_index_no_cache */ /* Clean up */ result = libfsntfs_mft_free( &mft, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft", mft ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft != NULL ) { libfsntfs_mft_free( &mft, &error ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_mft_attribute.c ================================================ /* * Library mft_attribute type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcdata.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_data_run.h" #include "../libfsntfs/libfsntfs_extent.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" uint8_t fsntfs_test_mft_attribute_data1[ 88 ] = { 0x90, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x00, 0x11, 0x00, 0x38, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x53, 0x00, 0x44, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t fsntfs_test_mft_attribute_data2[ 72 ] = { 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x33, 0x80, 0xaa, 0x00, 0x00, 0x00, 0x0c, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_mft_attribute_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); mft_attribute = (libfsntfs_mft_attribute_t *) 0x12345678UL; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); mft_attribute = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_mft_attribute_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_mft_attribute_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_mft_attribute_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_mft_attribute_data1, 88, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_mft_attribute_data2, 72, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_read_data( NULL, io_handle, fsntfs_test_mft_attribute_data1, 88, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); mft_attribute->name = (uint8_t *) 0x12345678UL; result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_mft_attribute_data1, 88, &error ); mft_attribute->name = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, NULL, fsntfs_test_mft_attribute_data1, 88, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, NULL, 88, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_mft_attribute_data1, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_mft_attribute_data1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where resident data is missing */ result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_mft_attribute_data1, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where non-resident data is missing */ result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_mft_attribute_data2, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); byte_stream_copy_from_uint16_little_endian( &( fsntfs_test_mft_attribute_data2[ 34 ] ), 0x0001 ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_mft_attribute_data2, 48, &error ); byte_stream_copy_from_uint16_little_endian( &( fsntfs_test_mft_attribute_data2[ 34 ] ), 0x0000 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) /* Test libfsntfs_mft_attribute_read_data with malloc failing */ fsntfs_test_malloc_attempts_before_fail = 0; result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_mft_attribute_data1, 88, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #if defined( OPTIMIZATION_DISABLED ) /* Test libfsntfs_mft_attribute_read_data with memcpy failing */ fsntfs_test_memcpy_attempts_before_fail = 0; result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_mft_attribute_data1, 88, &error ); if( fsntfs_test_memcpy_attempts_before_fail != -1 ) { fsntfs_test_memcpy_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( OPTIMIZATION_DISABLED ) */ #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Test error case where size value is invalid */ byte_stream_copy_from_uint32_little_endian( &( fsntfs_test_mft_attribute_data1[ 4 ] ), 0xffffffffUL ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_mft_attribute_data1, 88, &error ); byte_stream_copy_from_uint32_little_endian( &( fsntfs_test_mft_attribute_data1[ 4 ] ), 0x00000058UL ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where compression flags (in data flags) value is invalid */ byte_stream_copy_from_uint16_little_endian( &( fsntfs_test_mft_attribute_data1[ 12 ] ), 0x00ff ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_mft_attribute_data1, 88, &error ); byte_stream_copy_from_uint16_little_endian( &( fsntfs_test_mft_attribute_data1[ 12 ] ), 0x0000 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where non-resident valid data size value is invalid */ byte_stream_copy_from_uint64_little_endian( &( fsntfs_test_mft_attribute_data2[ 56 ] ), 0xffffffffffffffffULL ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_mft_attribute_data2, 72, &error ); byte_stream_copy_from_uint64_little_endian( &( fsntfs_test_mft_attribute_data2[ 56 ] ), 0x000000000000a0a8ULL ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where name offset value is invalid */ byte_stream_copy_from_uint16_little_endian( &( fsntfs_test_mft_attribute_data1[ 10 ] ), 0xffff ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_mft_attribute_data1, 88, &error ); byte_stream_copy_from_uint16_little_endian( &( fsntfs_test_mft_attribute_data1[ 10 ] ), 0x0018 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where name size value is invalid */ fsntfs_test_mft_attribute_data1[ 9 ] = 0xff; result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_mft_attribute_data1, 88, &error ); fsntfs_test_mft_attribute_data1[ 9 ] = 0x04; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where resident data offset value is invalid */ byte_stream_copy_from_uint16_little_endian( &( fsntfs_test_mft_attribute_data1[ 20 ] ), 0xffff ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_mft_attribute_data1, 88, &error ); byte_stream_copy_from_uint16_little_endian( &( fsntfs_test_mft_attribute_data1[ 20 ] ), 0x0020 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where non-resident data runs offset value is invalid */ byte_stream_copy_from_uint16_little_endian( &( fsntfs_test_mft_attribute_data2[ 32 ] ), 0xffff ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_mft_attribute_data2, 72, &error ); byte_stream_copy_from_uint16_little_endian( &( fsntfs_test_mft_attribute_data2[ 32 ] ), 0x0040 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_data_is_resident function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_data_is_resident( libfsntfs_mft_attribute_t *mft_attribute ) { libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_data_is_resident( mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_data_is_resident( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_get_type function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_get_type( libfsntfs_mft_attribute_t *mft_attribute ) { libcerror_error_t *error = NULL; uint32_t type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_get_type( mft_attribute, &type, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT32( "type", type, (uint32_t) 0x00000090UL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_get_type( NULL, &type, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_get_type( mft_attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_get_data_flags function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_get_data_flags( libfsntfs_mft_attribute_t *mft_attribute ) { libcerror_error_t *error = NULL; uint16_t data_flags = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_get_data_flags( mft_attribute, &data_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT16( "data_flags", data_flags, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_get_data_flags( NULL, &data_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_get_data_flags( mft_attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_get_utf8_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_get_utf8_name_size( libfsntfs_mft_attribute_t *mft_attribute ) { uint8_t *name = NULL; libcerror_error_t *error = NULL; size_t utf8_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_get_utf8_name_size( mft_attribute, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf8_name_size", utf8_name_size, (size_t) 5 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); name = mft_attribute->name; mft_attribute->name = NULL; result = libfsntfs_mft_attribute_get_utf8_name_size( mft_attribute, &utf8_name_size, &error ); mft_attribute->name = name; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf8_name_size", utf8_name_size, (size_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_get_utf8_name_size( NULL, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_get_utf8_name_size( mft_attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); name = mft_attribute->name; mft_attribute->name = NULL; result = libfsntfs_mft_attribute_get_utf8_name_size( mft_attribute, NULL, &error ); mft_attribute->name = name; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_get_utf8_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_get_utf8_name( libfsntfs_mft_attribute_t *mft_attribute ) { uint8_t utf8_name[ 16 ]; uint8_t *name = NULL; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_get_utf8_name( mft_attribute, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_get_utf8_name( NULL, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); name = mft_attribute->name; mft_attribute->name = NULL; result = libfsntfs_mft_attribute_get_utf8_name( mft_attribute, utf8_name, 16, &error ); mft_attribute->name = name; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_get_utf8_name( mft_attribute, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_get_utf8_name( mft_attribute, utf8_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_get_utf8_name( mft_attribute, utf8_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_get_utf16_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_get_utf16_name_size( libfsntfs_mft_attribute_t *mft_attribute ) { uint8_t *name = NULL; libcerror_error_t *error = NULL; size_t utf16_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_get_utf16_name_size( mft_attribute, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf16_name_size", utf16_name_size, (size_t) 5 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); name = mft_attribute->name; mft_attribute->name = NULL; result = libfsntfs_mft_attribute_get_utf16_name_size( mft_attribute, &utf16_name_size, &error ); mft_attribute->name = name; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf16_name_size", utf16_name_size, (size_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_get_utf16_name_size( NULL, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_get_utf16_name_size( mft_attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); name = mft_attribute->name; mft_attribute->name = NULL; result = libfsntfs_mft_attribute_get_utf16_name_size( mft_attribute, NULL, &error ); mft_attribute->name = name; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_get_utf16_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_get_utf16_name( libfsntfs_mft_attribute_t *mft_attribute ) { uint16_t utf16_name[ 16 ]; uint8_t *name = NULL; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_get_utf16_name( mft_attribute, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_get_utf16_name( NULL, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); name = mft_attribute->name; mft_attribute->name = NULL; result = libfsntfs_mft_attribute_get_utf16_name( mft_attribute, utf16_name, 16, &error ); mft_attribute->name = name; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_get_utf16_name( mft_attribute, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_get_utf16_name( mft_attribute, utf16_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_get_utf16_name( mft_attribute, utf16_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_compare_name_with_utf8_string function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_compare_name_with_utf8_string( libfsntfs_mft_attribute_t *mft_attribute ) { uint8_t utf8_name1[ 5 ] = { '$', 'S', 'D', 'H', 0 }; uint8_t utf8_name2[ 6 ] = { 'b', 'o', 'g', 'u', 's', 0 }; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_compare_name_with_utf8_string( mft_attribute, utf8_name1, 5, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_compare_name_with_utf8_string( mft_attribute, utf8_name2, 6, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_compare_name_with_utf8_string( NULL, utf8_name1, 5, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_compare_name_with_utf8_string( mft_attribute, NULL, 5, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_compare_name_with_utf8_string( mft_attribute, utf8_name1, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_compare_name_with_utf16_string function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_compare_name_with_utf16_string( libfsntfs_mft_attribute_t *mft_attribute ) { uint16_t utf16_name1[ 5 ] = { '$', 'S', 'D', 'H', 0 }; uint16_t utf16_name2[ 6 ] = { 'b', 'o', 'g', 'u', 's', 0 }; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_compare_name_with_utf16_string( mft_attribute, utf16_name1, 5, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_compare_name_with_utf16_string( mft_attribute, utf16_name2, 6, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_compare_name_with_utf16_string( NULL, utf16_name1, 5, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_compare_name_with_utf16_string( mft_attribute, NULL, 5, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_compare_name_with_utf16_string( mft_attribute, utf16_name1, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_get_compression_unit_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_get_compression_unit_size( libfsntfs_mft_attribute_t *mft_attribute ) { libcerror_error_t *error = NULL; size_t compression_unit_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_get_compression_unit_size( mft_attribute, &compression_unit_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "compression_unit_size", compression_unit_size, (size_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_get_compression_unit_size( NULL, &compression_unit_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_get_compression_unit_size( mft_attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_get_resident_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_get_resident_data( libfsntfs_mft_attribute_t *mft_attribute ) { libcerror_error_t *error = NULL; uint8_t *data = NULL; size_t data_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_get_resident_data( mft_attribute, &data, &data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "data", data ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "data_size", data_size, (size_t) 56 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_get_resident_data( NULL, &data, &data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_get_resident_data( mft_attribute, NULL, &data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_get_resident_data( mft_attribute, &data, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_get_number_of_data_runs function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_get_number_of_data_runs( libfsntfs_mft_attribute_t *mft_attribute ) { libcerror_error_t *error = NULL; int number_of_data_runs = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_get_number_of_data_runs( mft_attribute, &number_of_data_runs, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "number_of_data_runs", number_of_data_runs, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_get_number_of_data_runs( NULL, &number_of_data_runs, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_get_number_of_data_runs( mft_attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_get_data_run_by_index function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_get_data_run_by_index( libfsntfs_mft_attribute_t *mft_attribute ) { libcerror_error_t *error = NULL; libfsntfs_data_run_t *data_run = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_get_data_run_by_index( mft_attribute, 0, &data_run, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "data_run", data_run ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_get_data_run_by_index( NULL, 0, &data_run, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_get_data_run_by_index( mft_attribute, -1, &data_run, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_get_data_run_by_index( mft_attribute, 0, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_get_data_extents_array function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_get_data_extents_array( libfsntfs_mft_attribute_t *mft_attribute ) { libcdata_array_t *data_extents_array = NULL; libcerror_error_t *error = NULL; libfsntfs_io_handle_t *io_handle = NULL; int number_of_data_extents = 0; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; /* Test regular cases */ result = libfsntfs_mft_attribute_get_data_extents_array( mft_attribute, io_handle, &data_extents_array, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "data_extents_array", data_extents_array ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libcdata_array_get_number_of_entries( data_extents_array, &number_of_data_extents, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "number_of_data_extents", number_of_data_extents, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libcdata_array_free( &data_extents_array, (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_extent_free, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "data_extents_array", data_extents_array ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_get_data_extents_array( NULL, io_handle, &data_extents_array, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_get_data_extents_array( mft_attribute, NULL, &data_extents_array, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_get_data_extents_array( mft_attribute, io_handle, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( data_extents_array != NULL ) { libcdata_array_free( &data_extents_array, (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_extent_free, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute1 = NULL; libfsntfs_mft_attribute_t *mft_attribute2 = NULL; int result = 0; #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_mft_attribute_initialize", fsntfs_test_mft_attribute_initialize ); FSNTFS_TEST_RUN( "libfsntfs_mft_attribute_free", fsntfs_test_mft_attribute_free ); FSNTFS_TEST_RUN( "libfsntfs_mft_attribute_read_data", fsntfs_test_mft_attribute_read_data ); #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute1", mft_attribute1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute1, io_handle, fsntfs_test_mft_attribute_data1, 88, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_initialize( &mft_attribute2, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute2", mft_attribute2 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute2, io_handle, fsntfs_test_mft_attribute_data2, 72, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Run tests */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_data_is_resident", fsntfs_test_mft_attribute_data_is_resident, mft_attribute1 ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_get_type", fsntfs_test_mft_attribute_get_type, mft_attribute1 ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_get_data_flags", fsntfs_test_mft_attribute_get_data_flags, mft_attribute1 ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_get_utf8_name_size", fsntfs_test_mft_attribute_get_utf8_name_size, mft_attribute1 ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_get_utf8_name", fsntfs_test_mft_attribute_get_utf8_name, mft_attribute1 ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_get_utf16_name_size", fsntfs_test_mft_attribute_get_utf16_name_size, mft_attribute1 ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_get_utf16_name", fsntfs_test_mft_attribute_get_utf16_name, mft_attribute1 ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_compare_name_with_utf8_string", fsntfs_test_mft_attribute_compare_name_with_utf8_string, mft_attribute1 ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_compare_name_with_utf16_string", fsntfs_test_mft_attribute_compare_name_with_utf16_string, mft_attribute1 ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_get_compression_unit_size", fsntfs_test_mft_attribute_get_compression_unit_size, mft_attribute1 ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_get_resident_data", fsntfs_test_mft_attribute_get_resident_data, mft_attribute1 ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_get_number_of_data_runs", fsntfs_test_mft_attribute_get_number_of_data_runs, mft_attribute2 ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_get_data_run_by_index", fsntfs_test_mft_attribute_get_data_run_by_index, mft_attribute2 ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_get_data_extents_array", fsntfs_test_mft_attribute_get_data_extents_array, mft_attribute2 ); /* TODO add tests for libfsntfs_mft_attribute_get_next_attribute */ /* TODO add tests for libfsntfs_mft_attribute_append_to_chain */ /* Clean up */ result = libfsntfs_mft_attribute_free( &mft_attribute2, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute2", mft_attribute2 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute1", mft_attribute1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_attribute2 != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute2, NULL ); } if( mft_attribute1 != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute1, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_mft_attribute_list.c ================================================ /* * Library attribute_list type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcdata.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" #include "../libfsntfs/libfsntfs_mft_attribute_list.h" uint8_t fsntfs_test_mft_attribute_list_data1[ 368 ] = { 0x20, 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x58, 0x01, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x44, 0x43, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x53, 0x00, 0x44, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x11, 0x00, 0x24, 0x00, 0x53, 0x00, 0x44, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x10, 0x00, 0x24, 0x00, 0x53, 0x00, 0x49, 0x00, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x24, 0x00, 0x53, 0x00, 0x44, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x24, 0x00, 0x53, 0x00, 0x49, 0x00, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x24, 0x00, 0x53, 0x00, 0x44, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x24, 0x00, 0x53, 0x00, 0x49, 0x00, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_mft_attribute_list_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_list_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_mft_attribute_list_t *attribute_list = NULL; int result = 0; /* Initialize test */ result = libfsntfs_mft_attribute_list_initialize( &attribute_list, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "attribute_list", attribute_list ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_mft_attribute_list_read_data( attribute_list, &( fsntfs_test_mft_attribute_list_data1[ 24 ] ), 344, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_list_read_data( NULL, &( fsntfs_test_mft_attribute_list_data1[ 24 ] ), 344, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_read_data( attribute_list, NULL, 344, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_read_data( attribute_list, &( fsntfs_test_mft_attribute_list_data1[ 24 ] ), (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) /* Test libfsntfs_mft_attribute_list_read_data with malloc failing in libfsntfs_mft_attribute_list_entry_initialize */ fsntfs_test_malloc_attempts_before_fail = 0; result = libfsntfs_mft_attribute_list_read_data( attribute_list, &( fsntfs_test_mft_attribute_list_data1[ 24 ] ), 344, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_mft_attribute_list_free( &attribute_list, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute_list", attribute_list ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( attribute_list != NULL ) { libfsntfs_mft_attribute_list_free( &attribute_list, NULL ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_list_read_from_attribute function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_list_read_from_attribute( void ) { libcerror_error_t *error = NULL; libfsntfs_mft_attribute_list_t *attribute_list = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_mft_attribute_list_data1, 368, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_list_initialize( &attribute_list, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "attribute_list", attribute_list ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_mft_attribute_list_read_from_attribute( attribute_list, io_handle, NULL, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_list_read_from_attribute( NULL, io_handle, NULL, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_read_from_attribute( attribute_list, io_handle, NULL, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_mft_attribute_list_free( &attribute_list, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute_list", attribute_list ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( attribute_list != NULL ) { libfsntfs_mft_attribute_list_free( &attribute_list, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* TODO add tests for libfsntfs_mft_attribute_list_initialize */ /* TODO add tests for libfsntfs_mft_attribute_list_free */ /* TODO add tests for libfsntfs_mft_attribute_list_file_reference_free */ FSNTFS_TEST_RUN( "libfsntfs_mft_attribute_list_read_data", fsntfs_test_mft_attribute_list_read_data ); FSNTFS_TEST_RUN( "libfsntfs_mft_attribute_list_read_from_attribute", fsntfs_test_mft_attribute_list_read_from_attribute ); /* TODO add tests for libfsntfs_mft_attribute_list_get_number_of_entries */ /* TODO add tests for libfsntfs_mft_attribute_list_get_entry_by_index */ /* TODO add tests for libfsntfs_mft_attribute_list_compare_by_base_record_file_reference */ /* TODO add tests for libfsntfs_mft_attribute_list_get_number_of_file_references */ /* TODO add tests for libfsntfs_mft_attribute_list_get_file_reference_by_index */ /* TODO add tests for libfsntfs_mft_attribute_list_compare_file_reference */ /* TODO add tests for libfsntfs_mft_attribute_list_insert_file_reference */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_mft_attribute_list_entry.c ================================================ /* * Library mft_attribute_list_entry type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcdata.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_mft_attribute_list_entry.h" uint8_t fsntfs_test_mft_attribute_list_entry_data1[ 40 ] = { 0x80, 0x00, 0x00, 0x00, 0x28, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x53, 0x00, 0x44, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_mft_attribute_list_entry_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_list_entry_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_mft_attribute_list_entry_initialize( &mft_attribute_list_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute_list_entry", mft_attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute_list_entry", mft_attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_list_entry_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); mft_attribute_list_entry = (libfsntfs_mft_attribute_list_entry_t *) 0x12345678UL; result = libfsntfs_mft_attribute_list_entry_initialize( &mft_attribute_list_entry, &error ); mft_attribute_list_entry = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_mft_attribute_list_entry_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_mft_attribute_list_entry_initialize( &mft_attribute_list_entry, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( mft_attribute_list_entry != NULL ) { libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute_list_entry", mft_attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_mft_attribute_list_entry_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_mft_attribute_list_entry_initialize( &mft_attribute_list_entry, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( mft_attribute_list_entry != NULL ) { libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute_list_entry", mft_attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_attribute_list_entry != NULL ) { libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, NULL ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_list_entry_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_list_entry_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_mft_attribute_list_entry_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_list_entry_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_list_entry_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry = NULL; int result = 0; /* Initialize test */ result = libfsntfs_mft_attribute_list_entry_initialize( &mft_attribute_list_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute_list_entry", mft_attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_mft_attribute_list_entry_read_data( mft_attribute_list_entry, fsntfs_test_mft_attribute_list_entry_data1, 40, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_list_entry_read_data( mft_attribute_list_entry, fsntfs_test_mft_attribute_list_entry_data1, 40, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute_list_entry", mft_attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ result = libfsntfs_mft_attribute_list_entry_initialize( &mft_attribute_list_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute_list_entry", mft_attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_list_entry_read_data( NULL, fsntfs_test_mft_attribute_list_entry_data1, 40, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); mft_attribute_list_entry->name = (uint8_t *) 0x12345678UL; result = libfsntfs_mft_attribute_list_entry_read_data( mft_attribute_list_entry, fsntfs_test_mft_attribute_list_entry_data1, 40, &error ); mft_attribute_list_entry->name = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_entry_read_data( mft_attribute_list_entry, NULL, 40, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_entry_read_data( mft_attribute_list_entry, fsntfs_test_mft_attribute_list_entry_data1, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_entry_read_data( mft_attribute_list_entry, fsntfs_test_mft_attribute_list_entry_data1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) /* Test libfsntfs_mft_attribute_list_entry_read_data with malloc failing */ fsntfs_test_malloc_attempts_before_fail = 0; result = libfsntfs_mft_attribute_list_entry_read_data( mft_attribute_list_entry, fsntfs_test_mft_attribute_list_entry_data1, 40, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #if defined( OPTIMIZATION_DISABLED ) /* Test libfsntfs_mft_attribute_list_entry_read_data with memcpy failing */ fsntfs_test_memcpy_attempts_before_fail = 0; result = libfsntfs_mft_attribute_list_entry_read_data( mft_attribute_list_entry, fsntfs_test_mft_attribute_list_entry_data1, 40, &error ); if( fsntfs_test_memcpy_attempts_before_fail != -1 ) { fsntfs_test_memcpy_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( OPTIMIZATION_DISABLED ) */ #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Test error case where size value is invalid */ byte_stream_copy_from_uint16_little_endian( &( fsntfs_test_mft_attribute_list_entry_data1[ 4 ] ), 0xffff ); result = libfsntfs_mft_attribute_list_entry_read_data( mft_attribute_list_entry, fsntfs_test_mft_attribute_list_entry_data1, 40, &error ); byte_stream_copy_from_uint16_little_endian( &( fsntfs_test_mft_attribute_list_entry_data1[ 4 ] ), 0x0028 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where name offset value is invalid */ fsntfs_test_mft_attribute_list_entry_data1[ 7 ] = 0xff; result = libfsntfs_mft_attribute_list_entry_read_data( mft_attribute_list_entry, fsntfs_test_mft_attribute_list_entry_data1, 40, &error ); fsntfs_test_mft_attribute_list_entry_data1[ 7 ] = 0x1a; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where name size value is invalid */ fsntfs_test_mft_attribute_list_entry_data1[ 6 ] = 0xff; result = libfsntfs_mft_attribute_list_entry_read_data( mft_attribute_list_entry, fsntfs_test_mft_attribute_list_entry_data1, 40, &error ); fsntfs_test_mft_attribute_list_entry_data1[ 6 ] = 0x04; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute_list_entry", mft_attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_attribute_list_entry != NULL ) { libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, NULL ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_list_entry_get_attribute_type function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_list_entry_get_attribute_type( libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry ) { libcerror_error_t *error = NULL; uint32_t attribute_type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_list_entry_get_attribute_type( mft_attribute_list_entry, &attribute_type, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT32( "attribute_type", attribute_type, (uint32_t) 0x00000080UL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_list_entry_get_attribute_type( NULL, &attribute_type, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_entry_get_attribute_type( mft_attribute_list_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_list_entry_get_file_reference function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_list_entry_get_file_reference( libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry ) { libcerror_error_t *error = NULL; uint64_t file_reference = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_list_entry_get_file_reference( mft_attribute_list_entry, &file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_list_entry_get_file_reference( NULL, &file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_entry_get_file_reference( mft_attribute_list_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_list_entry_get_utf8_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_list_entry_get_utf8_name_size( libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry ) { uint8_t *name = NULL; libcerror_error_t *error = NULL; size_t utf8_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_list_entry_get_utf8_name_size( mft_attribute_list_entry, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf8_name_size", utf8_name_size, (size_t) 5 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); name = mft_attribute_list_entry->name; mft_attribute_list_entry->name = NULL; result = libfsntfs_mft_attribute_list_entry_get_utf8_name_size( mft_attribute_list_entry, &utf8_name_size, &error ); mft_attribute_list_entry->name = name; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf8_name_size", utf8_name_size, (size_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_list_entry_get_utf8_name_size( NULL, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_entry_get_utf8_name_size( mft_attribute_list_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); name = mft_attribute_list_entry->name; mft_attribute_list_entry->name = NULL; result = libfsntfs_mft_attribute_list_entry_get_utf8_name_size( mft_attribute_list_entry, NULL, &error ); mft_attribute_list_entry->name = name; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_list_entry_get_utf8_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_list_entry_get_utf8_name( libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry ) { uint8_t utf8_name[ 16 ]; uint8_t *name = NULL; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_list_entry_get_utf8_name( mft_attribute_list_entry, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_list_entry_get_utf8_name( NULL, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); name = mft_attribute_list_entry->name; mft_attribute_list_entry->name = NULL; result = libfsntfs_mft_attribute_list_entry_get_utf8_name( mft_attribute_list_entry, utf8_name, 16, &error ); mft_attribute_list_entry->name = name; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_entry_get_utf8_name( mft_attribute_list_entry, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_entry_get_utf8_name( mft_attribute_list_entry, utf8_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_entry_get_utf8_name( mft_attribute_list_entry, utf8_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_list_entry_get_utf16_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_list_entry_get_utf16_name_size( libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry ) { uint8_t *name = NULL; libcerror_error_t *error = NULL; size_t utf16_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_list_entry_get_utf16_name_size( mft_attribute_list_entry, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf16_name_size", utf16_name_size, (size_t) 5 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); name = mft_attribute_list_entry->name; mft_attribute_list_entry->name = NULL; result = libfsntfs_mft_attribute_list_entry_get_utf16_name_size( mft_attribute_list_entry, &utf16_name_size, &error ); mft_attribute_list_entry->name = name; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf16_name_size", utf16_name_size, (size_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_list_entry_get_utf16_name_size( NULL, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_entry_get_utf16_name_size( mft_attribute_list_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); name = mft_attribute_list_entry->name; mft_attribute_list_entry->name = NULL; result = libfsntfs_mft_attribute_list_entry_get_utf16_name_size( mft_attribute_list_entry, NULL, &error ); mft_attribute_list_entry->name = name; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_list_entry_get_utf16_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_list_entry_get_utf16_name( libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry ) { uint16_t utf16_name[ 16 ]; uint8_t *name = NULL; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_list_entry_get_utf16_name( mft_attribute_list_entry, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_list_entry_get_utf16_name( NULL, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); name = mft_attribute_list_entry->name; mft_attribute_list_entry->name = NULL; result = libfsntfs_mft_attribute_list_entry_get_utf16_name( mft_attribute_list_entry, utf16_name, 16, &error ); mft_attribute_list_entry->name = name; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_entry_get_utf16_name( mft_attribute_list_entry, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_entry_get_utf16_name( mft_attribute_list_entry, utf16_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_entry_get_utf16_name( mft_attribute_list_entry, utf16_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_list_entry_compare_name_with_utf8_string function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_list_entry_compare_name_with_utf8_string( libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry ) { uint8_t utf8_name1[ 5 ] = { '$', 'S', 'D', 'S', 0 }; uint8_t utf8_name2[ 6 ] = { 'b', 'o', 'g', 'u', 's', 0 }; libcerror_error_t *error = NULL; uint8_t *name = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_list_entry_compare_name_with_utf8_string( mft_attribute_list_entry, utf8_name1, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_list_entry_compare_name_with_utf8_string( mft_attribute_list_entry, utf8_name2, 5, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); name = mft_attribute_list_entry->name; mft_attribute_list_entry->name = NULL; result = libfsntfs_mft_attribute_list_entry_compare_name_with_utf8_string( mft_attribute_list_entry, utf8_name1, 4, &error ); mft_attribute_list_entry->name = name; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_list_entry_compare_name_with_utf8_string( NULL, utf8_name1, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_entry_compare_name_with_utf8_string( mft_attribute_list_entry, NULL, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_entry_compare_name_with_utf8_string( mft_attribute_list_entry, utf8_name1, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_attribute_list_entry_compare_name_with_utf16_string function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_attribute_list_entry_compare_name_with_utf16_string( libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry ) { uint16_t utf16_name1[ 5 ] = { '$', 'S', 'D', 'S', 0 }; uint16_t utf16_name2[ 6 ] = { 'b', 'o', 'g', 'u', 's', 0 }; libcerror_error_t *error = NULL; uint8_t *name = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_mft_attribute_list_entry_compare_name_with_utf16_string( mft_attribute_list_entry, utf16_name1, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_list_entry_compare_name_with_utf16_string( mft_attribute_list_entry, utf16_name2, 5, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); name = mft_attribute_list_entry->name; mft_attribute_list_entry->name = NULL; result = libfsntfs_mft_attribute_list_entry_compare_name_with_utf16_string( mft_attribute_list_entry, utf16_name1, 4, &error ); mft_attribute_list_entry->name = name; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_attribute_list_entry_compare_name_with_utf16_string( NULL, utf16_name1, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_entry_compare_name_with_utf16_string( mft_attribute_list_entry, NULL, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_attribute_list_entry_compare_name_with_utf16_string( mft_attribute_list_entry, utf16_name1, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry = NULL; int result = 0; #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_mft_attribute_list_entry_initialize", fsntfs_test_mft_attribute_list_entry_initialize ); FSNTFS_TEST_RUN( "libfsntfs_mft_attribute_list_entry_free", fsntfs_test_mft_attribute_list_entry_free ); FSNTFS_TEST_RUN( "libfsntfs_mft_attribute_list_entry_read_data", fsntfs_test_mft_attribute_list_entry_read_data ); #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize test */ result = libfsntfs_mft_attribute_list_entry_initialize( &mft_attribute_list_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute_list_entry", mft_attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_list_entry_read_data( mft_attribute_list_entry, fsntfs_test_mft_attribute_list_entry_data1, 40, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Run tests */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_list_entry_get_attribute_type", fsntfs_test_mft_attribute_list_entry_get_attribute_type, mft_attribute_list_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_list_entry_get_file_reference", fsntfs_test_mft_attribute_list_entry_get_file_reference, mft_attribute_list_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_list_entry_get_utf8_name_size", fsntfs_test_mft_attribute_list_entry_get_utf8_name_size, mft_attribute_list_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_list_entry_get_utf8_name", fsntfs_test_mft_attribute_list_entry_get_utf8_name, mft_attribute_list_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_list_entry_get_utf16_name_size", fsntfs_test_mft_attribute_list_entry_get_utf16_name_size, mft_attribute_list_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_list_entry_get_utf16_name", fsntfs_test_mft_attribute_list_entry_get_utf16_name, mft_attribute_list_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_list_entry_compare_name_with_utf8_string", fsntfs_test_mft_attribute_list_entry_compare_name_with_utf8_string, mft_attribute_list_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_attribute_list_entry_compare_name_with_utf16_string", fsntfs_test_mft_attribute_list_entry_compare_name_with_utf16_string, mft_attribute_list_entry ); /* Clean up */ result = libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute_list_entry", mft_attribute_list_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_attribute_list_entry != NULL ) { libfsntfs_mft_attribute_list_entry_free( &mft_attribute_list_entry, NULL ); } return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_mft_entry.c ================================================ /* * Library mft_entry type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_functions.h" #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_definitions.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" #include "../libfsntfs/libfsntfs_mft_entry.h" #include "../libfsntfs/libfsntfs_mft_entry_header.h" /* Define to make fsntfs_test_file generate verbose output #define FSNTFS_TEST_MFT_ENTRY_VERBOSE */ uint8_t fsntfs_test_mft_entry_data1[ 1024 ] = { 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x52, 0x51, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0xa8, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x96, 0xd5, 0x86, 0xa0, 0x08, 0x60, 0xd5, 0x01, 0x96, 0xd5, 0x86, 0xa0, 0x08, 0x60, 0xd5, 0x01, 0x96, 0xd5, 0x86, 0xa0, 0x08, 0x60, 0xd5, 0x01, 0x96, 0xd5, 0x86, 0xa0, 0x08, 0x60, 0xd5, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x96, 0xd5, 0x86, 0xa0, 0x08, 0x60, 0xd5, 0x01, 0x96, 0xd5, 0x86, 0xa0, 0x08, 0x60, 0xd5, 0x01, 0x96, 0xd5, 0x86, 0xa0, 0x08, 0x60, 0xd5, 0x01, 0x96, 0xd5, 0x86, 0xa0, 0x08, 0x60, 0xd5, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x24, 0x00, 0x4d, 0x00, 0x46, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, 0xfa, 0x00, 0x21, 0x3c, 0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0xf9, 0x00, 0x21, 0x01, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, 0xfa, 0x00, 0x21, 0x3c, 0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0xf9, 0x00, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00 }; uint8_t fsntfs_test_mft_entry_data2[ 1024 ] = { 0x46, 0x49, 0x4c, 0x45, 0x2a, 0x00, 0x03, 0x00, 0x96, 0x53, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x30, 0x00, 0x01, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xf6, 0x6e, 0xb6, 0x6b, 0xe8, 0xb3, 0xcb, 0x01, 0xf6, 0x6e, 0xb6, 0x6b, 0xe8, 0xb3, 0xcb, 0x01, 0xf6, 0x6e, 0xb6, 0x6b, 0xe8, 0xb3, 0xcb, 0x01, 0xf6, 0x6e, 0xb6, 0x6b, 0xe8, 0xb3, 0xcb, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xf6, 0x6e, 0xb6, 0x6b, 0xe8, 0xb3, 0xcb, 0x01, 0xf6, 0x6e, 0xb6, 0x6b, 0xe8, 0xb3, 0xcb, 0x01, 0xf6, 0x6e, 0xb6, 0x6b, 0xe8, 0xb3, 0xcb, 0x01, 0xf6, 0x6e, 0xb6, 0x6b, 0xe8, 0xb3, 0xcb, 0x01, 0x00, 0xcc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x24, 0x00, 0x4d, 0x00, 0x46, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x80, 0x48, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x89, 0x00, 0x12, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x89, 0x00, 0x12, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x20, 0x21, 0x19, 0x03, 0x12, 0xc6, 0x07, 0x21, 0x21, 0x7a, 0x8a, 0x09, 0x12, 0x40, 0x01, 0x7e, 0x22, 0x60, 0x02, 0x77, 0x06, 0x00, 0xc1, 0xb0, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x01, 0x41, 0x19, 0x03, 0x00, 0x0d, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_mft_entry_check_for_empty_block function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_check_for_empty_block( void ) { uint8_t mft_entry_data[ 1024 ]; libcerror_error_t *error = NULL; void *memset_result = NULL; int result = 0; /* Initialize test */ memset_result = memory_set( mft_entry_data, 0, sizeof( uint8_t ) * 1024 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "memset_result", memset_result ); /* Test regular cases */ result = libfsntfs_mft_entry_check_for_empty_block( mft_entry_data, 1024, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); mft_entry_data[ 1023 ] = 0xff; result = libfsntfs_mft_entry_check_for_empty_block( &( mft_entry_data[ 1 ] ), 1024 - 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_entry_check_for_empty_block( fsntfs_test_mft_entry_data1, 1024, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_check_for_empty_block( NULL, 1024, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_check_for_empty_block( mft_entry_data, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_entry_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 5; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_mft_entry_initialize( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_entry_free( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); mft_entry = (libfsntfs_mft_entry_t *) 0x12345678UL; result = libfsntfs_mft_entry_initialize( &mft_entry, &error ); mft_entry = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_mft_entry_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_mft_entry_initialize( &mft_entry, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( mft_entry != NULL ) { libfsntfs_mft_entry_free( &mft_entry, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_mft_entry_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_mft_entry_initialize( &mft_entry, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( mft_entry != NULL ) { libfsntfs_mft_entry_free( &mft_entry, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_entry != NULL ) { libfsntfs_mft_entry_free( &mft_entry, NULL ); } return( 0 ); } /* Tests the libfsntfs_mft_entry_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_mft_entry_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_entry_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_read_data( void ) { uint8_t mft_entry_data[ 1024 ]; libcerror_error_t *error = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; void *memcpy_result = NULL; void *memset_result = NULL; int result = 0; /* Initialize test */ memset_result = memory_set( mft_entry_data, 0, sizeof( uint8_t ) * 1024 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "memset_result", memset_result ); result = libfsntfs_mft_entry_initialize( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular case where MFT entry is empty */ result = libfsntfs_mft_entry_read_data( mft_entry, mft_entry_data, 1024, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfsntfs_mft_entry_free( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ memcpy_result = memory_copy( mft_entry_data, fsntfs_test_mft_entry_data1, sizeof( uint8_t ) * 1024 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "memcpy_result", memcpy_result ); result = libfsntfs_mft_entry_initialize( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular case where signature is "BAAD" */ byte_stream_copy_from_uint32_little_endian( &( mft_entry_data[ 0 ] ), 0x44414142UL ); result = libfsntfs_mft_entry_read_data( mft_entry, mft_entry_data, 1024, 0, &error ); byte_stream_copy_from_uint32_little_endian( &( mft_entry_data[ 0 ] ), 0x454c4946UL ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfsntfs_mft_entry_free( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ memcpy_result = memory_copy( mft_entry_data, fsntfs_test_mft_entry_data2, sizeof( uint8_t ) * 1024 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "memcpy_result", memcpy_result ); result = libfsntfs_mft_entry_initialize( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_mft_entry_read_data( mft_entry, mft_entry_data, 1024, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfsntfs_mft_entry_free( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ result = libfsntfs_mft_entry_initialize( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_mft_entry_read_data( mft_entry, mft_entry_data, 1024, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfsntfs_mft_entry_free( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ memcpy_result = memory_copy( mft_entry_data, fsntfs_test_mft_entry_data1, sizeof( uint8_t ) * 1024 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "memcpy_result", memcpy_result ); result = libfsntfs_mft_entry_initialize( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test where signature is invalid */ byte_stream_copy_from_uint32_little_endian( &( mft_entry_data[ 0 ] ), 0xffffffffUL ); result = libfsntfs_mft_entry_read_data( mft_entry, mft_entry_data, 1024, 0, &error ); byte_stream_copy_from_uint32_little_endian( &( mft_entry_data[ 0 ] ), 0x454c4946UL ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfsntfs_mft_entry_free( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ memcpy_result = memory_copy( mft_entry_data, fsntfs_test_mft_entry_data1, sizeof( uint8_t ) * 1024 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "memcpy_result", memcpy_result ); result = libfsntfs_mft_entry_initialize( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_read_data( NULL, mft_entry_data, 1024, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); mft_entry->header = (libfsntfs_mft_entry_header_t *) 0x12345678UL; result = libfsntfs_mft_entry_read_data( mft_entry, mft_entry_data, 1024, 0, &error ); mft_entry->header = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_read_data( mft_entry, NULL, 1024, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_read_data( mft_entry, mft_entry_data, (size_t) SSIZE_MAX + 1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_read_data( mft_entry, mft_entry_data, 0, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) /* Test libfsntfs_mft_entry_read_data with malloc failing in libfsntfs_mft_entry_header_initialize */ fsntfs_test_malloc_attempts_before_fail = 0; result = libfsntfs_mft_entry_read_data( mft_entry, mft_entry_data, 1024, 0, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_mft_entry_free( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_entry != NULL ) { libfsntfs_mft_entry_free( &mft_entry, NULL ); } return( 0 ); } /* Tests the libfsntfs_mft_entry_read_file_io_handle function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_read_file_io_handle( void ) { uint8_t mft_entry_data[ 1024 ]; libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; void *memcpy_result = NULL; void *memset_result = NULL; int result = 0; /* Initialize test */ result = libfsntfs_mft_entry_initialize( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize file IO handle */ memset_result = memory_set( mft_entry_data, 0, sizeof( uint8_t ) * 1024 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "memset_result", memset_result ); result = fsntfs_test_open_file_io_handle( &file_io_handle, mft_entry_data, 1024, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_mft_entry_read_file_io_handle( mft_entry, file_io_handle, 0, 1024, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up file IO handle */ result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize file IO handle */ memcpy_result = memory_copy( mft_entry_data, fsntfs_test_mft_entry_data1, sizeof( uint8_t ) * 1024 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "memcpy_result", memcpy_result ); result = fsntfs_test_open_file_io_handle( &file_io_handle, mft_entry_data, 1024, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_mft_entry_read_file_io_handle( mft_entry, file_io_handle, 0, 1024, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_read_file_io_handle( mft_entry, file_io_handle, 0, 1024, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_mft_entry_free( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ result = libfsntfs_mft_entry_initialize( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_read_file_io_handle( NULL, file_io_handle, 0, 1024, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_read_file_io_handle( mft_entry, NULL, 0, 1024, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_read_file_io_handle( mft_entry, file_io_handle, -1, 1024, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test MFT entry size too small */ result = libfsntfs_mft_entry_read_file_io_handle( mft_entry, file_io_handle, 0, 8, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) /* Test libfsntfs_mft_entry_read_file_io_handle with malloc failing */ fsntfs_test_malloc_attempts_before_fail = 0; result = libfsntfs_mft_entry_read_file_io_handle( mft_entry, file_io_handle, 0, 1024, 0, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up file IO handle */ result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test data too small */ result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_mft_entry_data1, 8, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_entry_read_file_io_handle( mft_entry, file_io_handle, 0, 1024, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfsntfs_mft_entry_free( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } if( mft_entry != NULL ) { libfsntfs_mft_entry_free( &mft_entry, NULL ); } return( 0 ); } /* Tests the libfsntfs_mft_entry_read_attributes_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_read_attributes_data( void ) { uint8_t mft_entry_data[ 1024 ]; libcerror_error_t *error = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; void *memcpy_result = NULL; int result = 0; /* Initialize test */ memcpy_result = memory_copy( mft_entry_data, fsntfs_test_mft_entry_data1, sizeof( uint8_t ) * 1024 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "memcpy_result", memcpy_result ); result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_entry_initialize( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_entry_read_data( mft_entry, mft_entry_data, 1024, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_mft_entry_read_attributes_data( mft_entry, io_handle, mft_entry_data, 1024, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_read_attributes_data( NULL, io_handle, mft_entry_data, 1024, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_read_attributes_data( mft_entry, io_handle, NULL, 1024, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_read_attributes_data( mft_entry, io_handle, mft_entry_data, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_read_attributes_data( mft_entry, io_handle, mft_entry_data, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_mft_entry_free( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_entry != NULL ) { libfsntfs_mft_entry_free( &mft_entry, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* TODO: add tests for libfsntfs_mft_entry_read_attributes */ /* TODO: add tests for libfsntfs_mft_entry_read_attributes_from_attribute_list */ /* Tests the libfsntfs_mft_entry_is_empty function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_is_empty( libfsntfs_mft_entry_t *mft_entry ) { libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_mft_entry_is_empty( mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_is_empty( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_entry_is_allocated function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_is_allocated( libfsntfs_mft_entry_t *mft_entry ) { libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_mft_entry_is_allocated( mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_is_allocated( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_entry_get_file_reference function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_get_file_reference( libfsntfs_mft_entry_t *mft_entry ) { libcerror_error_t *error = NULL; uint64_t file_reference = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_entry_get_file_reference( mft_entry, &file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_get_file_reference( NULL, &file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_get_file_reference( mft_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_entry_get_base_record_file_reference function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_get_base_record_file_reference( libfsntfs_mft_entry_t *mft_entry ) { libcerror_error_t *error = NULL; uint64_t base_record_file_reference = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_entry_get_base_record_file_reference( mft_entry, &base_record_file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_get_base_record_file_reference( NULL, &base_record_file_reference, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_get_base_record_file_reference( mft_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_entry_get_journal_sequence_number function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_get_journal_sequence_number( libfsntfs_mft_entry_t *mft_entry ) { libcerror_error_t *error = NULL; uint64_t journal_sequence_number = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_entry_get_journal_sequence_number( mft_entry, &journal_sequence_number, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_get_journal_sequence_number( NULL, &journal_sequence_number, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_get_journal_sequence_number( mft_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_entry_get_number_of_attributes function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_get_number_of_attributes( libfsntfs_mft_entry_t *mft_entry ) { libcerror_error_t *error = NULL; int number_of_attributes = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_entry_get_number_of_attributes( mft_entry, &number_of_attributes, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "number_of_attributes", number_of_attributes, 4 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_get_number_of_attributes( NULL, &number_of_attributes, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_get_number_of_attributes( mft_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: return( 0 ); } /* Tests the libfsntfs_mft_entry_get_attribute_by_index function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_get_attribute_by_index( libfsntfs_mft_entry_t *mft_entry ) { libcerror_error_t *error = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_mft_entry_get_attribute_by_index( mft_entry, 0, &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_get_attribute_by_index( NULL, 0, &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_get_attribute_by_index( mft_entry, -1, &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_get_attribute_by_index( mft_entry, 0, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: return( 0 ); } /* Tests the libfsntfs_mft_entry_get_number_of_alternate_data_attributes function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_get_number_of_alternate_data_attributes( libfsntfs_mft_entry_t *mft_entry ) { libcerror_error_t *error = NULL; int number_of_attributes = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_entry_get_number_of_alternate_data_attributes( mft_entry, &number_of_attributes, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "number_of_attributes", number_of_attributes, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_get_number_of_alternate_data_attributes( NULL, &number_of_attributes, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_get_number_of_alternate_data_attributes( mft_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_entry_get_alternate_data_attribute_by_index function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_get_alternate_data_attribute_by_index( libfsntfs_mft_entry_t *mft_entry ) { libcerror_error_t *error = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; /* Test regular cases */ /* TODO change test data and enable test result = libfsntfs_mft_entry_get_alternate_data_attribute_by_index( mft_entry, 0, &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); */ /* Test error cases */ result = libfsntfs_mft_entry_get_alternate_data_attribute_by_index( NULL, 0, &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_get_alternate_data_attribute_by_index( mft_entry, -1, &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_get_alternate_data_attribute_by_index( mft_entry, 0, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: return( 0 ); } /* TODO: add tests for libfsntfs_mft_entry_get_alternate_data_attribute_by_utf8_name */ /* TODO: add tests for libfsntfs_mft_entry_get_alternate_data_attribute_by_utf16_name */ /* TODO: add tests for libfsntfs_mft_entry_set_attribute_helper_values */ /* TODO: add tests for libfsntfs_mft_entry_set_data_attribute_helper_values */ /* TODO: add tests for libfsntfs_mft_entry_get_data_attribute_by_utf8_name */ /* TODO: add tests for libfsntfs_mft_entry_has_directory_entries_index */ /* TODO: add tests for libfsntfs_mft_entry_read_element_data */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) uint8_t mft_entry_data[ 1024 ]; libcerror_error_t *error = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; void *memcpy_result = NULL; int result = 0; #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( HAVE_DEBUG_OUTPUT ) && defined( FSNTFS_TEST_MFT_ENTRY_VERBOSE ) libfsntfs_notify_set_verbose( 1 ); libfsntfs_notify_set_stream( stderr, NULL ); #endif #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_mft_entry_check_for_empty_block", fsntfs_test_mft_entry_check_for_empty_block ); FSNTFS_TEST_RUN( "libfsntfs_mft_entry_initialize", fsntfs_test_mft_entry_initialize ); FSNTFS_TEST_RUN( "libfsntfs_mft_entry_free", fsntfs_test_mft_entry_free ); FSNTFS_TEST_RUN( "libfsntfs_mft_entry_read_data", fsntfs_test_mft_entry_read_data ); FSNTFS_TEST_RUN( "libfsntfs_mft_entry_read_file_io_handle", fsntfs_test_mft_entry_read_file_io_handle ); FSNTFS_TEST_RUN( "libfsntfs_mft_entry_read_attributes_data", fsntfs_test_mft_entry_read_attributes_data ); /* TODO: add tests for libfsntfs_mft_entry_read_attributes */ /* TODO: add tests for libfsntfs_mft_entry_read_attributes_from_attribute_list */ #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize test */ memcpy_result = memory_copy( mft_entry_data, fsntfs_test_mft_entry_data1, sizeof( uint8_t ) * 1024 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "memcpy_result", memcpy_result ); result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_entry_initialize( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_entry_read_data( mft_entry, mft_entry_data, 1024, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_entry_read_attributes_data( mft_entry, io_handle, mft_entry_data, 1024, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Run tests */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_entry_is_empty", fsntfs_test_mft_entry_is_empty, mft_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_entry_is_allocated", fsntfs_test_mft_entry_is_allocated, mft_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_entry_get_file_reference", fsntfs_test_mft_entry_get_file_reference, mft_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_entry_get_base_record_file_reference", fsntfs_test_mft_entry_get_base_record_file_reference, mft_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_entry_get_journal_sequence_number", fsntfs_test_mft_entry_get_journal_sequence_number, mft_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_entry_get_number_of_attributes", fsntfs_test_mft_entry_get_number_of_attributes, mft_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_entry_get_attribute_by_index", fsntfs_test_mft_entry_get_attribute_by_index, mft_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_entry_get_number_of_alternate_data_attributes", fsntfs_test_mft_entry_get_number_of_alternate_data_attributes, mft_entry ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_entry_get_alternate_data_attribute_by_index", fsntfs_test_mft_entry_get_alternate_data_attribute_by_index, mft_entry ); /* TODO: add tests for libfsntfs_mft_entry_get_alternate_data_attribute_by_utf8_name */ /* TODO: add tests for libfsntfs_mft_entry_get_alternate_data_attribute_by_utf16_name */ /* TODO: add tests for libfsntfs_mft_entry_set_attribute_helper_values */ /* TODO: add tests for libfsntfs_mft_entry_set_data_attribute_helper_values */ /* TODO: add tests for libfsntfs_mft_entry_get_data_attribute_by_utf8_name */ /* TODO: add tests for libfsntfs_mft_entry_has_directory_entries_index */ /* TODO: add tests for libfsntfs_mft_entry_read_element_data */ /* Clean up */ result = libfsntfs_mft_entry_free( &mft_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_entry != NULL ) { libfsntfs_mft_entry_free( &mft_entry, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_mft_entry_header.c ================================================ /* * Library mft_entry_header type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_mft_entry_header.h" uint8_t fsntfs_test_mft_entry_header_data1[ 48 ] = { 0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x98, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t fsntfs_test_mft_entry_header_data2[ 42 ] = { 0x46, 0x49, 0x4c, 0x45, 0x2a, 0x00, 0x03, 0x00, 0x96, 0x53, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x30, 0x00, 0x01, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_mft_entry_header_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_header_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_mft_entry_header_t *mft_entry_header = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_mft_entry_header_initialize( &mft_entry_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_entry_header", mft_entry_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_entry_header_free( &mft_entry_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_entry_header", mft_entry_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_header_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); mft_entry_header = (libfsntfs_mft_entry_header_t *) 0x12345678UL; result = libfsntfs_mft_entry_header_initialize( &mft_entry_header, &error ); mft_entry_header = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_mft_entry_header_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_mft_entry_header_initialize( &mft_entry_header, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( mft_entry_header != NULL ) { libfsntfs_mft_entry_header_free( &mft_entry_header, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_entry_header", mft_entry_header ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_mft_entry_header_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_mft_entry_header_initialize( &mft_entry_header, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( mft_entry_header != NULL ) { libfsntfs_mft_entry_header_free( &mft_entry_header, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_entry_header", mft_entry_header ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_entry_header != NULL ) { libfsntfs_mft_entry_header_free( &mft_entry_header, NULL ); } return( 0 ); } /* Tests the libfsntfs_mft_entry_header_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_header_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_mft_entry_header_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_entry_header_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_header_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_mft_entry_header_t *mft_entry_header = NULL; int result = 0; /* Initialize test */ result = libfsntfs_mft_entry_header_initialize( &mft_entry_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_entry_header", mft_entry_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_mft_entry_header_read_data( mft_entry_header, fsntfs_test_mft_entry_header_data1, 48, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "mft_entry_header->is_bad", mft_entry_header->is_bad, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_entry_header_read_data( mft_entry_header, fsntfs_test_mft_entry_header_data2, 42, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "mft_entry_header->is_bad", mft_entry_header->is_bad, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular case where signature is "BAAD" */ byte_stream_copy_from_uint32_little_endian( &( fsntfs_test_mft_entry_header_data1[ 0 ] ), 0x44414142UL ); result = libfsntfs_mft_entry_header_read_data( mft_entry_header, fsntfs_test_mft_entry_header_data1, 48, &error ); byte_stream_copy_from_uint32_little_endian( &( fsntfs_test_mft_entry_header_data1[ 0 ] ), 0x454c4946UL ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "mft_entry_header->is_bad", mft_entry_header->is_bad, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_header_read_data( NULL, fsntfs_test_mft_entry_header_data1, 48, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_header_read_data( mft_entry_header, NULL, 48, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_header_read_data( mft_entry_header, fsntfs_test_mft_entry_header_data1, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_header_read_data( mft_entry_header, fsntfs_test_mft_entry_header_data1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where signature is invalid */ byte_stream_copy_from_uint32_little_endian( &( fsntfs_test_mft_entry_header_data1[ 0 ] ), 0xffffffffUL ); result = libfsntfs_mft_entry_header_read_data( mft_entry_header, fsntfs_test_mft_entry_header_data1, 48, &error ); byte_stream_copy_from_uint32_little_endian( &( fsntfs_test_mft_entry_header_data1[ 0 ] ), 0x454c4946UL ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfsntfs_mft_entry_header_free( &mft_entry_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_entry_header", mft_entry_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_entry_header != NULL ) { libfsntfs_mft_entry_header_free( &mft_entry_header, NULL ); } return( 0 ); } /* Tests the libfsntfs_mft_entry_header_get_fixup_values_offset function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_header_get_fixup_values_offset( libfsntfs_mft_entry_header_t *mft_entry_header ) { libcerror_error_t *error = NULL; uint16_t fixup_values_offset = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_entry_header_get_fixup_values_offset( mft_entry_header, &fixup_values_offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT16( "fixup_values_offset", fixup_values_offset, 48 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_header_get_fixup_values_offset( NULL, &fixup_values_offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_header_get_fixup_values_offset( mft_entry_header, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_entry_header_get_number_of_fixup_values function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_header_get_number_of_fixup_values( libfsntfs_mft_entry_header_t *mft_entry_header ) { libcerror_error_t *error = NULL; uint16_t number_of_fixup_values = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_entry_header_get_number_of_fixup_values( mft_entry_header, &number_of_fixup_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT16( "number_of_fixup_values", number_of_fixup_values, 3 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_header_get_number_of_fixup_values( NULL, &number_of_fixup_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_header_get_number_of_fixup_values( mft_entry_header, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_entry_header_get_attributes_offset function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_header_get_attributes_offset( libfsntfs_mft_entry_header_t *mft_entry_header ) { libcerror_error_t *error = NULL; uint16_t attributes_offset = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_entry_header_get_attributes_offset( mft_entry_header, &attributes_offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT16( "attributes_offset", attributes_offset, 56 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_header_get_attributes_offset( NULL, &attributes_offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_header_get_attributes_offset( mft_entry_header, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_entry_header_get_used_entry_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_header_get_used_entry_size( libfsntfs_mft_entry_header_t *mft_entry_header ) { libcerror_error_t *error = NULL; uint32_t used_entry_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_entry_header_get_used_entry_size( mft_entry_header, &used_entry_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT16( "used_entry_size", used_entry_size, 408 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_header_get_used_entry_size( NULL, &used_entry_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_header_get_used_entry_size( mft_entry_header, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_entry_header_get_total_entry_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_entry_header_get_total_entry_size( libfsntfs_mft_entry_header_t *mft_entry_header ) { libcerror_error_t *error = NULL; uint32_t total_entry_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_entry_header_get_total_entry_size( mft_entry_header, &total_entry_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT16( "total_entry_size", total_entry_size, 1024 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_entry_header_get_total_entry_size( NULL, &total_entry_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_entry_header_get_total_entry_size( mft_entry_header, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_mft_entry_header_t *mft_entry_header = NULL; int result = 0; #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_mft_entry_header_initialize", fsntfs_test_mft_entry_header_initialize ); FSNTFS_TEST_RUN( "libfsntfs_mft_entry_header_free", fsntfs_test_mft_entry_header_free ); FSNTFS_TEST_RUN( "libfsntfs_mft_entry_header_read_data", fsntfs_test_mft_entry_header_read_data ); #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize test */ result = libfsntfs_mft_entry_header_initialize( &mft_entry_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_entry_header", mft_entry_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_entry_header_read_data( mft_entry_header, fsntfs_test_mft_entry_header_data1, 48, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Run tests */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_entry_header_get_fixup_values_offset", fsntfs_test_mft_entry_header_get_fixup_values_offset, mft_entry_header ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_entry_header_get_number_of_fixup_values", fsntfs_test_mft_entry_header_get_number_of_fixup_values, mft_entry_header ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_entry_header_get_attributes_offset", fsntfs_test_mft_entry_header_get_attributes_offset, mft_entry_header ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_entry_header_get_used_entry_size", fsntfs_test_mft_entry_header_get_used_entry_size, mft_entry_header ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_entry_header_get_total_entry_size", fsntfs_test_mft_entry_header_get_total_entry_size, mft_entry_header ); /* Clean up */ result = libfsntfs_mft_entry_header_free( &mft_entry_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_entry_header", mft_entry_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_entry_header != NULL ) { libfsntfs_mft_entry_header_free( &mft_entry_header, NULL ); } return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_mft_metadata_file.c ================================================ /* * Library mft_metadata_file type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_functions.h" #include "fsntfs_test_getopt.h" #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libclocale.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_libuna.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "../libfsntfs/libfsntfs_mft_metadata_file.h" #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) && SIZEOF_WCHAR_T != 2 && SIZEOF_WCHAR_T != 4 #error Unsupported size of wchar_t #endif /* Define to make fsntfs_test_mft_metadata_file generate verbose output #define FSNTFS_TEST_MFT_METADATA_FILE_VERBOSE */ #if !defined( LIBFSNTFS_HAVE_BFIO ) LIBFSNTFS_EXTERN \ int libfsntfs_check_mft_metadata_file_signature_file_io_handle( libbfio_handle_t *file_io_handle, libfsntfs_error_t **error ); #endif /* !defined( LIBFSNTFS_HAVE_BFIO ) */ /* Creates and opens a source MFT metadata file * Returns 1 if successful or -1 on error */ int fsntfs_test_mft_metadata_file_open_source( libfsntfs_mft_metadata_file_t **mft_metadata_file, libbfio_handle_t *file_io_handle, libcerror_error_t **error ) { static char *function = "fsntfs_test_mft_metadata_file_open_source"; int result = 0; if( mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } if( file_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file IO handle.", function ); return( -1 ); } if( libfsntfs_mft_metadata_file_initialize( mft_metadata_file, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize MFT metadata file.", function ); goto on_error; } result = libfsntfs_mft_metadata_file_open_file_io_handle( *mft_metadata_file, file_io_handle, LIBFSNTFS_OPEN_READ, error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open MFT metadata file.", function ); goto on_error; } return( 1 ); on_error: if( *mft_metadata_file != NULL ) { libfsntfs_mft_metadata_file_free( mft_metadata_file, NULL ); } return( -1 ); } /* Closes and frees a source MFT metadata file * Returns 1 if successful or -1 on error */ int fsntfs_test_mft_metadata_file_close_source( libfsntfs_mft_metadata_file_t **mft_metadata_file, libcerror_error_t **error ) { static char *function = "fsntfs_test_mft_metadata_file_close_source"; int result = 0; if( mft_metadata_file == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid MFT metadata file.", function ); return( -1 ); } if( libfsntfs_mft_metadata_file_close( *mft_metadata_file, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close MFT metadata file.", function ); result = -1; } if( libfsntfs_mft_metadata_file_free( mft_metadata_file, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free MFT metadata file.", function ); result = -1; } return( result ); } /* Tests the libfsntfs_mft_metadata_file_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_metadata_file_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_mft_metadata_file_t *mft_metadata_file = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_mft_metadata_file_initialize( &mft_metadata_file, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_metadata_file", mft_metadata_file ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_metadata_file_free( &mft_metadata_file, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_metadata_file", mft_metadata_file ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_metadata_file_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); mft_metadata_file = (libfsntfs_mft_metadata_file_t *) 0x12345678UL; result = libfsntfs_mft_metadata_file_initialize( &mft_metadata_file, &error ); mft_metadata_file = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_mft_metadata_file_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_mft_metadata_file_initialize( &mft_metadata_file, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( mft_metadata_file != NULL ) { libfsntfs_mft_metadata_file_free( &mft_metadata_file, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_metadata_file", mft_metadata_file ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_mft_metadata_file_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_mft_metadata_file_initialize( &mft_metadata_file, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( mft_metadata_file != NULL ) { libfsntfs_mft_metadata_file_free( &mft_metadata_file, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_metadata_file", mft_metadata_file ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_metadata_file != NULL ) { libfsntfs_mft_metadata_file_free( &mft_metadata_file, NULL ); } return( 0 ); } /* Tests the libfsntfs_mft_metadata_file_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_metadata_file_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_mft_metadata_file_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_metadata_file_open function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_metadata_file_open( const system_character_t *source ) { char narrow_source[ 256 ]; libcerror_error_t *error = NULL; libfsntfs_mft_metadata_file_t *mft_metadata_file = NULL; int result = 0; /* Initialize test */ result = fsntfs_test_get_narrow_source( source, narrow_source, 256, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_metadata_file_initialize( &mft_metadata_file, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_metadata_file", mft_metadata_file ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test open */ result = libfsntfs_mft_metadata_file_open( mft_metadata_file, narrow_source, LIBFSNTFS_OPEN_READ, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_metadata_file_open( mft_metadata_file, narrow_source, LIBFSNTFS_OPEN_READ, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_mft_metadata_file_free( &mft_metadata_file, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_metadata_file", mft_metadata_file ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_metadata_file != NULL ) { libfsntfs_mft_metadata_file_free( &mft_metadata_file, NULL ); } return( 0 ); } #if defined( HAVE_WIDE_CHARACTER_TYPE ) /* Tests the libfsntfs_mft_metadata_file_open_wide function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_metadata_file_open_wide( const system_character_t *source ) { wchar_t wide_source[ 256 ]; libcerror_error_t *error = NULL; libfsntfs_mft_metadata_file_t *mft_metadata_file = NULL; int result = 0; /* Initialize test */ result = fsntfs_test_get_wide_source( source, wide_source, 256, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_metadata_file_initialize( &mft_metadata_file, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_metadata_file", mft_metadata_file ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test open */ result = libfsntfs_mft_metadata_file_open_wide( mft_metadata_file, wide_source, LIBFSNTFS_OPEN_READ, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_metadata_file_open_wide( mft_metadata_file, wide_source, LIBFSNTFS_OPEN_READ, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_mft_metadata_file_free( &mft_metadata_file, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_metadata_file", mft_metadata_file ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_metadata_file != NULL ) { libfsntfs_mft_metadata_file_free( &mft_metadata_file, NULL ); } return( 0 ); } #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */ /* Tests the libfsntfs_mft_metadata_file_close function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_metadata_file_close( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_mft_metadata_file_close( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_metadata_file_open and libfsntfs_mft_metadata_file_close functions * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_metadata_file_open_close( const system_character_t *source ) { libcerror_error_t *error = NULL; libfsntfs_mft_metadata_file_t *mft_metadata_file = NULL; int result = 0; /* Initialize test */ result = libfsntfs_mft_metadata_file_initialize( &mft_metadata_file, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_metadata_file", mft_metadata_file ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test open and close */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_mft_metadata_file_open_wide( mft_metadata_file, source, LIBFSNTFS_OPEN_READ, &error ); #else result = libfsntfs_mft_metadata_file_open( mft_metadata_file, source, LIBFSNTFS_OPEN_READ, &error ); #endif FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_metadata_file_close( mft_metadata_file, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test open and close a second time to validate clean up on close */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_mft_metadata_file_open_wide( mft_metadata_file, source, LIBFSNTFS_OPEN_READ, &error ); #else result = libfsntfs_mft_metadata_file_open( mft_metadata_file, source, LIBFSNTFS_OPEN_READ, &error ); #endif FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_metadata_file_close( mft_metadata_file, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfsntfs_mft_metadata_file_free( &mft_metadata_file, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_metadata_file", mft_metadata_file ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_metadata_file != NULL ) { libfsntfs_mft_metadata_file_free( &mft_metadata_file, NULL ); } return( 0 ); } /* Tests the libfsntfs_mft_metadata_file_signal_abort function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_metadata_file_signal_abort( libfsntfs_mft_metadata_file_t *mft_metadata_file ) { libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_mft_metadata_file_signal_abort( mft_metadata_file, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_mft_metadata_file_signal_abort( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_metadata_file_get_utf8_volume_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_metadata_file_get_utf8_volume_name_size( libfsntfs_mft_metadata_file_t *mft_metadata_file ) { libcerror_error_t *error = NULL; size_t utf8_volume_name_size = 0; int result = 0; int utf8_volume_name_size_is_set = 0; /* Test regular cases */ result = libfsntfs_mft_metadata_file_get_utf8_volume_name_size( mft_metadata_file, &utf8_volume_name_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf8_volume_name_size_is_set = result; /* Test error cases */ result = libfsntfs_mft_metadata_file_get_utf8_volume_name_size( NULL, &utf8_volume_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf8_volume_name_size_is_set != 0 ) { result = libfsntfs_mft_metadata_file_get_utf8_volume_name_size( mft_metadata_file, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_metadata_file_get_utf8_volume_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_metadata_file_get_utf8_volume_name( libfsntfs_mft_metadata_file_t *mft_metadata_file ) { uint8_t utf8_volume_name[ 512 ]; libcerror_error_t *error = NULL; int result = 0; int utf8_volume_name_is_set = 0; /* Test regular cases */ result = libfsntfs_mft_metadata_file_get_utf8_volume_name( mft_metadata_file, utf8_volume_name, 512, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf8_volume_name_is_set = result; /* Test error cases */ result = libfsntfs_mft_metadata_file_get_utf8_volume_name( NULL, utf8_volume_name, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf8_volume_name_is_set != 0 ) { result = libfsntfs_mft_metadata_file_get_utf8_volume_name( mft_metadata_file, NULL, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_metadata_file_get_utf8_volume_name( mft_metadata_file, utf8_volume_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_metadata_file_get_utf8_volume_name( mft_metadata_file, utf8_volume_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_metadata_file_get_utf16_volume_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_metadata_file_get_utf16_volume_name_size( libfsntfs_mft_metadata_file_t *mft_metadata_file ) { libcerror_error_t *error = NULL; size_t utf16_volume_name_size = 0; int result = 0; int utf16_volume_name_size_is_set = 0; /* Test regular cases */ result = libfsntfs_mft_metadata_file_get_utf16_volume_name_size( mft_metadata_file, &utf16_volume_name_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf16_volume_name_size_is_set = result; /* Test error cases */ result = libfsntfs_mft_metadata_file_get_utf16_volume_name_size( NULL, &utf16_volume_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf16_volume_name_size_is_set != 0 ) { result = libfsntfs_mft_metadata_file_get_utf16_volume_name_size( mft_metadata_file, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_metadata_file_get_utf16_volume_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_metadata_file_get_utf16_volume_name( libfsntfs_mft_metadata_file_t *mft_metadata_file ) { uint16_t utf16_volume_name[ 512 ]; libcerror_error_t *error = NULL; int result = 0; int utf16_volume_name_is_set = 0; /* Test regular cases */ result = libfsntfs_mft_metadata_file_get_utf16_volume_name( mft_metadata_file, utf16_volume_name, 512, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf16_volume_name_is_set = result; /* Test error cases */ result = libfsntfs_mft_metadata_file_get_utf16_volume_name( NULL, utf16_volume_name, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf16_volume_name_is_set != 0 ) { result = libfsntfs_mft_metadata_file_get_utf16_volume_name( mft_metadata_file, NULL, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_metadata_file_get_utf16_volume_name( mft_metadata_file, utf16_volume_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_mft_metadata_file_get_utf16_volume_name( mft_metadata_file, utf16_volume_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_mft_metadata_file_get_number_of_file_entries function * Returns 1 if successful or 0 if not */ int fsntfs_test_mft_metadata_file_get_number_of_file_entries( libfsntfs_mft_metadata_file_t *mft_metadata_file ) { libcerror_error_t *error = NULL; uint64_t number_of_file_entries = 0; int number_of_file_entries_is_set = 0; int result = 0; /* Test regular cases */ result = libfsntfs_mft_metadata_file_get_number_of_file_entries( mft_metadata_file, &number_of_file_entries, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); number_of_file_entries_is_set = result; /* Test error cases */ result = libfsntfs_mft_metadata_file_get_number_of_file_entries( NULL, &number_of_file_entries, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( number_of_file_entries_is_set != 0 ) { result = libfsntfs_mft_metadata_file_get_number_of_file_entries( mft_metadata_file, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc, wchar_t * const argv[] ) #else int main( int argc, char * const argv[] ) #endif { libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_mft_metadata_file_t *mft_metadata_file = NULL; system_character_t *option_offset = NULL; system_character_t *source = NULL; system_integer_t option = 0; size_t string_length = 0; off64_t mft_metadata_file_offset = 0; int result = 0; while( ( option = fsntfs_test_getopt( argc, argv, _SYSTEM_STRING( "o:" ) ) ) != (system_integer_t) -1 ) { switch( option ) { case (system_integer_t) '?': default: fprintf( stderr, "Invalid argument: %" PRIs_SYSTEM ".\n", argv[ optind - 1 ] ); return( EXIT_FAILURE ); case (system_integer_t) 'o': option_offset = optarg; break; } } if( optind < argc ) { source = argv[ optind ]; } if( option_offset != NULL ) { string_length = system_string_length( option_offset ); result = fsntfs_test_system_string_copy_from_64_bit_in_decimal( option_offset, string_length + 1, (uint64_t *) &mft_metadata_file_offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } #if defined( HAVE_DEBUG_OUTPUT ) && defined( FSNTFS_TEST_MFT_METADATA_FILE_VERBOSE ) libfsntfs_notify_set_verbose( 1 ); libfsntfs_notify_set_stream( stderr, NULL ); #endif FSNTFS_TEST_RUN( "libfsntfs_mft_metadata_file_initialize", fsntfs_test_mft_metadata_file_initialize ); FSNTFS_TEST_RUN( "libfsntfs_mft_metadata_file_free", fsntfs_test_mft_metadata_file_free ); #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) if( source != NULL ) { result = libbfio_file_range_initialize( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); string_length = system_string_length( source ); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libbfio_file_range_set_name_wide( file_io_handle, source, string_length, &error ); #else result = libbfio_file_range_set_name( file_io_handle, source, string_length, &error ); #endif FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libbfio_file_range_set( file_io_handle, mft_metadata_file_offset, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_check_mft_metadata_file_signature_file_io_handle( file_io_handle, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } if( ( result != 0 ) && ( mft_metadata_file_offset == 0 ) ) { FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_metadata_file_open", fsntfs_test_mft_metadata_file_open, source ); #if defined( HAVE_WIDE_CHARACTER_TYPE ) FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_metadata_file_open_wide", fsntfs_test_mft_metadata_file_open_wide, source ); #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */ #if defined( LIBFSNTFS_HAVE_BFIO ) /* TODO add test for libfsntfs_mft_metadata_file_open_file_io_handle */ #endif /* defined( LIBFSNTFS_HAVE_BFIO ) */ FSNTFS_TEST_RUN( "libfsntfs_mft_metadata_file_close", fsntfs_test_mft_metadata_file_close ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_metadata_file_open_close", fsntfs_test_mft_metadata_file_open_close, source ); } if( result != 0 ) { /* Initialize test */ result = fsntfs_test_mft_metadata_file_open_source( &mft_metadata_file, file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_metadata_file", mft_metadata_file ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_metadata_file_signal_abort", fsntfs_test_mft_metadata_file_signal_abort, mft_metadata_file ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* TODO: add tests for libfsntfs_mft_metadata_file_open_read */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_metadata_file_get_utf8_volume_name_size", fsntfs_test_mft_metadata_file_get_utf8_volume_name_size, mft_metadata_file ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_metadata_file_get_utf8_volume_name", fsntfs_test_mft_metadata_file_get_utf8_volume_name, mft_metadata_file ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_metadata_file_get_utf16_volume_name_size", fsntfs_test_mft_metadata_file_get_utf16_volume_name_size, mft_metadata_file ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_metadata_file_get_utf16_volume_name", fsntfs_test_mft_metadata_file_get_utf16_volume_name, mft_metadata_file ); /* TODO: add tests for libfsntfs_mft_metadata_file_get_volume_version */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_mft_metadata_file_get_number_of_file_entries", fsntfs_test_mft_metadata_file_get_number_of_file_entries, mft_metadata_file ); /* TODO: add tests for libfsntfs_mft_metadata_file_get_file_entry_by_index */ /* Clean up */ result = fsntfs_test_mft_metadata_file_close_source( &mft_metadata_file, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_metadata_file", mft_metadata_file ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } if( file_io_handle != NULL ) { result = libbfio_handle_free( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ return( EXIT_SUCCESS ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( mft_metadata_file != NULL ) { fsntfs_test_mft_metadata_file_close_source( &mft_metadata_file, NULL ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } return( EXIT_FAILURE ); } ================================================ FILE: tests/fsntfs_test_name.c ================================================ /* * Library name functions test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_libuna.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_name.h" #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_name_compare function * Returns 1 if successful or 0 if not */ int fsntfs_test_name_compare( void ) { uint8_t utf16_stream_equal[ 12 ] = { 'e', 0, 'q', 0, 'u', 0, 'a', 0, 'l', 0, 0 }; uint8_t utf16_stream_equal_upper[ 12 ] = { 'E', 0, 'Q', 0, 'U', 0, 'A', 0, 'L', 0, 0 }; uint8_t utf16_stream_great[ 12 ] = { 'g', 0, 'r', 0, 'e', 0, 'a', 0, 't', 0, 0, 0 }; uint8_t utf16_stream_greater[ 16 ] = { 'g', 0, 'r', 0, 'e', 0, 'a', 0, 't', 0, 'e', 0, 'r', 0, 0, 0 }; uint8_t utf16_stream_less[ 10 ] = { 'l', 0, 'e', 0, 's', 0, 's', 0, 0, 0 }; uint8_t utf16_stream_lesser[ 14 ] = { 'l', 0, 'e', 0, 's', 0, 's', 0, 'e', 0, 'r', 0, 0, 0 }; uint8_t utf16_stream_more[ 10 ] = { 'm', 0, 'o', 0, 'r', 0, 'e', 0, 0, 0 }; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_name_compare( utf16_stream_equal, 12, utf16_stream_equal, 12, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare( utf16_stream_equal, 12, utf16_stream_equal, 12, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare( utf16_stream_equal, 12, utf16_stream_equal_upper, 12, 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare( utf16_stream_great, 12, utf16_stream_greater, 16, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_GREATER ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare( utf16_stream_less, 10, utf16_stream_more, 10, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_GREATER ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare( utf16_stream_more, 10, utf16_stream_less, 10, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_LESS ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare( utf16_stream_lesser, 14, utf16_stream_less, 10, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_LESS ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_name_compare( NULL, 12, utf16_stream_equal, 12, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_name_compare( utf16_stream_equal, (size_t) SSIZE_MAX + 1, utf16_stream_equal, 12, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_name_compare( utf16_stream_equal, 12, NULL, 12, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_name_compare( utf16_stream_equal, 12, utf16_stream_equal, (size_t) SSIZE_MAX + 1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_name_compare_short function * Returns 1 if successful or 0 if not */ int fsntfs_test_name_compare_short( void ) { uint8_t utf16_stream_long1[ 46 ] = { 'D', 0, 'o', 0, 'c', 0, 'u', 0, 'm', 0, 'e', 0, 'n', 0, 't', 0, 's', 0, ' ', 0, 'a', 0, 'n', 0, 'd', 0, ' ', 0, 'S', 0, 'e', 0, 't', 0, 't', 0, 'i', 0, 'n', 0, 'g', 0, 's', 0, 0, 0 }; uint8_t utf16_stream_long2[ 98 ] = { 'B', 0, 'C', 0, 'D', 0, '{', 0, '3', 0, 'e', 0, '8', 0, '0', 0, '4', 0, '9', 0, '5', 0, '9', 0, '-', 0, 'e', 0, 'b', 0, '0', 0, '4', 0, '-', 0, '1', 0, '1', 0, 'e', 0, '4', 0, '-', 0, '8', 0, '0', 0, 'c', 0, '4', 0, '-', 0, '0', 0, '0', 0, '2', 0, '6', 0, 'b', 0, '9', 0, '4', 0, 'a', 0, '1', 0, '7', 0, '7', 0, '3', 0, '}', 0, '.', 0, 'T', 0, 'M', 0, '.', 0, 'b', 0, 'l', 0, 'f', 0, 0, 0 }; uint8_t utf16_stream_long3[ 8 ] = { 'B', 0, 'C', 0, 'D', 0, 0, 0 }; uint8_t utf16_stream_long4[ 18 ] = { 'B', 0, 'C', 0, 'D', 0, '.', 0, 'L', 0, 'O', 0, 'G', 0, '2', 0, 0, 0 }; uint8_t utf16_stream_long5[ 14 ] = { 'O', 0, 'l', 0, 'e', 0, ' ', 0, 'D', 0, 'B', 0, 0, 0 }; uint8_t utf16_stream_long6[ 18 ] = { 'f', 0, '[', 0, '1', 0, ']', 0, '.', 0, 't', 0, 'x', 0, 't', 0, 0, 0 }; uint8_t utf16_stream_long7[ 52 ] = { '6', 0, '.', 0, '1', 0, '.', 0, '0', 0, '.', 0, '0', 0, '_', 0, '_', 0, '3', 0, '1', 0, 'b', 0, 'f', 0, '3', 0, '8', 0, '5', 0, '6', 0, 'a', 0, 'd', 0, '3', 0, '6', 0, '4', 0, 'e', 0, '3', 0, '5', 0, 0, 0 }; uint8_t utf16_stream_long8[ 14 ] = { 'v', 0, '2', 0, '.', 0, '0', 0, '.', 0, '6', 0, 0, 0 }; uint8_t utf16_stream_long9[ 28 ] = { '.', 0, 'N', 0, 'E', 0, 'T', 0, ' ', 0, 'C', 0, 'L', 0, 'R', 0, ' ', 0, 'D', 0, 'a', 0, 't', 0, 'a', 0, 0, 0 }; uint8_t utf16_stream_long10[ 36 ] = { 'a', 0, 'u', 0, 'd', 0, 'i', 0, 'o', 0, 'e', 0, 'n', 0, 'd', 0, 'p', 0, 'o', 0, 'i', 0, 'n', 0, 't', 0, '.', 0, 'P', 0, 'N', 0, 'F', 0, 0, 0 }; uint8_t utf16_stream_short1[ 18 ] = { 'D', 0, 'O', 0, 'C', 0, 'U', 0, 'M', 0, 'E', 0, '~', 0, '1', 0, 0, 0 }; uint8_t utf16_stream_short2[ 26 ] = { 'B', 0, 'C', 0, 'D', 0, '{', 0, '3', 0, 'E', 0, '~', 0, '1', 0, '.', 0, 'B', 0, 'L', 0, 'F', 0, 0, 0 }; uint8_t utf16_stream_short4[ 20 ] = { 'B', 0, 'C', 0, 'D', 0, '~', 0, '2', 0, '.', 0, 'L', 0, 'O', 0, 'G', 0, 0, 0 }; uint8_t utf16_stream_short5[ 16 ] = { 'O', 0, 'L', 0, 'E', 0, 'D', 0, 'B', 0, '~', 0, '1', 0, 0, 0 }; uint8_t utf16_stream_short6[ 22 ] = { 'F', 0, '_', 0, '1', 0, '_', 0, '~', 0, '1', 0, '.', 0, 'T', 0, 'X', 0, 'T', 0, 0, 0 }; uint8_t utf16_stream_short7[ 20 ] = { '6', 0, '1', 0, '0', 0, '~', 0, '1', 0, '.', 0, '0', 0, '_', 0, '_', 0, 0, 0 }; uint8_t utf16_stream_short8[ 16 ] = { 'V', 0, '2', 0, '0', 0, '~', 0, '1', 0, '.', 0, '6', 0, 0, 0 }; uint8_t utf16_stream_short9[ 18 ] = { 'N', 0, 'E', 0, 'T', 0, 'C', 0, 'L', 0, 'R', 0, '~', 0, '1', 0, 0, 0 }; uint8_t utf16_stream_short10[ 26 ] = { 'A', 0, 'U', 0, 'D', 0, 'I', 0, 'O', 0, 'E', 0, '~', 0, '1', 0, '.', 0, 'P', 0, 'N', 0, 'F', 0, 0, 0 }; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_name_compare_short( utf16_stream_long1, 26, utf16_stream_short1, 18, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_short( utf16_stream_long2, 96, utf16_stream_short2, 26, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_short( utf16_stream_long3, 8, utf16_stream_short2, 26, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_GREATER ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_short( utf16_stream_long4, 18, utf16_stream_short2, 26, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_GREATER ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_short( utf16_stream_long4, 18, utf16_stream_short4, 20, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_short( utf16_stream_long5, 14, utf16_stream_short5, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_short( utf16_stream_long6, 18, utf16_stream_short6, 22, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_short( utf16_stream_long7, 52, utf16_stream_short7, 20, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_short( utf16_stream_long8, 14, utf16_stream_short8, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_short( utf16_stream_long9, 28, utf16_stream_short9, 18, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_short( utf16_stream_long10, 36, utf16_stream_short10, 26, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_name_compare_short( NULL, 26, utf16_stream_short1, 18, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_name_compare_short( utf16_stream_long1, (size_t) SSIZE_MAX + 1, utf16_stream_short1, 18, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_name_compare_short( utf16_stream_long1, 26, NULL, 18, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_name_compare_short( utf16_stream_long1, 26, utf16_stream_short1, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_name_compare_with_utf8_string function * Returns 1 if successful or 0 if not */ int fsntfs_test_name_compare_with_utf8_string( void ) { uint8_t utf16_stream_equal[ 12 ] = { 'e', 0, 'q', 0, 'u', 0, 'a', 0, 'l', 0, 0 }; uint8_t utf16_stream_great[ 12 ] = { 'g', 0, 'r', 0, 'e', 0, 'a', 0, 't', 0, 0, 0 }; uint8_t utf16_stream_less[ 10 ] = { 'l', 0, 'e', 0, 's', 0, 's', 0, 0, 0 }; uint8_t utf16_stream_lesser[ 14 ] = { 'l', 0, 'e', 0, 's', 0, 's', 0, 'e', 0, 'r', 0, 0, 0 }; uint8_t utf16_stream_more[ 10 ] = { 'm', 0, 'o', 0, 'r', 0, 'e', 0, 0, 0 }; uint8_t utf8_string_equal[ 6 ] = { 'e', 'q', 'u', 'a', 'l', 0 }; uint8_t utf8_string_equal_upper[ 6 ] = { 'E', 'Q', 'U', 'A', 'L', 0 }; uint8_t utf8_string_greater[ 7 ] = { 'g', 'r', 'e', 'a', 't', 'e', 'r' }; uint8_t utf8_string_less[ 4 ] = { 'l', 'e', 's', 's' }; uint8_t utf8_string_more[ 4 ] = { 'm', 'o', 'r', 'e' }; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_name_compare_with_utf8_string( utf16_stream_equal, 12, utf8_string_equal, 5, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_with_utf8_string( utf16_stream_equal, 12, utf8_string_equal, 6, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_with_utf8_string( utf16_stream_equal, 12, utf8_string_equal_upper, 5, 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_with_utf8_string( utf16_stream_great, 12, utf8_string_greater, 7, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_GREATER ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_with_utf8_string( utf16_stream_less, 10, utf8_string_more, 4, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_GREATER ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_with_utf8_string( utf16_stream_more, 10, utf8_string_less, 4, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_LESS ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_with_utf8_string( utf16_stream_lesser, 14, utf8_string_less, 4, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_LESS ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_name_compare_with_utf8_string( NULL, 12, utf8_string_equal, 5, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_name_compare_with_utf8_string( utf16_stream_equal, (size_t) SSIZE_MAX + 1, utf8_string_equal, 5, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_name_compare_with_utf8_string( utf16_stream_equal, 12, NULL, 5, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_name_compare_with_utf8_string( utf16_stream_equal, 12, utf8_string_equal, (size_t) SSIZE_MAX + 1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_name_compare_with_utf16_string function * Returns 1 if successful or 0 if not */ int fsntfs_test_name_compare_with_utf16_string( void ) { uint8_t utf16_stream_equal[ 12 ] = { 'e', 0, 'q', 0, 'u', 0, 'a', 0, 'l', 0, 0 }; uint8_t utf16_stream_great[ 12 ] = { 'g', 0, 'r', 0, 'e', 0, 'a', 0, 't', 0, 0, 0 }; uint8_t utf16_stream_less[ 10 ] = { 'l', 0, 'e', 0, 's', 0, 's', 0, 0, 0 }; uint8_t utf16_stream_lesser[ 14 ] = { 'l', 0, 'e', 0, 's', 0, 's', 0, 'e', 0, 'r', 0, 0, 0 }; uint8_t utf16_stream_more[ 10 ] = { 'm', 0, 'o', 0, 'r', 0, 'e', 0, 0, 0 }; uint16_t utf16_string_equal[ 6 ] = { 'e', 'q', 'u', 'a', 'l', 0 }; uint16_t utf16_string_equal_upper[ 6 ] = { 'E', 'Q', 'U', 'A', 'L', 0 }; uint16_t utf16_string_greater[ 7 ] = { 'g', 'r', 'e', 'a', 't', 'e', 'r' }; uint16_t utf16_string_less[ 4 ] = { 'l', 'e', 's', 's' }; uint16_t utf16_string_more[ 4 ] = { 'm', 'o', 'r', 'e' }; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_name_compare_with_utf16_string( utf16_stream_equal, 12, utf16_string_equal, 5, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_with_utf16_string( utf16_stream_equal, 12, utf16_string_equal, 6, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_with_utf16_string( utf16_stream_equal, 12, utf16_string_equal_upper, 5, 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_with_utf16_string( utf16_stream_great, 12, utf16_string_greater, 7, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_GREATER ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_with_utf16_string( utf16_stream_less, 10, utf16_string_more, 4, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_GREATER ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_with_utf16_string( utf16_stream_more, 10, utf16_string_less, 4, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_LESS ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_name_compare_with_utf16_string( utf16_stream_lesser, 14, utf16_string_less, 4, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBUNA_COMPARE_LESS ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_name_compare_with_utf16_string( NULL, 12, utf16_string_equal, 5, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_name_compare_with_utf16_string( utf16_stream_equal, (size_t) SSIZE_MAX + 1, utf16_string_equal, 5, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_name_compare_with_utf16_string( utf16_stream_equal, 12, NULL, 5, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_name_compare_with_utf16_string( utf16_stream_equal, 12, utf16_string_equal, (size_t) SSIZE_MAX + 1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_name_compare", fsntfs_test_name_compare ); FSNTFS_TEST_RUN( "libfsntfs_name_compare_short", fsntfs_test_name_compare_short ); FSNTFS_TEST_RUN( "libfsntfs_name_compare_with_utf8_string", fsntfs_test_name_compare_with_utf8_string ); FSNTFS_TEST_RUN( "libfsntfs_name_compare_with_utf16_string", fsntfs_test_name_compare_with_utf16_string ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_notify.c ================================================ /* * Library notification functions test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_unused.h" /* Tests the libfsntfs_notify_set_verbose function * Returns 1 if successful or 0 if not */ int fsntfs_test_notify_set_verbose( void ) { /* Test invocation of function only */ libfsntfs_notify_set_verbose( 0 ); return( 1 ); } /* Tests the libfsntfs_notify_set_stream function * Returns 1 if successful or 0 if not */ int fsntfs_test_notify_set_stream( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_notify_set_stream( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ /* TODO test libcnotify_stream_set failure */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_notify_stream_open function * Returns 1 if successful or 0 if not */ int fsntfs_test_notify_stream_open( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_notify_stream_open( "notify_stream.log", &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_notify_stream_open( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_notify_stream_close( &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_notify_stream_close function * Returns 1 if successful or 0 if not */ int fsntfs_test_notify_stream_close( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_notify_stream_close( &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ /* TODO test libcnotify_stream_close failure */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) FSNTFS_TEST_RUN( "libfsntfs_notify_set_verbose", fsntfs_test_notify_set_verbose ) FSNTFS_TEST_RUN( "libfsntfs_notify_set_stream", fsntfs_test_notify_set_stream ) FSNTFS_TEST_RUN( "libfsntfs_notify_stream_open", fsntfs_test_notify_stream_open ) FSNTFS_TEST_RUN( "libfsntfs_notify_stream_close", fsntfs_test_notify_stream_close ) return( EXIT_SUCCESS ); on_error: return( EXIT_FAILURE ); } ================================================ FILE: tests/fsntfs_test_object_identifier_values.c ================================================ /* * Library object_identifier_values type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" #include "../libfsntfs/libfsntfs_object_identifier_values.h" uint8_t fsntfs_test_object_identifier_values_data1[ 40 ] = { 0x40, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xcc, 0xed, 0x85, 0x47, 0x32, 0xbf, 0x83, 0x4c, 0xb7, 0x65, 0x55, 0xef, 0x93, 0x4d, 0x21, 0x45 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_object_identifier_values_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_object_identifier_values_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_object_identifier_values_t *object_identifier_values = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_object_identifier_values_initialize( &object_identifier_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "object_identifier_values", object_identifier_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_object_identifier_values_free( &object_identifier_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "object_identifier_values", object_identifier_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_object_identifier_values_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); object_identifier_values = (libfsntfs_object_identifier_values_t *) 0x12345678UL; result = libfsntfs_object_identifier_values_initialize( &object_identifier_values, &error ); object_identifier_values = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_object_identifier_values_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_object_identifier_values_initialize( &object_identifier_values, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( object_identifier_values != NULL ) { libfsntfs_object_identifier_values_free( &object_identifier_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "object_identifier_values", object_identifier_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_object_identifier_values_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_object_identifier_values_initialize( &object_identifier_values, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( object_identifier_values != NULL ) { libfsntfs_object_identifier_values_free( &object_identifier_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "object_identifier_values", object_identifier_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( object_identifier_values != NULL ) { libfsntfs_object_identifier_values_free( &object_identifier_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_object_identifier_values_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_object_identifier_values_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_object_identifier_values_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_object_identifier_values_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_object_identifier_values_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_object_identifier_values_t *object_identifier_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_object_identifier_values_initialize( &object_identifier_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "object_identifier_values", object_identifier_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_object_identifier_values_read_data( object_identifier_values, &( fsntfs_test_object_identifier_values_data1[ 24 ] ), 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_object_identifier_values_read_data( NULL, &( fsntfs_test_object_identifier_values_data1[ 24 ] ), 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_object_identifier_values_read_data( object_identifier_values, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_object_identifier_values_read_data( object_identifier_values, &( fsntfs_test_object_identifier_values_data1[ 24 ] ), (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_object_identifier_values_free( &object_identifier_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "object_identifier_values", object_identifier_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( object_identifier_values != NULL ) { libfsntfs_object_identifier_values_free( &object_identifier_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_object_identifier_values_read_from_mft_attribute function * Returns 1 if successful or 0 if not */ int fsntfs_test_object_identifier_values_read_from_mft_attribute( void ) { libcerror_error_t *error = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; libfsntfs_object_identifier_values_t *object_identifier_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_object_identifier_values_data1, 40, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_object_identifier_values_initialize( &object_identifier_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "object_identifier_values", object_identifier_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_object_identifier_values_read_from_mft_attribute( object_identifier_values, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_object_identifier_values_read_from_mft_attribute( NULL, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_object_identifier_values_read_from_mft_attribute( object_identifier_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_object_identifier_values_free( &object_identifier_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "object_identifier_values", object_identifier_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( object_identifier_values != NULL ) { libfsntfs_object_identifier_values_free( &object_identifier_values, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_object_identifier_values_initialize", fsntfs_test_object_identifier_values_initialize ); FSNTFS_TEST_RUN( "libfsntfs_object_identifier_values_free", fsntfs_test_object_identifier_values_free ); FSNTFS_TEST_RUN( "libfsntfs_object_identifier_values_read_data", fsntfs_test_object_identifier_values_read_data ); FSNTFS_TEST_RUN( "libfsntfs_object_identifier_values_read_from_mft_attribute", fsntfs_test_object_identifier_values_read_from_mft_attribute ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_path_hint.c ================================================ /* * Library path_hint type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_path_hint.h" #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_path_hint_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_path_hint_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_path_hint_t *path_hint = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_path_hint_initialize( &path_hint, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "path_hint", path_hint ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_path_hint_free( &path_hint, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "path_hint", path_hint ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_path_hint_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); path_hint = (libfsntfs_path_hint_t *) 0x12345678UL; result = libfsntfs_path_hint_initialize( &path_hint, &error ); path_hint = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_path_hint_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_path_hint_initialize( &path_hint, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( path_hint != NULL ) { libfsntfs_path_hint_free( &path_hint, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "path_hint", path_hint ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_path_hint_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_path_hint_initialize( &path_hint, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( path_hint != NULL ) { libfsntfs_path_hint_free( &path_hint, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "path_hint", path_hint ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( path_hint != NULL ) { libfsntfs_path_hint_free( &path_hint, NULL ); } return( 0 ); } /* Tests the libfsntfs_path_hint_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_path_hint_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_path_hint_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_path_hint_initialize", fsntfs_test_path_hint_initialize ); FSNTFS_TEST_RUN( "libfsntfs_path_hint_free", fsntfs_test_path_hint_free ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_profiler.c ================================================ /* * Library profiler type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_profiler.h" #if defined( HAVE_PROFILER ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_profiler_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_profiler_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_profiler_t *profiler = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_profiler_initialize( &profiler, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "profiler", profiler ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_profiler_free( &profiler, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "profiler", profiler ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_profiler_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); profiler = (libfsntfs_profiler_t *) 0x12345678UL; result = libfsntfs_profiler_initialize( &profiler, &error ); profiler = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_profiler_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_profiler_initialize( &profiler, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( profiler != NULL ) { libfsntfs_profiler_free( &profiler, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "profiler", profiler ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_profiler_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_profiler_initialize( &profiler, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( profiler != NULL ) { libfsntfs_profiler_free( &profiler, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "profiler", profiler ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( profiler != NULL ) { libfsntfs_profiler_free( &profiler, NULL ); } return( 0 ); } /* Tests the libfsntfs_profiler_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_profiler_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_profiler_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_profiler_close function * Returns 1 if successful or 0 if not */ int fsntfs_test_profiler_close( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_profiler_close( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ #endif /* defined( HAVE_PROFILER ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( HAVE_PROFILER ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_profiler_initialize", fsntfs_test_profiler_initialize ); FSNTFS_TEST_RUN( "libfsntfs_profiler_free", fsntfs_test_profiler_free ); /* TODO: add tests for libfsntfs_profiler_open */ FSNTFS_TEST_RUN( "libfsntfs_profiler_close", fsntfs_test_profiler_close ); /* TODO: add tests for libfsntfs_profiler_start_timing */ /* TODO: add tests for libfsntfs_profiler_stop_timing */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ #endif /* defined( HAVE_PROFILER ) */ return( EXIT_SUCCESS ); #if defined( HAVE_PROFILER ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ #endif /* defined( HAVE_PROFILER ) */ } ================================================ FILE: tests/fsntfs_test_reparse_point_attribute.c ================================================ /* * Library reparse_point_attributes functions test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_attribute.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) #include "../libfsntfs/libfsntfs_reparse_point_attribute.h" #endif uint8_t fsntfs_test_reparse_point_attribute_data1[ 88 ] = { 0xc0, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xa0, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x1a, 0x00, 0x10, 0x00, 0x5c, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x5c, 0x00, 0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x00, 0x00, 0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_reparse_point_attribute_get_tag function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_attribute_get_tag( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; uint32_t tag = 0; int result = 0; /* Test regular cases */ result = libfsntfs_reparse_point_attribute_get_tag( attribute, &tag, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_reparse_point_attribute_get_tag( NULL, &tag, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_attribute_get_tag( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_attribute_get_utf8_substitute_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_attribute_get_utf8_substitute_name_size( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; size_t utf8_substitute_name_size = 0; int result = 0; int utf8_substitute_name_size_is_set = 0; /* Test regular cases */ result = libfsntfs_reparse_point_attribute_get_utf8_substitute_name_size( attribute, &utf8_substitute_name_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf8_substitute_name_size_is_set = result; /* Test error cases */ result = libfsntfs_reparse_point_attribute_get_utf8_substitute_name_size( NULL, &utf8_substitute_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf8_substitute_name_size_is_set != 0 ) { result = libfsntfs_reparse_point_attribute_get_utf8_substitute_name_size( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_attribute_get_utf8_substitute_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_attribute_get_utf8_substitute_name( libfsntfs_attribute_t *attribute ) { uint8_t utf8_substitute_name[ 512 ]; libcerror_error_t *error = NULL; int result = 0; int utf8_substitute_name_is_set = 0; /* Test regular cases */ result = libfsntfs_reparse_point_attribute_get_utf8_substitute_name( attribute, utf8_substitute_name, 512, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf8_substitute_name_is_set = result; /* Test error cases */ result = libfsntfs_reparse_point_attribute_get_utf8_substitute_name( NULL, utf8_substitute_name, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf8_substitute_name_is_set != 0 ) { result = libfsntfs_reparse_point_attribute_get_utf8_substitute_name( attribute, NULL, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_attribute_get_utf8_substitute_name( attribute, utf8_substitute_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_attribute_get_utf8_substitute_name( attribute, utf8_substitute_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_attribute_get_utf16_substitute_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_attribute_get_utf16_substitute_name_size( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; size_t utf16_substitute_name_size = 0; int result = 0; int utf16_substitute_name_size_is_set = 0; /* Test regular cases */ result = libfsntfs_reparse_point_attribute_get_utf16_substitute_name_size( attribute, &utf16_substitute_name_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf16_substitute_name_size_is_set = result; /* Test error cases */ result = libfsntfs_reparse_point_attribute_get_utf16_substitute_name_size( NULL, &utf16_substitute_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf16_substitute_name_size_is_set != 0 ) { result = libfsntfs_reparse_point_attribute_get_utf16_substitute_name_size( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_attribute_get_utf16_substitute_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_attribute_get_utf16_substitute_name( libfsntfs_attribute_t *attribute ) { uint16_t utf16_substitute_name[ 512 ]; libcerror_error_t *error = NULL; int result = 0; int utf16_substitute_name_is_set = 0; /* Test regular cases */ result = libfsntfs_reparse_point_attribute_get_utf16_substitute_name( attribute, utf16_substitute_name, 512, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf16_substitute_name_is_set = result; /* Test error cases */ result = libfsntfs_reparse_point_attribute_get_utf16_substitute_name( NULL, utf16_substitute_name, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf16_substitute_name_is_set != 0 ) { result = libfsntfs_reparse_point_attribute_get_utf16_substitute_name( attribute, NULL, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_attribute_get_utf16_substitute_name( attribute, utf16_substitute_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_attribute_get_utf16_substitute_name( attribute, utf16_substitute_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_attribute_get_utf8_print_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_attribute_get_utf8_print_name_size( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; size_t utf8_print_name_size = 0; int result = 0; int utf8_print_name_size_is_set = 0; /* Test regular cases */ result = libfsntfs_reparse_point_attribute_get_utf8_print_name_size( attribute, &utf8_print_name_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf8_print_name_size_is_set = result; /* Test error cases */ result = libfsntfs_reparse_point_attribute_get_utf8_print_name_size( NULL, &utf8_print_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf8_print_name_size_is_set != 0 ) { result = libfsntfs_reparse_point_attribute_get_utf8_print_name_size( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_attribute_get_utf8_print_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_attribute_get_utf8_print_name( libfsntfs_attribute_t *attribute ) { uint8_t utf8_print_name[ 512 ]; libcerror_error_t *error = NULL; int result = 0; int utf8_print_name_is_set = 0; /* Test regular cases */ result = libfsntfs_reparse_point_attribute_get_utf8_print_name( attribute, utf8_print_name, 512, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf8_print_name_is_set = result; /* Test error cases */ result = libfsntfs_reparse_point_attribute_get_utf8_print_name( NULL, utf8_print_name, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf8_print_name_is_set != 0 ) { result = libfsntfs_reparse_point_attribute_get_utf8_print_name( attribute, NULL, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_attribute_get_utf8_print_name( attribute, utf8_print_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_attribute_get_utf8_print_name( attribute, utf8_print_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_attribute_get_utf16_print_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_attribute_get_utf16_print_name_size( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; size_t utf16_print_name_size = 0; int result = 0; int utf16_print_name_size_is_set = 0; /* Test regular cases */ result = libfsntfs_reparse_point_attribute_get_utf16_print_name_size( attribute, &utf16_print_name_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf16_print_name_size_is_set = result; /* Test error cases */ result = libfsntfs_reparse_point_attribute_get_utf16_print_name_size( NULL, &utf16_print_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf16_print_name_size_is_set != 0 ) { result = libfsntfs_reparse_point_attribute_get_utf16_print_name_size( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_attribute_get_utf16_print_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_attribute_get_utf16_print_name( libfsntfs_attribute_t *attribute ) { uint16_t utf16_print_name[ 512 ]; libcerror_error_t *error = NULL; int result = 0; int utf16_print_name_is_set = 0; /* Test regular cases */ result = libfsntfs_reparse_point_attribute_get_utf16_print_name( attribute, utf16_print_name, 512, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf16_print_name_is_set = result; /* Test error cases */ result = libfsntfs_reparse_point_attribute_get_utf16_print_name( NULL, utf16_print_name, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf16_print_name_is_set != 0 ) { result = libfsntfs_reparse_point_attribute_get_utf16_print_name( attribute, NULL, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_attribute_get_utf16_print_name( attribute, utf16_print_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_attribute_get_utf16_print_name( attribute, utf16_print_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_attribute_t *attribute = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; #endif FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize attribute for tests */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_reparse_point_attribute_data1, 88, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_attribute_initialize( &attribute, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_internal_attribute_read_value( (libfsntfs_internal_attribute_t *) attribute, io_handle, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_reparse_point_attribute_get_tag", fsntfs_test_reparse_point_attribute_get_tag, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_reparse_point_attribute_get_utf8_substitute_name_size", fsntfs_test_reparse_point_attribute_get_utf8_substitute_name_size, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_reparse_point_attribute_get_utf8_substitute_name", fsntfs_test_reparse_point_attribute_get_utf8_substitute_name, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_reparse_point_attribute_get_utf16_substitute_name_size", fsntfs_test_reparse_point_attribute_get_utf16_substitute_name_size, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_reparse_point_attribute_get_utf16_substitute_name", fsntfs_test_reparse_point_attribute_get_utf16_substitute_name, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_reparse_point_attribute_get_utf8_print_name_size", fsntfs_test_reparse_point_attribute_get_utf8_print_name_size, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_reparse_point_attribute_get_utf8_print_name", fsntfs_test_reparse_point_attribute_get_utf8_print_name, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_reparse_point_attribute_get_utf16_print_name_size", fsntfs_test_reparse_point_attribute_get_utf16_print_name_size, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_reparse_point_attribute_get_utf16_print_name", fsntfs_test_reparse_point_attribute_get_utf16_print_name, attribute ); /* Clean up */ result = libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( attribute != NULL ) { libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &attribute, &error ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, &error ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_reparse_point_values.c ================================================ /* * Library reparse_point_values type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" #include "../libfsntfs/libfsntfs_reparse_point_values.h" uint8_t fsntfs_test_reparse_point_values_data1[ 88 ] = { 0xc0, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xa0, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x1a, 0x00, 0x10, 0x00, 0x5c, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x5c, 0x00, 0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x00, 0x00, 0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_reparse_point_values_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_values_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_reparse_point_values_t *reparse_point_values = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_reparse_point_values_initialize( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_reparse_point_values_free( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_reparse_point_values_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); reparse_point_values = (libfsntfs_reparse_point_values_t *) 0x12345678UL; result = libfsntfs_reparse_point_values_initialize( &reparse_point_values, &error ); reparse_point_values = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_reparse_point_values_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_reparse_point_values_initialize( &reparse_point_values, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( reparse_point_values != NULL ) { libfsntfs_reparse_point_values_free( &reparse_point_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_reparse_point_values_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_reparse_point_values_initialize( &reparse_point_values, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( reparse_point_values != NULL ) { libfsntfs_reparse_point_values_free( &reparse_point_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( reparse_point_values != NULL ) { libfsntfs_reparse_point_values_free( &reparse_point_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_values_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_values_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_reparse_point_values_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_values_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_values_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_reparse_point_values_t *reparse_point_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_reparse_point_values_initialize( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_reparse_point_values_read_data( reparse_point_values, &( fsntfs_test_reparse_point_values_data1[ 24 ] ), 60, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_reparse_point_values_read_data( NULL, &( fsntfs_test_reparse_point_values_data1[ 24 ] ), 60, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_values_read_data( reparse_point_values, NULL, 60, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_values_read_data( reparse_point_values, &( fsntfs_test_reparse_point_values_data1[ 24 ] ), (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_reparse_point_values_free( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( reparse_point_values != NULL ) { libfsntfs_reparse_point_values_free( &reparse_point_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_values_read_from_mft_attribute function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_values_read_from_mft_attribute( void ) { libcerror_error_t *error = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; libfsntfs_reparse_point_values_t *reparse_point_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_reparse_point_values_data1, 88, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_reparse_point_values_initialize( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_reparse_point_values_read_from_mft_attribute( reparse_point_values, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_reparse_point_values_read_from_mft_attribute( NULL, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_values_read_from_mft_attribute( reparse_point_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_reparse_point_values_free( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( reparse_point_values != NULL ) { libfsntfs_reparse_point_values_free( &reparse_point_values, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_values_get_tag function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_values_get_tag( void ) { libcerror_error_t *error = NULL; libfsntfs_reparse_point_values_t *reparse_point_values = NULL; uint32_t tag = 0; int result = 0; /* Initialize test */ result = libfsntfs_reparse_point_values_initialize( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_reparse_point_values_get_tag( reparse_point_values, &tag, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_reparse_point_values_get_tag( NULL, &tag, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_values_get_tag( reparse_point_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_reparse_point_values_free( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( reparse_point_values != NULL ) { libfsntfs_reparse_point_values_free( &reparse_point_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_values_get_utf8_substitute_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_values_get_utf8_substitute_name_size( void ) { libcerror_error_t *error = NULL; libfsntfs_reparse_point_values_t *reparse_point_values = NULL; size_t utf8_substitute_name_size = 0; int result = 0; int utf8_substitute_name_size_is_set = 0; /* Initialize test */ result = libfsntfs_reparse_point_values_initialize( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_reparse_point_values_get_utf8_substitute_name_size( reparse_point_values, &utf8_substitute_name_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf8_substitute_name_size_is_set = result; /* Test error cases */ result = libfsntfs_reparse_point_values_get_utf8_substitute_name_size( NULL, &utf8_substitute_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf8_substitute_name_size_is_set != 0 ) { result = libfsntfs_reparse_point_values_get_utf8_substitute_name_size( reparse_point_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Clean up */ result = libfsntfs_reparse_point_values_free( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( reparse_point_values != NULL ) { libfsntfs_reparse_point_values_free( &reparse_point_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_values_get_utf8_substitute_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_values_get_utf8_substitute_name( void ) { uint8_t utf8_substitute_name[ 512 ]; libcerror_error_t *error = NULL; libfsntfs_reparse_point_values_t *reparse_point_values = NULL; int result = 0; int utf8_substitute_name_is_set = 0; /* Initialize test */ result = libfsntfs_reparse_point_values_initialize( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_reparse_point_values_get_utf8_substitute_name( reparse_point_values, utf8_substitute_name, 512, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf8_substitute_name_is_set = result; /* Test error cases */ result = libfsntfs_reparse_point_values_get_utf8_substitute_name( NULL, utf8_substitute_name, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf8_substitute_name_is_set != 0 ) { result = libfsntfs_reparse_point_values_get_utf8_substitute_name( reparse_point_values, NULL, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_values_get_utf8_substitute_name( reparse_point_values, utf8_substitute_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_values_get_utf8_substitute_name( reparse_point_values, utf8_substitute_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Clean up */ result = libfsntfs_reparse_point_values_free( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( reparse_point_values != NULL ) { libfsntfs_reparse_point_values_free( &reparse_point_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_values_get_utf16_substitute_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_values_get_utf16_substitute_name_size( void ) { libcerror_error_t *error = NULL; libfsntfs_reparse_point_values_t *reparse_point_values = NULL; size_t utf16_substitute_name_size = 0; int result = 0; int utf16_substitute_name_size_is_set = 0; /* Initialize test */ result = libfsntfs_reparse_point_values_initialize( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_reparse_point_values_get_utf16_substitute_name_size( reparse_point_values, &utf16_substitute_name_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf16_substitute_name_size_is_set = result; /* Test error cases */ result = libfsntfs_reparse_point_values_get_utf16_substitute_name_size( NULL, &utf16_substitute_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf16_substitute_name_size_is_set != 0 ) { result = libfsntfs_reparse_point_values_get_utf16_substitute_name_size( reparse_point_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Clean up */ result = libfsntfs_reparse_point_values_free( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( reparse_point_values != NULL ) { libfsntfs_reparse_point_values_free( &reparse_point_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_values_get_utf16_substitute_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_values_get_utf16_substitute_name( void ) { uint16_t utf16_substitute_name[ 512 ]; libcerror_error_t *error = NULL; libfsntfs_reparse_point_values_t *reparse_point_values = NULL; int result = 0; int utf16_substitute_name_is_set = 0; /* Initialize test */ result = libfsntfs_reparse_point_values_initialize( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_reparse_point_values_get_utf16_substitute_name( reparse_point_values, utf16_substitute_name, 512, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf16_substitute_name_is_set = result; /* Test error cases */ result = libfsntfs_reparse_point_values_get_utf16_substitute_name( NULL, utf16_substitute_name, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf16_substitute_name_is_set != 0 ) { result = libfsntfs_reparse_point_values_get_utf16_substitute_name( reparse_point_values, NULL, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_values_get_utf16_substitute_name( reparse_point_values, utf16_substitute_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_values_get_utf16_substitute_name( reparse_point_values, utf16_substitute_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Clean up */ result = libfsntfs_reparse_point_values_free( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( reparse_point_values != NULL ) { libfsntfs_reparse_point_values_free( &reparse_point_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_values_get_utf8_print_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_values_get_utf8_print_name_size( void ) { libcerror_error_t *error = NULL; libfsntfs_reparse_point_values_t *reparse_point_values = NULL; size_t utf8_print_name_size = 0; int result = 0; int utf8_print_name_size_is_set = 0; /* Initialize test */ result = libfsntfs_reparse_point_values_initialize( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_reparse_point_values_get_utf8_print_name_size( reparse_point_values, &utf8_print_name_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf8_print_name_size_is_set = result; /* Test error cases */ result = libfsntfs_reparse_point_values_get_utf8_print_name_size( NULL, &utf8_print_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf8_print_name_size_is_set != 0 ) { result = libfsntfs_reparse_point_values_get_utf8_print_name_size( reparse_point_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Clean up */ result = libfsntfs_reparse_point_values_free( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( reparse_point_values != NULL ) { libfsntfs_reparse_point_values_free( &reparse_point_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_values_get_utf8_print_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_values_get_utf8_print_name( void ) { uint8_t utf8_print_name[ 512 ]; libcerror_error_t *error = NULL; libfsntfs_reparse_point_values_t *reparse_point_values = NULL; int result = 0; int utf8_print_name_is_set = 0; /* Initialize test */ result = libfsntfs_reparse_point_values_initialize( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_reparse_point_values_get_utf8_print_name( reparse_point_values, utf8_print_name, 512, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf8_print_name_is_set = result; /* Test error cases */ result = libfsntfs_reparse_point_values_get_utf8_print_name( NULL, utf8_print_name, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf8_print_name_is_set != 0 ) { result = libfsntfs_reparse_point_values_get_utf8_print_name( reparse_point_values, NULL, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_values_get_utf8_print_name( reparse_point_values, utf8_print_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_values_get_utf8_print_name( reparse_point_values, utf8_print_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Clean up */ result = libfsntfs_reparse_point_values_free( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( reparse_point_values != NULL ) { libfsntfs_reparse_point_values_free( &reparse_point_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_values_get_utf16_print_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_values_get_utf16_print_name_size( void ) { libcerror_error_t *error = NULL; libfsntfs_reparse_point_values_t *reparse_point_values = NULL; size_t utf16_print_name_size = 0; int result = 0; int utf16_print_name_size_is_set = 0; /* Initialize test */ result = libfsntfs_reparse_point_values_initialize( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_reparse_point_values_get_utf16_print_name_size( reparse_point_values, &utf16_print_name_size, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf16_print_name_size_is_set = result; /* Test error cases */ result = libfsntfs_reparse_point_values_get_utf16_print_name_size( NULL, &utf16_print_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf16_print_name_size_is_set != 0 ) { result = libfsntfs_reparse_point_values_get_utf16_print_name_size( reparse_point_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Clean up */ result = libfsntfs_reparse_point_values_free( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( reparse_point_values != NULL ) { libfsntfs_reparse_point_values_free( &reparse_point_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_reparse_point_values_get_utf16_print_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_reparse_point_values_get_utf16_print_name( void ) { uint16_t utf16_print_name[ 512 ]; libcerror_error_t *error = NULL; libfsntfs_reparse_point_values_t *reparse_point_values = NULL; int result = 0; int utf16_print_name_is_set = 0; /* Initialize test */ result = libfsntfs_reparse_point_values_initialize( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_reparse_point_values_get_utf16_print_name( reparse_point_values, utf16_print_name, 512, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); utf16_print_name_is_set = result; /* Test error cases */ result = libfsntfs_reparse_point_values_get_utf16_print_name( NULL, utf16_print_name, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( utf16_print_name_is_set != 0 ) { result = libfsntfs_reparse_point_values_get_utf16_print_name( reparse_point_values, NULL, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_values_get_utf16_print_name( reparse_point_values, utf16_print_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_reparse_point_values_get_utf16_print_name( reparse_point_values, utf16_print_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } /* Clean up */ result = libfsntfs_reparse_point_values_free( &reparse_point_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "reparse_point_values", reparse_point_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( reparse_point_values != NULL ) { libfsntfs_reparse_point_values_free( &reparse_point_values, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_reparse_point_values_initialize", fsntfs_test_reparse_point_values_initialize ); FSNTFS_TEST_RUN( "libfsntfs_reparse_point_values_free", fsntfs_test_reparse_point_values_free ); FSNTFS_TEST_RUN( "libfsntfs_reparse_point_values_read_data", fsntfs_test_reparse_point_values_read_data ); FSNTFS_TEST_RUN( "libfsntfs_reparse_point_values_read_from_mft_attribute", fsntfs_test_reparse_point_values_read_from_mft_attribute ); FSNTFS_TEST_RUN( "libfsntfs_reparse_point_values_get_tag", fsntfs_test_reparse_point_values_get_tag ); FSNTFS_TEST_RUN( "libfsntfs_reparse_point_values_get_utf8_substitute_name_size", fsntfs_test_reparse_point_values_get_utf8_substitute_name_size ); FSNTFS_TEST_RUN( "libfsntfs_reparse_point_values_get_utf8_substitute_name", fsntfs_test_reparse_point_values_get_utf8_substitute_name ); FSNTFS_TEST_RUN( "libfsntfs_reparse_point_values_get_utf16_substitute_name_size", fsntfs_test_reparse_point_values_get_utf16_substitute_name_size ); FSNTFS_TEST_RUN( "libfsntfs_reparse_point_values_get_utf16_substitute_name", fsntfs_test_reparse_point_values_get_utf16_substitute_name ); FSNTFS_TEST_RUN( "libfsntfs_reparse_point_values_get_utf8_print_name_size", fsntfs_test_reparse_point_values_get_utf8_print_name_size ); FSNTFS_TEST_RUN( "libfsntfs_reparse_point_values_get_utf8_print_name", fsntfs_test_reparse_point_values_get_utf8_print_name ); FSNTFS_TEST_RUN( "libfsntfs_reparse_point_values_get_utf16_print_name_size", fsntfs_test_reparse_point_values_get_utf16_print_name_size ); FSNTFS_TEST_RUN( "libfsntfs_reparse_point_values_get_utf16_print_name", fsntfs_test_reparse_point_values_get_utf16_print_name ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_rwlock.c ================================================ /* * Read/Write lock functions for testing * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include #if defined( HAVE_GNU_DL_DLSYM ) && defined( __GNUC__ ) #define __USE_GNU #include #undef __USE_GNU #endif #include "fsntfs_test_rwlock.h" #if defined( HAVE_FSNTFS_TEST_RWLOCK ) static int (*fsntfs_test_real_pthread_rwlock_destroy)(pthread_rwlock_t *) = NULL; static int (*fsntfs_test_real_pthread_rwlock_rdlock)(pthread_rwlock_t *) = NULL; static int (*fsntfs_test_real_pthread_rwlock_wrlock)(pthread_rwlock_t *) = NULL; static int (*fsntfs_test_real_pthread_rwlock_unlock)(pthread_rwlock_t *) = NULL; int fsntfs_test_pthread_rwlock_destroy_attempts_before_fail = -1; int fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; int fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = -1; int fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; #if defined( TODO ) /* TODO currently disabled since this causes the tests to segfault on Ubuntu 14.04 */ static int (*fsntfs_test_real_pthread_rwlock_init)(pthread_rwlock_t *, const pthread_rwlockattr_t *) = NULL; int fsntfs_test_pthread_rwlock_init_attempts_before_fail = -1; /* Custom pthread_rwlock_init for testing error cases * Returns 0 if successful or an error value otherwise */ int pthread_rwlock_init( pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr ) { int result = 0; if( fsntfs_test_real_pthread_rwlock_init == NULL ) { fsntfs_test_real_pthread_rwlock_init = dlsym( RTLD_NEXT, "pthread_rwlock_init" ); } if( fsntfs_test_pthread_rwlock_init_attempts_before_fail == 0 ) { fsntfs_test_pthread_rwlock_init_attempts_before_fail = -1; return( EBUSY ); } else if( fsntfs_test_pthread_rwlock_init_attempts_before_fail > 0 ) { fsntfs_test_pthread_rwlock_init_attempts_before_fail--; } result = fsntfs_test_real_pthread_rwlock_init( rwlock, attr ); return( result ); } #endif /* defined( TODO ) */ /* Custom pthread_rwlock_destroy for testing error cases * Returns 0 if successful or an error value otherwise */ int pthread_rwlock_destroy( pthread_rwlock_t *rwlock ) { int result = 0; if( fsntfs_test_real_pthread_rwlock_destroy == NULL ) { fsntfs_test_real_pthread_rwlock_destroy = dlsym( RTLD_NEXT, "pthread_rwlock_destroy" ); } if( fsntfs_test_pthread_rwlock_destroy_attempts_before_fail == 0 ) { fsntfs_test_pthread_rwlock_destroy_attempts_before_fail = -1; return( EBUSY ); } else if( fsntfs_test_pthread_rwlock_destroy_attempts_before_fail > 0 ) { fsntfs_test_pthread_rwlock_destroy_attempts_before_fail--; } result = fsntfs_test_real_pthread_rwlock_destroy( rwlock ); return( result ); } /* Custom pthread_rwlock_rdlock for testing error cases * Returns 0 if successful or an error value otherwise */ int pthread_rwlock_rdlock( pthread_rwlock_t *rwlock ) { int result = 0; if( fsntfs_test_real_pthread_rwlock_rdlock == NULL ) { fsntfs_test_real_pthread_rwlock_rdlock = dlsym( RTLD_NEXT, "pthread_rwlock_rdlock" ); } if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail == 0 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail = -1; return( EBUSY ); } else if( fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail > 0 ) { fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail--; } result = fsntfs_test_real_pthread_rwlock_rdlock( rwlock ); return( result ); } /* Custom pthread_rwlock_wrlock for testing error cases * Returns 0 if successful or an error value otherwise */ int pthread_rwlock_wrlock( pthread_rwlock_t *rwlock ) { int result = 0; if( fsntfs_test_real_pthread_rwlock_wrlock == NULL ) { fsntfs_test_real_pthread_rwlock_wrlock = dlsym( RTLD_NEXT, "pthread_rwlock_wrlock" ); } if( fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail == 0 ) { fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail = -1; return( EBUSY ); } else if( fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail > 0 ) { fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail--; } result = fsntfs_test_real_pthread_rwlock_wrlock( rwlock ); return( result ); } /* Custom pthread_rwlock_unlock for testing error cases * Returns 0 if successful or an error value otherwise */ int pthread_rwlock_unlock( pthread_rwlock_t *rwlock ) { int result = 0; if( fsntfs_test_real_pthread_rwlock_unlock == NULL ) { fsntfs_test_real_pthread_rwlock_unlock = dlsym( RTLD_NEXT, "pthread_rwlock_unlock" ); } if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail == 0 ) { /* Unlock the lock otherwise it can enter a nondeterministic state */ fsntfs_test_real_pthread_rwlock_unlock( rwlock ); fsntfs_test_pthread_rwlock_unlock_attempts_before_fail = -1; return( EBUSY ); } else if( fsntfs_test_pthread_rwlock_unlock_attempts_before_fail > 0 ) { fsntfs_test_pthread_rwlock_unlock_attempts_before_fail--; } result = fsntfs_test_real_pthread_rwlock_unlock( rwlock ); return( result ); } #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ ================================================ FILE: tests/fsntfs_test_rwlock.h ================================================ /* * Read/Write lock functions for testing * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_TEST_RWLOCK_H ) #define _FSNTFS_TEST_RWLOCK_H #include #include "fsntfs_test_libfsntfs.h" #if defined( __cplusplus ) extern "C" { #endif #if defined( LIBFSNTFS_HAVE_MULTI_THREAD_SUPPORT ) && defined( HAVE_GNU_DL_DLSYM ) && defined( __GNUC__ ) && !defined( __clang__ ) && !defined( __CYGWIN__ ) #define HAVE_FSNTFS_TEST_RWLOCK 1 #endif #if defined( HAVE_FSNTFS_TEST_RWLOCK ) extern int fsntfs_test_pthread_rwlock_init_attempts_before_fail; extern int fsntfs_test_pthread_rwlock_destroy_attempts_before_fail; extern int fsntfs_test_pthread_rwlock_rdlock_attempts_before_fail; extern int fsntfs_test_pthread_rwlock_wrlock_attempts_before_fail; extern int fsntfs_test_pthread_rwlock_unlock_attempts_before_fail; #endif /* defined( HAVE_FSNTFS_TEST_RWLOCK ) */ #if defined( __cplusplus ) } #endif #endif /* !defined( _FSNTFS_TEST_RWLOCK_H ) */ ================================================ FILE: tests/fsntfs_test_sds_index_value.c ================================================ /* * Library sds_index_value type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_sds_index_value.h" uint8_t fsntfs_test_sds_index_value_data1[ 20 ] = { 0x14, 0x38, 0x78, 0x2c, 0x06, 0x01, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_sds_index_value_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_sds_index_value_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_sds_index_value_t *sds_index_value = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_sds_index_value_initialize( &sds_index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "sds_index_value", sds_index_value ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_sds_index_value_free( &sds_index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "sds_index_value", sds_index_value ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_sds_index_value_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); sds_index_value = (libfsntfs_sds_index_value_t *) 0x12345678UL; result = libfsntfs_sds_index_value_initialize( &sds_index_value, &error ); sds_index_value = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_sds_index_value_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_sds_index_value_initialize( &sds_index_value, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( sds_index_value != NULL ) { libfsntfs_sds_index_value_free( &sds_index_value, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "sds_index_value", sds_index_value ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_sds_index_value_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_sds_index_value_initialize( &sds_index_value, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( sds_index_value != NULL ) { libfsntfs_sds_index_value_free( &sds_index_value, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "sds_index_value", sds_index_value ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( sds_index_value != NULL ) { libfsntfs_sds_index_value_free( &sds_index_value, NULL ); } return( 0 ); } /* Tests the libfsntfs_sds_index_value_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_sds_index_value_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_sds_index_value_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_sds_index_value_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_sds_index_value_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_sds_index_value_t *sds_index_value = NULL; int result = 0; /* Initialize test */ result = libfsntfs_sds_index_value_initialize( &sds_index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "sds_index_value", sds_index_value ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_sds_index_value_read_data( sds_index_value, fsntfs_test_sds_index_value_data1, 20, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_sds_index_value_read_data( NULL, fsntfs_test_sds_index_value_data1, 20, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_sds_index_value_read_data( sds_index_value, NULL, 20, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_sds_index_value_read_data( sds_index_value, fsntfs_test_sds_index_value_data1, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_sds_index_value_read_data( sds_index_value, fsntfs_test_sds_index_value_data1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_sds_index_value_free( &sds_index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "sds_index_value", sds_index_value ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( sds_index_value != NULL ) { libfsntfs_sds_index_value_free( &sds_index_value, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_sds_index_value_initialize", fsntfs_test_sds_index_value_initialize ); FSNTFS_TEST_RUN( "libfsntfs_sds_index_value_free", fsntfs_test_sds_index_value_free ); FSNTFS_TEST_RUN( "libfsntfs_sds_index_value_read_data", fsntfs_test_sds_index_value_read_data ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_security_descriptor_index.c ================================================ /* * Library security_descriptor_index type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" #include "../libfsntfs/libfsntfs_security_descriptor_index.h" uint8_t fsntfs_test_security_descriptor_index_data1[ 80 ] = { 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x53, 0x00, 0x44, 0x00, 0x53, 0x00, 0x21, 0x41, 0xd2, 0x50, 0x00, 0xf8, 0xff, 0xff }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_security_descriptor_index_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_security_descriptor_index_initialize( void ) { libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *data_attribute = NULL; libfsntfs_security_descriptor_index_t *security_descriptor_index = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &data_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "data_attribute", data_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( data_attribute, io_handle, fsntfs_test_security_descriptor_index_data1, 80, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_security_descriptor_index_initialize( &security_descriptor_index, io_handle, file_io_handle, data_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "security_descriptor_index", security_descriptor_index ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_security_descriptor_index_free( &security_descriptor_index, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "security_descriptor_index", security_descriptor_index ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_security_descriptor_index_initialize( NULL, io_handle, file_io_handle, data_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); security_descriptor_index = (libfsntfs_security_descriptor_index_t *) 0x12345678UL; result = libfsntfs_security_descriptor_index_initialize( &security_descriptor_index, io_handle, file_io_handle, data_attribute, &error ); security_descriptor_index = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_security_descriptor_index_initialize( &security_descriptor_index, io_handle, file_io_handle, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_security_descriptor_index_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_security_descriptor_index_initialize( &security_descriptor_index, io_handle, file_io_handle, data_attribute, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( security_descriptor_index != NULL ) { libfsntfs_security_descriptor_index_free( &security_descriptor_index, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "security_descriptor_index", security_descriptor_index ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_security_descriptor_index_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_security_descriptor_index_initialize( &security_descriptor_index, io_handle, file_io_handle, data_attribute, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( security_descriptor_index != NULL ) { libfsntfs_security_descriptor_index_free( &security_descriptor_index, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "security_descriptor_index", security_descriptor_index ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_mft_attribute_free( &data_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "data_attribute", data_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( security_descriptor_index != NULL ) { libfsntfs_security_descriptor_index_free( &security_descriptor_index, NULL ); } if( data_attribute != NULL ) { libfsntfs_mft_attribute_free( &data_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_security_descriptor_index_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_security_descriptor_index_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_security_descriptor_index_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_security_descriptor_index_initialize", fsntfs_test_security_descriptor_index_initialize ); FSNTFS_TEST_RUN( "libfsntfs_security_descriptor_index_free", fsntfs_test_security_descriptor_index_free ); /* TODO: add tests for libfsntfs_security_descriptor_index_read_sii_index */ /* TODO: add tests for libfsntfs_security_descriptor_index_get_security_descriptor_by_identifier */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_security_descriptor_index_value.c ================================================ /* * Library security_descriptor_index_value type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcdata.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_security_descriptor_index_value.h" uint8_t fsntfs_test_security_descriptor_index_value_data1[ 20 ] = { 0xcb, 0xc6, 0xfe, 0x32, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_security_descriptor_index_value_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_security_descriptor_index_value_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_security_descriptor_index_value_t *security_descriptor_index_value = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_security_descriptor_index_value_initialize( &security_descriptor_index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "security_descriptor_index_value", security_descriptor_index_value ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_security_descriptor_index_value_free( &security_descriptor_index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "security_descriptor_index_value", security_descriptor_index_value ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_security_descriptor_index_value_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); security_descriptor_index_value = (libfsntfs_security_descriptor_index_value_t *) 0x12345678UL; result = libfsntfs_security_descriptor_index_value_initialize( &security_descriptor_index_value, &error ); security_descriptor_index_value = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_security_descriptor_index_value_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_security_descriptor_index_value_initialize( &security_descriptor_index_value, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( security_descriptor_index_value != NULL ) { libfsntfs_security_descriptor_index_value_free( &security_descriptor_index_value, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "security_descriptor_index_value", security_descriptor_index_value ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_security_descriptor_index_value_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_security_descriptor_index_value_initialize( &security_descriptor_index_value, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( security_descriptor_index_value != NULL ) { libfsntfs_security_descriptor_index_value_free( &security_descriptor_index_value, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "security_descriptor_index_value", security_descriptor_index_value ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( security_descriptor_index_value != NULL ) { libfsntfs_security_descriptor_index_value_free( &security_descriptor_index_value, NULL ); } return( 0 ); } /* Tests the libfsntfs_security_descriptor_index_value_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_security_descriptor_index_value_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_security_descriptor_index_value_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_security_descriptor_index_value_compare function * Returns 1 if successful or 0 if not */ int fsntfs_test_security_descriptor_index_value_compare( void ) { libcerror_error_t *error = NULL; libfsntfs_security_descriptor_index_value_t *first_security_descriptor_index_value = NULL; libfsntfs_security_descriptor_index_value_t *second_security_descriptor_index_value = NULL; int result = 0; /* Initialize test */ result = libfsntfs_security_descriptor_index_value_initialize( &first_security_descriptor_index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "first_security_descriptor_index_value", first_security_descriptor_index_value ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_security_descriptor_index_value_initialize( &second_security_descriptor_index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "second_security_descriptor_index_value", second_security_descriptor_index_value ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ first_security_descriptor_index_value->identifier = 1; second_security_descriptor_index_value->identifier = 1; result = libfsntfs_security_descriptor_index_value_compare( first_security_descriptor_index_value, second_security_descriptor_index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBCDATA_COMPARE_EQUAL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); first_security_descriptor_index_value->identifier = 1; second_security_descriptor_index_value->identifier = 2; result = libfsntfs_security_descriptor_index_value_compare( first_security_descriptor_index_value, second_security_descriptor_index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBCDATA_COMPARE_LESS ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); first_security_descriptor_index_value->identifier = 2; second_security_descriptor_index_value->identifier = 1; result = libfsntfs_security_descriptor_index_value_compare( first_security_descriptor_index_value, second_security_descriptor_index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, LIBCDATA_COMPARE_GREATER ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_security_descriptor_index_value_compare( NULL, second_security_descriptor_index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_security_descriptor_index_value_compare( first_security_descriptor_index_value, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_security_descriptor_index_value_free( &second_security_descriptor_index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "second_security_descriptor_index_value", second_security_descriptor_index_value ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_security_descriptor_index_value_free( &first_security_descriptor_index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "first_security_descriptor_index_value", first_security_descriptor_index_value ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( second_security_descriptor_index_value != NULL ) { libfsntfs_security_descriptor_index_value_free( &second_security_descriptor_index_value, NULL ); } if( first_security_descriptor_index_value != NULL ) { libfsntfs_security_descriptor_index_value_free( &first_security_descriptor_index_value, NULL ); } return( 0 ); } /* Tests the libfsntfs_security_descriptor_index_value_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_security_descriptor_index_value_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_security_descriptor_index_value_t *security_descriptor_index_value = NULL; int result = 0; /* Initialize test */ result = libfsntfs_security_descriptor_index_value_initialize( &security_descriptor_index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "security_descriptor_index_value", security_descriptor_index_value ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_security_descriptor_index_value_read_data( security_descriptor_index_value, fsntfs_test_security_descriptor_index_value_data1, 20, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_security_descriptor_index_value_read_data( NULL, fsntfs_test_security_descriptor_index_value_data1, 20, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_security_descriptor_index_value_read_data( security_descriptor_index_value, NULL, 20, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_security_descriptor_index_value_read_data( security_descriptor_index_value, fsntfs_test_security_descriptor_index_value_data1, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_security_descriptor_index_value_read_data( security_descriptor_index_value, fsntfs_test_security_descriptor_index_value_data1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_security_descriptor_index_value_free( &security_descriptor_index_value, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "security_descriptor_index_value", security_descriptor_index_value ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( security_descriptor_index_value != NULL ) { libfsntfs_security_descriptor_index_value_free( &security_descriptor_index_value, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_security_descriptor_index_value_initialize", fsntfs_test_security_descriptor_index_value_initialize ); FSNTFS_TEST_RUN( "libfsntfs_security_descriptor_index_value_free", fsntfs_test_security_descriptor_index_value_free ); FSNTFS_TEST_RUN( "libfsntfs_security_descriptor_index_value_compare", fsntfs_test_security_descriptor_index_value_compare ); FSNTFS_TEST_RUN( "libfsntfs_security_descriptor_index_value_read_data", fsntfs_test_security_descriptor_index_value_read_data ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_security_descriptor_values.c ================================================ /* * Library security_descriptor_values type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_functions.h" #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfdata.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" #include "../libfsntfs/libfsntfs_security_descriptor_values.h" uint8_t fsntfs_test_security_descriptor_values_data1[ 128 ] = { 0x50, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x64, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x80, 0x48, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x89, 0x00, 0x12, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x89, 0x00, 0x12, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Reads data from the current offset into a buffer * Callback for the compressed block descriptor data stream * Returns the number of bytes read or -1 on error */ ssize_t fsntfs_test_security_descriptor_values_read_segment_data( intptr_t *data_handle FSNTFS_TEST_ATTRIBUTE_UNUSED, libbfio_handle_t *file_io_handle, int segment_index FSNTFS_TEST_ATTRIBUTE_UNUSED, int segment_file_index FSNTFS_TEST_ATTRIBUTE_UNUSED, uint8_t *segment_data, size_t segment_data_size, uint32_t segment_flags FSNTFS_TEST_ATTRIBUTE_UNUSED, uint8_t read_flags FSNTFS_TEST_ATTRIBUTE_UNUSED, libcerror_error_t **error ) { static char *function = "fsntfs_test_security_descriptor_values_read_segment_data"; ssize_t read_count = 0; FSNTFS_TEST_UNREFERENCED_PARAMETER( data_handle ) FSNTFS_TEST_UNREFERENCED_PARAMETER( segment_index ) FSNTFS_TEST_UNREFERENCED_PARAMETER( segment_file_index ) FSNTFS_TEST_UNREFERENCED_PARAMETER( segment_flags ) FSNTFS_TEST_UNREFERENCED_PARAMETER( read_flags ) read_count = libbfio_handle_read_buffer( file_io_handle, segment_data, segment_data_size, error ); if( read_count != (ssize_t) segment_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read segment data.", function ); return( -1 ); } return( read_count ); } /* Seeks a certain offset of the data * Callback for the cluster block stream * Returns the offset if seek is successful or -1 on error */ off64_t fsntfs_test_security_descriptor_values_seek_segment_offset( intptr_t *data_handle FSNTFS_TEST_ATTRIBUTE_UNUSED, libbfio_handle_t *file_io_handle, int segment_index FSNTFS_TEST_ATTRIBUTE_UNUSED, int segment_file_index FSNTFS_TEST_ATTRIBUTE_UNUSED, off64_t segment_offset, libcerror_error_t **error ) { static char *function = "fsntfs_test_security_descriptor_values_seek_segment_offset"; FSNTFS_TEST_UNREFERENCED_PARAMETER( data_handle ) FSNTFS_TEST_UNREFERENCED_PARAMETER( segment_index ) FSNTFS_TEST_UNREFERENCED_PARAMETER( segment_file_index ) if( libbfio_handle_seek_offset( file_io_handle, segment_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek segment offset: %" PRIi64 " (0x%08" PRIx64 ").", function, segment_offset, segment_offset ); return( -1 ); } return( segment_offset ); } /* Tests the libfsntfs_security_descriptor_values_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_security_descriptor_values_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_security_descriptor_values_t *security_descriptor_values = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_security_descriptor_values_initialize( &security_descriptor_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "security_descriptor_values", security_descriptor_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_security_descriptor_values_free( &security_descriptor_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "security_descriptor_values", security_descriptor_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_security_descriptor_values_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); security_descriptor_values = (libfsntfs_security_descriptor_values_t *) 0x12345678UL; result = libfsntfs_security_descriptor_values_initialize( &security_descriptor_values, &error ); security_descriptor_values = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_security_descriptor_values_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_security_descriptor_values_initialize( &security_descriptor_values, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( security_descriptor_values != NULL ) { libfsntfs_security_descriptor_values_free( &security_descriptor_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "security_descriptor_values", security_descriptor_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_security_descriptor_values_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_security_descriptor_values_initialize( &security_descriptor_values, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( security_descriptor_values != NULL ) { libfsntfs_security_descriptor_values_free( &security_descriptor_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "security_descriptor_values", security_descriptor_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( security_descriptor_values != NULL ) { libfsntfs_security_descriptor_values_free( &security_descriptor_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_security_descriptor_values_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_security_descriptor_values_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_security_descriptor_values_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_security_descriptor_values_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_security_descriptor_values_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_security_descriptor_values_t *security_descriptor_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_security_descriptor_values_initialize( &security_descriptor_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "security_descriptor_values", security_descriptor_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_security_descriptor_values_read_data( security_descriptor_values, &( fsntfs_test_security_descriptor_values_data1[ 24 ] ), 100, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_security_descriptor_values_read_data( NULL, &( fsntfs_test_security_descriptor_values_data1[ 24 ] ), 100, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_security_descriptor_values_read_data( security_descriptor_values, NULL, 100, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_security_descriptor_values_read_data( security_descriptor_values, &( fsntfs_test_security_descriptor_values_data1[ 24 ] ), (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_security_descriptor_values_free( &security_descriptor_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "security_descriptor_values", security_descriptor_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( security_descriptor_values != NULL ) { libfsntfs_security_descriptor_values_free( &security_descriptor_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_security_descriptor_values_read_buffer function * Returns 1 if successful or 0 if not */ int fsntfs_test_security_descriptor_values_read_buffer( void ) { libcerror_error_t *error = NULL; libfsntfs_security_descriptor_values_t *security_descriptor_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_security_descriptor_values_initialize( &security_descriptor_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "security_descriptor_values", security_descriptor_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_security_descriptor_values_read_buffer( security_descriptor_values, &( fsntfs_test_security_descriptor_values_data1[ 24 ] ), 100, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_security_descriptor_values_read_buffer( security_descriptor_values, &( fsntfs_test_security_descriptor_values_data1[ 24 ] ), 100, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_security_descriptor_values_free( &security_descriptor_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "security_descriptor_values", security_descriptor_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ result = libfsntfs_security_descriptor_values_initialize( &security_descriptor_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "security_descriptor_values", security_descriptor_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_security_descriptor_values_read_buffer( NULL, &( fsntfs_test_security_descriptor_values_data1[ 24 ] ), 100, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_security_descriptor_values_read_buffer( security_descriptor_values, NULL, 100, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_security_descriptor_values_read_buffer( security_descriptor_values, &( fsntfs_test_security_descriptor_values_data1[ 24 ] ), (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_security_descriptor_values_read_buffer( security_descriptor_values, &( fsntfs_test_security_descriptor_values_data1[ 24 ] ), 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) /* Test libfsntfs_security_descriptor_values_read_buffer with malloc failing */ fsntfs_test_malloc_attempts_before_fail = 0; result = libfsntfs_security_descriptor_values_read_buffer( security_descriptor_values, &( fsntfs_test_security_descriptor_values_data1[ 24 ] ), 100, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #if defined( OPTIMIZATION_DISABLED ) /* Test libfsntfs_security_descriptor_values_read_buffer with memcpy failing */ fsntfs_test_memcpy_attempts_before_fail = 0; result = libfsntfs_security_descriptor_values_read_buffer( security_descriptor_values, &( fsntfs_test_security_descriptor_values_data1[ 24 ] ), 100, &error ); if( fsntfs_test_memcpy_attempts_before_fail != -1 ) { fsntfs_test_memcpy_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( OPTIMIZATION_DISABLED ) */ #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Test libfsntfs_security_descriptor_values_read_buffer with libfsntfs_security_descriptor_values_read_data failing */ /* TODO implement */ /* Clean up */ result = libfsntfs_security_descriptor_values_free( &security_descriptor_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "security_descriptor_values", security_descriptor_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( security_descriptor_values != NULL ) { libfsntfs_security_descriptor_values_free( &security_descriptor_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_security_descriptor_values_read_stream function * Returns 1 if successful or 0 if not */ int fsntfs_test_security_descriptor_values_read_stream( void ) { libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfdata_stream_t *data_stream = NULL; libfsntfs_security_descriptor_values_t *security_descriptor_values = NULL; int element_index = 0; int result = 0; /* Initialize test */ result = fsntfs_test_open_file_io_handle( &file_io_handle, &( fsntfs_test_security_descriptor_values_data1[ 24 ] ), 100, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfdata_stream_initialize( &data_stream, NULL, NULL, NULL, NULL, (ssize_t (*)(intptr_t *, intptr_t *, int, int, uint8_t *, size_t, uint32_t, uint8_t, libcerror_error_t **)) &fsntfs_test_security_descriptor_values_read_segment_data, NULL, (off64_t (*)(intptr_t *, intptr_t *, int, int, off64_t, libcerror_error_t **)) &fsntfs_test_security_descriptor_values_seek_segment_offset, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "data_stream", data_stream ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfdata_stream_append_segment( data_stream, &element_index, 0, 0, 100, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_security_descriptor_values_initialize( &security_descriptor_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "security_descriptor_values", security_descriptor_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_security_descriptor_values_read_stream( security_descriptor_values, file_io_handle, data_stream, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_security_descriptor_values_read_stream( security_descriptor_values, file_io_handle, data_stream, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_security_descriptor_values_free( &security_descriptor_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "security_descriptor_values", security_descriptor_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ result = libfsntfs_security_descriptor_values_initialize( &security_descriptor_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "security_descriptor_values", security_descriptor_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_security_descriptor_values_read_stream( NULL, file_io_handle, data_stream, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* TODO implement */ /* Clean up */ result = libfsntfs_security_descriptor_values_free( &security_descriptor_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "security_descriptor_values", security_descriptor_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfdata_stream_free( &data_stream, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "data_stream", data_stream ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libbfio_handle_free( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( security_descriptor_values != NULL ) { libfsntfs_security_descriptor_values_free( &security_descriptor_values, NULL ); } if( data_stream != NULL ) { libfdata_stream_free( &data_stream, NULL ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_security_descriptor_values_read_from_mft_attribute function * Returns 1 if successful or 0 if not */ int fsntfs_test_security_descriptor_values_read_from_mft_attribute( void ) { libcerror_error_t *error = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; libfsntfs_security_descriptor_values_t *security_descriptor_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_security_descriptor_values_data1, 128, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_security_descriptor_values_initialize( &security_descriptor_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "security_descriptor_values", security_descriptor_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_security_descriptor_values_read_from_mft_attribute( security_descriptor_values, mft_attribute, io_handle, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_security_descriptor_values_read_from_mft_attribute( NULL, mft_attribute, io_handle, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_security_descriptor_values_read_from_mft_attribute( security_descriptor_values, NULL, io_handle, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_security_descriptor_values_free( &security_descriptor_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "security_descriptor_values", security_descriptor_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( security_descriptor_values != NULL ) { libfsntfs_security_descriptor_values_free( &security_descriptor_values, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_security_descriptor_values_get_data_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_security_descriptor_values_get_data_size( libfsntfs_security_descriptor_values_t *security_descriptor_values ) { libcerror_error_t *error = NULL; size_t data_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_security_descriptor_values_get_data_size( security_descriptor_values, &data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "data_size", data_size, (size_t) 100 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_security_descriptor_values_get_data_size( NULL, &data_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_security_descriptor_values_get_data_size( security_descriptor_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_security_descriptor_values_get_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_security_descriptor_values_get_data( libfsntfs_security_descriptor_values_t *security_descriptor_values ) { uint8_t data[ 128 ]; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_security_descriptor_values_get_data( security_descriptor_values, data, 128, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_security_descriptor_values_get_data( NULL, data, 128, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_security_descriptor_values_get_data( security_descriptor_values, NULL, 128, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_security_descriptor_values_get_data( security_descriptor_values, data, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_security_descriptor_values_get_data( security_descriptor_values, data, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) && defined( OPTIMIZATION_DISABLED ) /* Test libfsntfs_security_descriptor_values_get_data with memcpy failing */ fsntfs_test_memcpy_attempts_before_fail = 0; result = libfsntfs_security_descriptor_values_get_data( security_descriptor_values, data, 128, &error ); if( fsntfs_test_memcpy_attempts_before_fail != -1 ) { fsntfs_test_memcpy_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( OPTIMIZATION_DISABLED ) && defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_security_descriptor_values_t *security_descriptor_values = NULL; int result = 0; #endif FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_security_descriptor_values_initialize", fsntfs_test_security_descriptor_values_initialize ); FSNTFS_TEST_RUN( "libfsntfs_security_descriptor_values_free", fsntfs_test_security_descriptor_values_free ); FSNTFS_TEST_RUN( "libfsntfs_security_descriptor_values_read_data", fsntfs_test_security_descriptor_values_read_data ); FSNTFS_TEST_RUN( "libfsntfs_security_descriptor_values_read_buffer", fsntfs_test_security_descriptor_values_read_buffer ); FSNTFS_TEST_RUN( "libfsntfs_security_descriptor_values_read_stream", fsntfs_test_security_descriptor_values_read_stream ); FSNTFS_TEST_RUN( "libfsntfs_security_descriptor_values_read_from_mft_attribute", fsntfs_test_security_descriptor_values_read_from_mft_attribute ); #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize security_descriptor_values for tests */ result = libfsntfs_security_descriptor_values_initialize( &security_descriptor_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "security_descriptor_values", security_descriptor_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_security_descriptor_values_read_buffer( security_descriptor_values, &( fsntfs_test_security_descriptor_values_data1[ 24 ] ), 100, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_security_descriptor_values_get_data_size", fsntfs_test_security_descriptor_values_get_data_size, security_descriptor_values ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_security_descriptor_values_get_data", fsntfs_test_security_descriptor_values_get_data, security_descriptor_values ); /* Clean up */ result = libfsntfs_security_descriptor_values_free( &security_descriptor_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "security_descriptor_values", security_descriptor_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); on_error: #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) if( error != NULL ) { libcerror_error_free( &error ); } if( security_descriptor_values != NULL ) { libfsntfs_security_descriptor_values_free( &security_descriptor_values, NULL ); } #endif return( EXIT_FAILURE ); } ================================================ FILE: tests/fsntfs_test_standard_information_values.c ================================================ /* * Library standard_information_values type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" #include "../libfsntfs/libfsntfs_standard_information_values.h" uint8_t fsntfs_test_standard_information_values_data1[ 96 ] = { 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xad, 0xca, 0xbc, 0x0c, 0xdc, 0x8e, 0xd0, 0x01, 0xad, 0xca, 0xbc, 0x0c, 0xdc, 0x8e, 0xd0, 0x01, 0xad, 0xca, 0xbc, 0x0c, 0xdc, 0x8e, 0xd0, 0x01, 0xad, 0xca, 0xbc, 0x0c, 0xdc, 0x8e, 0xd0, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_standard_information_values_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_standard_information_values_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_standard_information_values_initialize( &standard_information_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "standard_information_values", standard_information_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_standard_information_values_free( &standard_information_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "standard_information_values", standard_information_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_standard_information_values_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); standard_information_values = (libfsntfs_standard_information_values_t *) 0x12345678UL; result = libfsntfs_standard_information_values_initialize( &standard_information_values, &error ); standard_information_values = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_standard_information_values_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_standard_information_values_initialize( &standard_information_values, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( standard_information_values != NULL ) { libfsntfs_standard_information_values_free( &standard_information_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "standard_information_values", standard_information_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_standard_information_values_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_standard_information_values_initialize( &standard_information_values, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( standard_information_values != NULL ) { libfsntfs_standard_information_values_free( &standard_information_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "standard_information_values", standard_information_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( standard_information_values != NULL ) { libfsntfs_standard_information_values_free( &standard_information_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_standard_information_values_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_standard_information_values_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_standard_information_values_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_standard_information_values_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_standard_information_values_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_standard_information_values_initialize( &standard_information_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "standard_information_values", standard_information_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_standard_information_values_read_data( standard_information_values, &( fsntfs_test_standard_information_values_data1[ 24 ] ), 72, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_standard_information_values_read_data( NULL, &( fsntfs_test_standard_information_values_data1[ 24 ] ), 72, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_standard_information_values_read_data( standard_information_values, NULL, 72, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_standard_information_values_read_data( standard_information_values, &( fsntfs_test_standard_information_values_data1[ 24 ] ), (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_standard_information_values_read_data( standard_information_values, &( fsntfs_test_standard_information_values_data1[ 24 ] ), 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_standard_information_values_free( &standard_information_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "standard_information_values", standard_information_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( standard_information_values != NULL ) { libfsntfs_standard_information_values_free( &standard_information_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_standard_information_values_read_from_mft_attribute function * Returns 1 if successful or 0 if not */ int fsntfs_test_standard_information_values_read_from_mft_attribute( void ) { libcerror_error_t *error = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_standard_information_values_data1, 96, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_standard_information_values_initialize( &standard_information_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "standard_information_values", standard_information_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_standard_information_values_read_from_mft_attribute( standard_information_values, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_standard_information_values_read_from_mft_attribute( NULL, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_standard_information_values_read_from_mft_attribute( standard_information_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_standard_information_values_free( &standard_information_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "standard_information_values", standard_information_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( standard_information_values != NULL ) { libfsntfs_standard_information_values_free( &standard_information_values, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_standard_information_values_get_creation_time function * Returns 1 if successful or 0 if not */ int fsntfs_test_standard_information_values_get_creation_time( libfsntfs_standard_information_values_t *standard_information_values ) { libcerror_error_t *error = NULL; uint64_t creation_time = 0; int result = 0; /* Test regular cases */ result = libfsntfs_standard_information_values_get_creation_time( standard_information_values, &creation_time, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_standard_information_values_get_creation_time( NULL, &creation_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_standard_information_values_get_creation_time( standard_information_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_standard_information_values_get_modification_time function * Returns 1 if successful or 0 if not */ int fsntfs_test_standard_information_values_get_modification_time( libfsntfs_standard_information_values_t *standard_information_values ) { libcerror_error_t *error = NULL; uint64_t modification_time = 0; int result = 0; /* Test regular cases */ result = libfsntfs_standard_information_values_get_modification_time( standard_information_values, &modification_time, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_standard_information_values_get_modification_time( NULL, &modification_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_standard_information_values_get_modification_time( standard_information_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_standard_information_values_get_access_time function * Returns 1 if successful or 0 if not */ int fsntfs_test_standard_information_values_get_access_time( libfsntfs_standard_information_values_t *standard_information_values ) { libcerror_error_t *error = NULL; uint64_t access_time = 0; int result = 0; /* Test regular cases */ result = libfsntfs_standard_information_values_get_access_time( standard_information_values, &access_time, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_standard_information_values_get_access_time( NULL, &access_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_standard_information_values_get_access_time( standard_information_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_standard_information_values_get_entry_modification_time function * Returns 1 if successful or 0 if not */ int fsntfs_test_standard_information_values_get_entry_modification_time( libfsntfs_standard_information_values_t *standard_information_values ) { libcerror_error_t *error = NULL; uint64_t entry_modification_time = 0; int result = 0; /* Test regular cases */ result = libfsntfs_standard_information_values_get_entry_modification_time( standard_information_values, &entry_modification_time, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_standard_information_values_get_entry_modification_time( NULL, &entry_modification_time, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_standard_information_values_get_entry_modification_time( standard_information_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_standard_information_values_get_file_attribute_flags function * Returns 1 if successful or 0 if not */ int fsntfs_test_standard_information_values_get_file_attribute_flags( libfsntfs_standard_information_values_t *standard_information_values ) { libcerror_error_t *error = NULL; uint32_t file_attribute_flags = 0; int result = 0; /* Test regular cases */ result = libfsntfs_standard_information_values_get_file_attribute_flags( standard_information_values, &file_attribute_flags, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_standard_information_values_get_file_attribute_flags( NULL, &file_attribute_flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_standard_information_values_get_file_attribute_flags( standard_information_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_standard_information_values_get_security_descriptor_identifier function * Returns 1 if successful or 0 if not */ int fsntfs_test_standard_information_values_get_security_descriptor_identifier( libfsntfs_standard_information_values_t *standard_information_values ) { libcerror_error_t *error = NULL; uint32_t security_descriptor_identifier = 0; int result = 0; /* Test regular cases */ result = libfsntfs_standard_information_values_get_security_descriptor_identifier( standard_information_values, &security_descriptor_identifier, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_standard_information_values_get_security_descriptor_identifier( NULL, &security_descriptor_identifier, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_standard_information_values_get_security_descriptor_identifier( standard_information_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_standard_information_values_get_update_sequence_number function * Returns 1 if successful or 0 if not */ int fsntfs_test_standard_information_values_get_update_sequence_number( libfsntfs_standard_information_values_t *standard_information_values ) { libcerror_error_t *error = NULL; uint64_t update_sequence_number = 0; int result = 0; /* Test regular cases */ result = libfsntfs_standard_information_values_get_update_sequence_number( standard_information_values, &update_sequence_number, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_standard_information_values_get_update_sequence_number( NULL, &update_sequence_number, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_standard_information_values_get_update_sequence_number( standard_information_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_standard_information_values_t *standard_information_values = NULL; int result = 0; #endif FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_standard_information_values_initialize", fsntfs_test_standard_information_values_initialize ); FSNTFS_TEST_RUN( "libfsntfs_standard_information_values_free", fsntfs_test_standard_information_values_free ); FSNTFS_TEST_RUN( "libfsntfs_standard_information_values_read_data", fsntfs_test_standard_information_values_read_data ); FSNTFS_TEST_RUN( "fsntfs_test_standard_information_values_read_from_mft_attribute", fsntfs_test_standard_information_values_read_from_mft_attribute ); #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize standard_information_values for tests */ result = libfsntfs_standard_information_values_initialize( &standard_information_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "standard_information_values", standard_information_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_standard_information_values_read_data( standard_information_values, &( fsntfs_test_standard_information_values_data1[ 24 ] ), 72, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_standard_information_values_get_creation_time", fsntfs_test_standard_information_values_get_creation_time, standard_information_values ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_standard_information_values_get_modification_time", fsntfs_test_standard_information_values_get_modification_time, standard_information_values ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_standard_information_values_get_access_time", fsntfs_test_standard_information_values_get_access_time, standard_information_values ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_standard_information_values_get_entry_modification_time", fsntfs_test_standard_information_values_get_entry_modification_time, standard_information_values ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_standard_information_values_get_file_attribute_flags", fsntfs_test_standard_information_values_get_file_attribute_flags, standard_information_values ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_standard_information_values_get_security_descriptor_identifier", fsntfs_test_standard_information_values_get_security_descriptor_identifier, standard_information_values ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_standard_information_values_get_update_sequence_number", fsntfs_test_standard_information_values_get_update_sequence_number, standard_information_values ); /* Clean up */ result = libfsntfs_standard_information_values_free( &standard_information_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "standard_information_values", standard_information_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( standard_information_values != NULL ) { libfsntfs_standard_information_values_free( &standard_information_values, NULL ); } return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_support.c ================================================ /* * Library support functions test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_functions.h" #include "fsntfs_test_getopt.h" #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #if !defined( LIBFSNTFS_HAVE_BFIO ) LIBFSNTFS_EXTERN \ int libfsntfs_check_volume_signature_file_io_handle( libbfio_handle_t *file_io_handle, libcerror_error_t **error ); #endif /* !defined( LIBFSNTFS_HAVE_BFIO ) */ /* Tests the libfsntfs_get_version function * Returns 1 if successful or 0 if not */ int fsntfs_test_get_version( void ) { const char *version_string = NULL; int result = 0; version_string = libfsntfs_get_version(); result = narrow_string_compare( version_string, LIBFSNTFS_VERSION_STRING, 9 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); return( 1 ); on_error: return( 0 ); } /* Tests the libfsntfs_get_access_flags_read function * Returns 1 if successful or 0 if not */ int fsntfs_test_get_access_flags_read( void ) { int access_flags = 0; access_flags = libfsntfs_get_access_flags_read(); FSNTFS_TEST_ASSERT_EQUAL_INT( "access_flags", access_flags, LIBFSNTFS_ACCESS_FLAG_READ ); return( 1 ); on_error: return( 0 ); } /* Tests the libfsntfs_get_codepage function * Returns 1 if successful or 0 if not */ int fsntfs_test_get_codepage( void ) { libcerror_error_t *error = NULL; int codepage = 0; int result = 0; result = libfsntfs_get_codepage( &codepage, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_get_codepage( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_set_codepage function * Returns 1 if successful or 0 if not */ int fsntfs_test_set_codepage( void ) { libcerror_error_t *error = NULL; int result = 0; result = libfsntfs_set_codepage( 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_set_codepage( -1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_check_volume_signature function * Returns 1 if successful or 0 if not */ int fsntfs_test_check_volume_signature( const system_character_t *source ) { char narrow_source[ 256 ]; libcerror_error_t *error = NULL; int result = 0; if( source != NULL ) { /* Initialize test */ result = fsntfs_test_get_narrow_source( source, narrow_source, 256, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test check volume signature */ result = libfsntfs_check_volume_signature( narrow_source, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } /* Test error cases */ result = libfsntfs_check_volume_signature( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_check_volume_signature( "", &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( source != NULL ) { #if defined( HAVE_FSNTFS_TEST_MEMORY ) /* Test libfsntfs_check_volume_signature with malloc failing in libbfio_file_initialize */ fsntfs_test_malloc_attempts_before_fail = 0; result = libfsntfs_check_volume_signature( narrow_source, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ } return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #if defined( HAVE_WIDE_CHARACTER_TYPE ) /* Tests the libfsntfs_check_volume_signature_wide function * Returns 1 if successful or 0 if not */ int fsntfs_test_check_volume_signature_wide( const system_character_t *source ) { wchar_t wide_source[ 256 ]; libcerror_error_t *error = NULL; int result = 0; if( source != NULL ) { /* Initialize test */ result = fsntfs_test_get_wide_source( source, wide_source, 256, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test check volume signature */ result = libfsntfs_check_volume_signature_wide( wide_source, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } /* Test error cases */ result = libfsntfs_check_volume_signature_wide( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_check_volume_signature_wide( L"", &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( source != NULL ) { #if defined( HAVE_FSNTFS_TEST_MEMORY ) /* Test libfsntfs_check_volume_signature_wide with malloc failing in libbfio_file_initialize */ fsntfs_test_malloc_attempts_before_fail = 0; result = libfsntfs_check_volume_signature_wide( wide_source, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ } return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */ /* Tests the libfsntfs_check_volume_signature_file_io_handle function * Returns 1 if successful or 0 if not */ int fsntfs_test_check_volume_signature_file_io_handle( const system_character_t *source ) { uint8_t empty_block[ 8192 ]; libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; void *memset_result = NULL; size_t source_length = 0; int result = 0; /* Initialize test */ memset_result = memory_set( empty_block, 0, sizeof( uint8_t ) * 8192 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "memset_result", memset_result ); if( source != NULL ) { /* Initialize test */ result = libbfio_file_initialize( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); source_length = system_string_length( source ); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libbfio_file_set_name_wide( file_io_handle, source, source_length, &error ); #else result = libbfio_file_set_name( file_io_handle, source, source_length, &error ); #endif FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libbfio_handle_open( file_io_handle, LIBBFIO_OPEN_READ, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test check volume signature */ result = libfsntfs_check_volume_signature_file_io_handle( file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } /* Test error cases */ result = libfsntfs_check_volume_signature_file_io_handle( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ if( source != NULL ) { result = libbfio_handle_close( file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libbfio_handle_free( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } /* Test check volume signature with data too small */ result = fsntfs_test_open_file_io_handle( &file_io_handle, empty_block, sizeof( uint8_t ) * 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_check_volume_signature_file_io_handle( file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test check volume signature with empty block */ result = fsntfs_test_open_file_io_handle( &file_io_handle, empty_block, sizeof( uint8_t ) * 8192, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_check_volume_signature_file_io_handle( file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } return( 0 ); } /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc, wchar_t * const argv[] ) #else int main( int argc, char * const argv[] ) #endif { libcerror_error_t *error = NULL; system_character_t *option_offset = NULL; system_character_t *source = NULL; system_integer_t option = 0; size_t string_length = 0; off64_t volume_offset = 0; int result = 0; while( ( option = fsntfs_test_getopt( argc, argv, _SYSTEM_STRING( "o:" ) ) ) != (system_integer_t) -1 ) { switch( option ) { case (system_integer_t) '?': default: fprintf( stderr, "Invalid argument: %" PRIs_SYSTEM ".\n", argv[ optind - 1 ] ); return( EXIT_FAILURE ); case (system_integer_t) 'o': option_offset = optarg; break; } } if( optind < argc ) { source = argv[ optind ]; } if( option_offset != NULL ) { string_length = system_string_length( option_offset ); result = fsntfs_test_system_string_copy_from_64_bit_in_decimal( option_offset, string_length + 1, (uint64_t *) &volume_offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } FSNTFS_TEST_RUN( "libfsntfs_get_version", fsntfs_test_get_version ); FSNTFS_TEST_RUN( "libfsntfs_get_access_flags_read", fsntfs_test_get_access_flags_read ); FSNTFS_TEST_RUN( "libfsntfs_get_codepage", fsntfs_test_get_codepage ); FSNTFS_TEST_RUN( "libfsntfs_set_codepage", fsntfs_test_set_codepage ); #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) if( ( source != NULL ) && ( volume_offset == 0 ) ) { FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_check_volume_signature", fsntfs_test_check_volume_signature, source ); #if defined( HAVE_WIDE_CHARACTER_TYPE ) FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_check_volume_signature_wide", fsntfs_test_check_volume_signature_wide, source ); #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_check_volume_signature_file_io_handle", fsntfs_test_check_volume_signature_file_io_handle, source ); } #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ return( EXIT_SUCCESS ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( EXIT_FAILURE ); } ================================================ FILE: tests/fsntfs_test_tools_bodyfile.c ================================================ /* * Tools bodyfile functions test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_unused.h" #include "../fsntfstools/bodyfile.h" /* Tests the bodyfile_path_string_copy_from_file_entry_path function * Returns 1 if successful or 0 if not */ int fsntfs_test_tools_bodyfile_path_string_copy_from_file_entry_path( void ) { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) system_character_t file_entry_path3[ 5 ] = { 't', 'e', 0x2028, 't', 0 }; #else system_character_t file_entry_path3[ 7 ] = { 't', 'e', 0xe2, 0x80, 0xa8, 't', 0 }; #endif system_character_t file_entry_path1[ 5 ] = { 't', 'e', 's', 't', 0 }; system_character_t file_entry_path2[ 5 ] = { 't', 'e', 0x03, 't', 0 }; system_character_t file_entry_path4[ 5 ] = { 't', 'e', '\\', 't', 0 }; system_character_t expected_path1[ 5 ] = { 't', 'e', 's', 't', 0 }; system_character_t expected_path2[ 8 ] = { 't', 'e', '\\', 'x', '0', '3', 't', 0 }; system_character_t expected_path3[ 14 ] = { 't', 'e', '\\', 'U', '0', '0', '0', '0', '2', '0', '2', '8', 't', 0 }; system_character_t expected_path4[ 6 ] = { 't', 'e', '\\', '\\', 't', 0 }; libcerror_error_t *error = NULL; system_character_t *path = NULL; size_t path_size = 0; int result = 0; /* Test regular cases */ result = bodyfile_path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path1, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "path", path ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "path_size", path_size, (size_t) 41 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( path, expected_path1, 5 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( path ); path = NULL; result = bodyfile_path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path2, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "path", path ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "path_size", path_size, (size_t) 41 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( path, expected_path2, 8 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( path ); path = NULL; #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = bodyfile_path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path3, 4, &error ); #else result = bodyfile_path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path3, 6, &error ); #endif FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "path", path ); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) FSNTFS_TEST_ASSERT_EQUAL_SIZE( "path_size", path_size, (size_t) 41 ); #else FSNTFS_TEST_ASSERT_EQUAL_SIZE( "path_size", path_size, (size_t) 61 ); #endif FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( path, expected_path3, 14 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( path ); path = NULL; result = bodyfile_path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path4, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "path", path ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "path_size", path_size, (size_t) 41 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( path, expected_path4, 6 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( path ); path = NULL; /* TODO add test for escaping | */ /* Test error cases */ result = bodyfile_path_string_copy_from_file_entry_path( NULL, &path_size, file_entry_path1, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = bodyfile_path_string_copy_from_file_entry_path( &path, NULL, file_entry_path1, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = bodyfile_path_string_copy_from_file_entry_path( &path, &path_size, NULL, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = bodyfile_path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = bodyfile_path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path1, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( path != NULL ) { memory_free( path ); } if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) FSNTFS_TEST_RUN( "bodyfile_path_string_copy_from_file_entry_path", fsntfs_test_tools_bodyfile_path_string_copy_from_file_entry_path ) return( EXIT_SUCCESS ); on_error: return( EXIT_FAILURE ); } ================================================ FILE: tests/fsntfs_test_tools_digest_hash.c ================================================ /* * Tools digest_hash functions test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_unused.h" #include "../fsntfstools/digest_hash.h" /* Tests the digest_hash_copy_to_string function * Returns 1 if successful or 0 if not */ int fsntfs_test_tools_digest_hash_copy_to_string( void ) { char string[ 64 ]; uint8_t md5_hash[ 16 ] = { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e }; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = digest_hash_copy_to_string( md5_hash, 16, string, 64, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( string, "d41d8cd98f00b204e9800998ecf8427e", 33 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); /* Test error cases */ result = digest_hash_copy_to_string( NULL, 16, string, 64, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = digest_hash_copy_to_string( md5_hash, (size_t) SSIZE_MAX + 1, string, 64, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = digest_hash_copy_to_string( md5_hash, 16, NULL, 64, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = digest_hash_copy_to_string( md5_hash, 16, string, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = digest_hash_copy_to_string( md5_hash, 16, string, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) FSNTFS_TEST_RUN( "digest_hash_copy_to_string", fsntfs_test_tools_digest_hash_copy_to_string ); return( EXIT_SUCCESS ); on_error: return( EXIT_FAILURE ); } ================================================ FILE: tests/fsntfs_test_tools_info_handle.c ================================================ /* * Tools info_handle type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../fsntfstools/info_handle.h" /* Tests the info_handle_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_tools_info_handle_initialize( void ) { info_handle_t *info_handle = NULL; libcerror_error_t *error = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = info_handle_initialize( &info_handle, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "info_handle", info_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = info_handle_free( &info_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "info_handle", info_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = info_handle_initialize( NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); info_handle = (info_handle_t *) 0x12345678UL; result = info_handle_initialize( &info_handle, 0, &error ); info_handle = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test info_handle_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = info_handle_initialize( &info_handle, 0, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( info_handle != NULL ) { info_handle_free( &info_handle, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "info_handle", info_handle ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test info_handle_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = info_handle_initialize( &info_handle, 0, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( info_handle != NULL ) { info_handle_free( &info_handle, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "info_handle", info_handle ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( info_handle != NULL ) { info_handle_free( &info_handle, NULL ); } return( 0 ); } /* Tests the info_handle_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_tools_info_handle_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = info_handle_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) FSNTFS_TEST_RUN( "info_handle_initialize", fsntfs_test_tools_info_handle_initialize ); FSNTFS_TEST_RUN( "info_handle_free", fsntfs_test_tools_info_handle_free ); return( EXIT_SUCCESS ); on_error: return( EXIT_FAILURE ); } ================================================ FILE: tests/fsntfs_test_tools_mount_path_string.c ================================================ /* * Tools mount_path_string functions test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libcpath.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_unused.h" #include "../fsntfstools/mount_path_string.h" #if defined( WINAPI ) #define ESCAPE_CHARACTER (system_character_t) '^' #else #define ESCAPE_CHARACTER (system_character_t) '\\' #endif /* Tests the mount_path_string_copy_hexadecimal_to_integer_32_bit function * Returns 1 if successful or 0 if not */ int fsntfs_test_tools_mount_path_string_copy_hexadecimal_to_integer_32_bit( void ) { system_character_t error_string[ 5 ] = { '2', '0', 'Z', '8', 0 }; system_character_t string[ 5 ] = { '2', '0', '2', '8', 0 }; libcerror_error_t *error = NULL; uint32_t value_32bit = 0; int result = 0; /* Test regular cases */ result = mount_path_string_copy_hexadecimal_to_integer_32_bit( string, 4, &value_32bit, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT32( "value_32bit", value_32bit, (uint32_t) 0x2028 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = mount_path_string_copy_hexadecimal_to_integer_32_bit( NULL, 4, &value_32bit, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = mount_path_string_copy_hexadecimal_to_integer_32_bit( string, 0, &value_32bit, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = mount_path_string_copy_hexadecimal_to_integer_32_bit( string, (size_t) SSIZE_MAX + 1, &value_32bit, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = mount_path_string_copy_hexadecimal_to_integer_32_bit( string, 4, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = mount_path_string_copy_hexadecimal_to_integer_32_bit( error_string, 4, &value_32bit, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the mount_path_string_copy_from_file_entry_path function * Returns 1 if successful or 0 if not */ int fsntfs_test_tools_mount_path_string_copy_from_file_entry_path( void ) { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) system_character_t file_entry_path3[ 5 ] = { 't', 'e', 0x2028, 't', 0 }; system_character_t file_entry_path4[ 5 ] = { 't', 'e', '\\', 't', 0 }; system_character_t file_entry_path5[ 5 ] = { 't', 'e', ESCAPE_CHARACTER, 't', 0 }; system_character_t expected_path2[ 8 ] = { 't', 'e', ESCAPE_CHARACTER, 'x', '0', '3', 't', 0 }; system_character_t expected_path3[ 14 ] = { 't', 'e', ESCAPE_CHARACTER, 'U', '0', '0', '0', '0', '2', '0', '2', '8', 't', 0 }; system_character_t expected_path4[ 8 ] = { 't', 'e', ESCAPE_CHARACTER, 'x', '5', 'c', 't', 0 }; system_character_t expected_path5[ 6 ] = { 't', 'e', ESCAPE_CHARACTER, ESCAPE_CHARACTER, 't', 0 }; #else system_character_t file_entry_path3[ 7 ] = { 't', 'e', 0xe2, 0x80, 0xa8, 't', 0 }; system_character_t file_entry_path4[ 5 ] = { 't', 'e', LIBCPATH_SEPARATOR, 't', 0 }; system_character_t file_entry_path5[ 5 ] = { 't', 'e', ESCAPE_CHARACTER, 't', 0 }; system_character_t expected_path2[ 8 ] = { 't', 'e', ESCAPE_CHARACTER, 'x', '0', '3', 't', 0 }; system_character_t expected_path3[ 14 ] = { 't', 'e', ESCAPE_CHARACTER, 'U', '0', '0', '0', '0', '2', '0', '2', '8', 't', 0 }; #if defined( WINAPI ) system_character_t expected_path4[ 8 ] = { 't', 'e', ESCAPE_CHARACTER, 'x', '5', 'c', 't', 0 }; #else system_character_t expected_path4[ 8 ] = { 't', 'e', ESCAPE_CHARACTER, 'x', '2', 'f', 't', 0 }; #endif system_character_t expected_path5[ 6 ] = { 't', 'e', ESCAPE_CHARACTER, ESCAPE_CHARACTER, 't', 0 }; #endif system_character_t file_entry_path1[ 5 ] = { 't', 'e', 's', 't', 0 }; system_character_t file_entry_path2[ 5 ] = { 't', 'e', 0x03, 't', 0 }; system_character_t expected_path1[ 5 ] = { 't', 'e', 's', 't', 0 }; libcerror_error_t *error = NULL; system_character_t *path = NULL; size_t path_size = 0; int result = 0; /* Test regular cases */ result = mount_path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path1, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "path", path ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "path_size", path_size, (size_t) 41 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( path, expected_path1, 5 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( path ); path = NULL; result = mount_path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path2, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "path", path ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "path_size", path_size, (size_t) 41 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( path, expected_path2, 8 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( path ); path = NULL; #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = mount_path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path3, 4, &error ); #else result = mount_path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path3, 6, &error ); #endif FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "path", path ); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) FSNTFS_TEST_ASSERT_EQUAL_SIZE( "path_size", path_size, (size_t) 41 ); #else FSNTFS_TEST_ASSERT_EQUAL_SIZE( "path_size", path_size, (size_t) 61 ); #endif FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( path, expected_path3, 14 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( path ); path = NULL; result = mount_path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path4, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "path", path ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "path_size", path_size, (size_t) 41 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( path, expected_path4, 8 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( path ); path = NULL; result = mount_path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path5, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "path", path ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "path_size", path_size, (size_t) 41 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( path, expected_path5, 6 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( path ); path = NULL; /* Test error cases */ result = mount_path_string_copy_from_file_entry_path( NULL, &path_size, file_entry_path1, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = mount_path_string_copy_from_file_entry_path( &path, NULL, file_entry_path1, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = mount_path_string_copy_from_file_entry_path( &path, &path_size, NULL, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = mount_path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = mount_path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path1, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( path != NULL ) { memory_free( path ); } if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the mount_path_string_copy_to_file_entry_path function * Returns 1 if successful or 0 if not */ int fsntfs_test_tools_mount_path_string_copy_to_file_entry_path( void ) { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) system_character_t expected_file_entry_path3[ 6 ] = { LIBFSNTFS_SEPARATOR, 't', 'e', 0x2028, 't', 0 }; system_character_t expected_file_entry_path4[ 6 ] = { LIBFSNTFS_SEPARATOR, 't', 'e', ESCAPE_CHARACTER, 't', 0 }; system_character_t path2[ 9 ] = { LIBCPATH_SEPARATOR, 't', 'e', ESCAPE_CHARACTER, 'x', '0', '3', 't', 0 }; system_character_t path3[ 15 ] = { LIBCPATH_SEPARATOR, 't', 'e', ESCAPE_CHARACTER, 'U', '0', '0', '0', '0', '2', '0', '2', '8', 't', 0 }; system_character_t path4[ 7 ] = { LIBCPATH_SEPARATOR, 't', 'e', ESCAPE_CHARACTER, ESCAPE_CHARACTER, 't', 0 }; #else system_character_t expected_file_entry_path3[ 8 ] = { LIBFSNTFS_SEPARATOR, 't', 'e', 0xe2, 0x80, 0xa8, 't', 0 }; system_character_t expected_file_entry_path4[ 6 ] = { LIBFSNTFS_SEPARATOR, 't', 'e', ESCAPE_CHARACTER, 't', 0 }; system_character_t path2[ 9 ] = { LIBCPATH_SEPARATOR, 't', 'e', ESCAPE_CHARACTER, 'x', '0', '3', 't', 0 }; system_character_t path3[ 15 ] = { LIBCPATH_SEPARATOR, 't', 'e', ESCAPE_CHARACTER, 'U', '0', '0', '0', '0', '2', '0', '2', '8', 't', 0 }; system_character_t path4[ 7 ] = { LIBCPATH_SEPARATOR, 't', 'e', ESCAPE_CHARACTER, ESCAPE_CHARACTER, 't', 0 }; #endif system_character_t expected_file_entry_path1[ 6 ] = { LIBFSNTFS_SEPARATOR, 't', 'e', 's', 't', 0 }; system_character_t expected_file_entry_path2[ 6 ] = { LIBFSNTFS_SEPARATOR, 't', 'e', 0x03, 't', 0 }; system_character_t expected_file_entry_path5[ 6 ] = { LIBFSNTFS_SEPARATOR, 't', 'e', LIBFSNTFS_SEPARATOR, 't', 0 }; system_character_t path1[ 6 ] = { LIBCPATH_SEPARATOR, 't', 'e', 's', 't', 0 }; system_character_t path5[ 6 ] = { LIBCPATH_SEPARATOR, 't', 'e', LIBCPATH_SEPARATOR, 't', 0 }; libcerror_error_t *error = NULL; system_character_t *file_entry_path = NULL; size_t file_entry_path_size = 0; int result = 0; /* Test regular cases */ result = mount_path_string_copy_to_file_entry_path( path1, 5, &file_entry_path, &file_entry_path_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_entry_path", file_entry_path ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "file_entry_path_size", file_entry_path_size, (size_t) 6 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( file_entry_path, expected_file_entry_path1, 6 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( file_entry_path ); file_entry_path = NULL; result = mount_path_string_copy_to_file_entry_path( path2, 8, &file_entry_path, &file_entry_path_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_entry_path", file_entry_path ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "file_entry_path_size", file_entry_path_size, (size_t) 9 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( file_entry_path, expected_file_entry_path2, 6 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( file_entry_path ); file_entry_path = NULL; result = mount_path_string_copy_to_file_entry_path( path3, 14, &file_entry_path, &file_entry_path_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_entry_path", file_entry_path ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "file_entry_path_size", file_entry_path_size, (size_t) 15 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = memory_compare( file_entry_path, expected_file_entry_path3, 6 ); #else result = memory_compare( file_entry_path, expected_file_entry_path3, 8 ); #endif FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( file_entry_path ); file_entry_path = NULL; result = mount_path_string_copy_to_file_entry_path( path4, 6, &file_entry_path, &file_entry_path_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_entry_path", file_entry_path ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "file_entry_path_size", file_entry_path_size, (size_t) 7 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( file_entry_path, expected_file_entry_path4, 6 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( file_entry_path ); file_entry_path = NULL; result = mount_path_string_copy_to_file_entry_path( path5, 6, &file_entry_path, &file_entry_path_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_entry_path", file_entry_path ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "file_entry_path_size", file_entry_path_size, (size_t) 7 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( file_entry_path, expected_file_entry_path5, 6 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( file_entry_path ); file_entry_path = NULL; /* Test error cases */ result = mount_path_string_copy_to_file_entry_path( NULL, 5, &file_entry_path, &file_entry_path_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = mount_path_string_copy_to_file_entry_path( path1, 0, &file_entry_path, &file_entry_path_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = mount_path_string_copy_to_file_entry_path( path1, (size_t) SSIZE_MAX + 1, &file_entry_path, &file_entry_path_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = mount_path_string_copy_to_file_entry_path( path1, 5, NULL, &file_entry_path_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = mount_path_string_copy_to_file_entry_path( path1, 5, &file_entry_path, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( file_entry_path != NULL ) { memory_free( file_entry_path ); } if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) FSNTFS_TEST_RUN( "mount_path_string_copy_hexadecimal_to_integer_32_bit", fsntfs_test_tools_mount_path_string_copy_hexadecimal_to_integer_32_bit ) FSNTFS_TEST_RUN( "mount_path_string_copy_from_file_entry_path", fsntfs_test_tools_mount_path_string_copy_from_file_entry_path ) FSNTFS_TEST_RUN( "mount_path_string_copy_to_file_entry_path", fsntfs_test_tools_mount_path_string_copy_to_file_entry_path ) return( EXIT_SUCCESS ); on_error: return( EXIT_FAILURE ); } ================================================ FILE: tests/fsntfs_test_tools_output.c ================================================ /* * Tools output functions test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_IO_H ) || defined( WINAPI ) #include #endif #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_unused.h" #include "../fsntfstools/fsntfstools_output.h" /* Tests the fsntfstools_output_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_tools_output_initialize( void ) { libcerror_error_t *error = NULL; int result = 0; result = fsntfstools_output_initialize( _IONBF, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) FSNTFS_TEST_RUN( "fsntfstools_output_initialize", fsntfs_test_tools_output_initialize ) /* TODO add tests for fsntfstools_output_copyright_fprint */ /* TODO add tests for fsntfstools_output_version_fprint */ /* TODO add tests for fsntfstools_output_version_detailed_fprint */ return( EXIT_SUCCESS ); on_error: return( EXIT_FAILURE ); } ================================================ FILE: tests/fsntfs_test_tools_path_string.c ================================================ /* * Tools path_string functions test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_unused.h" #include "../fsntfstools/path_string.h" /* Tests the path_string_copy_hexadecimal_to_integer_32_bit function * Returns 1 if successful or 0 if not */ int fsntfs_test_tools_path_string_copy_hexadecimal_to_integer_32_bit( void ) { system_character_t error_string[ 5 ] = { '2', '0', 'Z', '8', 0 }; system_character_t string[ 5 ] = { '2', '0', '2', '8', 0 }; libcerror_error_t *error = NULL; uint32_t value_32bit = 0; int result = 0; /* Test regular cases */ result = path_string_copy_hexadecimal_to_integer_32_bit( string, 4, &value_32bit, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT32( "value_32bit", value_32bit, (uint32_t) 0x2028 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = path_string_copy_hexadecimal_to_integer_32_bit( NULL, 4, &value_32bit, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = path_string_copy_hexadecimal_to_integer_32_bit( string, 0, &value_32bit, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = path_string_copy_hexadecimal_to_integer_32_bit( string, (size_t) SSIZE_MAX + 1, &value_32bit, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = path_string_copy_hexadecimal_to_integer_32_bit( string, 4, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = path_string_copy_hexadecimal_to_integer_32_bit( error_string, 4, &value_32bit, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the path_string_copy_from_file_entry_path function * Returns 1 if successful or 0 if not */ int fsntfs_test_tools_path_string_copy_from_file_entry_path( void ) { #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) system_character_t file_entry_path3[ 5 ] = { 't', 'e', 0x2028, 't', 0 }; #else system_character_t file_entry_path3[ 7 ] = { 't', 'e', 0xe2, 0x80, 0xa8, 't', 0 }; #endif system_character_t file_entry_path1[ 5 ] = { 't', 'e', 's', 't', 0 }; system_character_t file_entry_path2[ 5 ] = { 't', 'e', 0x03, 't', 0 }; system_character_t file_entry_path4[ 5 ] = { 't', 'e', '\\', 't', 0 }; system_character_t expected_path1[ 5 ] = { 't', 'e', 's', 't', 0 }; system_character_t expected_path2[ 8 ] = { 't', 'e', '\\', 'x', '0', '3', 't', 0 }; system_character_t expected_path3[ 14 ] = { 't', 'e', '\\', 'U', '0', '0', '0', '0', '2', '0', '2', '8', 't', 0 }; system_character_t expected_path4[ 6 ] = { 't', 'e', '\\', '\\', 't', 0 }; libcerror_error_t *error = NULL; system_character_t *path = NULL; size_t path_size = 0; int result = 0; /* Test regular cases */ result = path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path1, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "path", path ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "path_size", path_size, (size_t) 41 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( path, expected_path1, 5 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( path ); path = NULL; result = path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path2, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "path", path ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "path_size", path_size, (size_t) 41 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( path, expected_path2, 8 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( path ); path = NULL; #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path3, 4, &error ); #else result = path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path3, 6, &error ); #endif FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "path", path ); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) FSNTFS_TEST_ASSERT_EQUAL_SIZE( "path_size", path_size, (size_t) 41 ); #else FSNTFS_TEST_ASSERT_EQUAL_SIZE( "path_size", path_size, (size_t) 61 ); #endif FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( path, expected_path3, 14 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( path ); path = NULL; result = path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path4, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "path", path ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "path_size", path_size, (size_t) 41 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( path, expected_path4, 6 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( path ); path = NULL; /* Test error cases */ result = path_string_copy_from_file_entry_path( NULL, &path_size, file_entry_path1, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = path_string_copy_from_file_entry_path( &path, NULL, file_entry_path1, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = path_string_copy_from_file_entry_path( &path, &path_size, NULL, 4, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = path_string_copy_from_file_entry_path( &path, &path_size, file_entry_path1, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( path != NULL ) { memory_free( path ); } if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the path_string_copy_to_file_entry_path function * Returns 1 if successful or 0 if not */ int fsntfs_test_tools_path_string_copy_to_file_entry_path( void ) { system_character_t expected_file_entry_path1[ 6 ] = { LIBFSNTFS_SEPARATOR, 't', 'e', 's', 't', 0 }; system_character_t path1[ 7 ] = { '\\', '\\', 't', 'e', 's', 't', 0 }; libcerror_error_t *error = NULL; system_character_t *file_entry_path = NULL; size_t file_entry_path_size = 0; int result = 0; /* Test regular cases */ result = path_string_copy_to_file_entry_path( path1, 6, (system_character_t) '\\', &file_entry_path, &file_entry_path_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_entry_path", file_entry_path ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "file_entry_path_size", file_entry_path_size, (size_t) 7 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = memory_compare( file_entry_path, expected_file_entry_path1, 6 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); memory_free( file_entry_path ); file_entry_path = NULL; /* TODO improve test coverage */ /* Test error cases */ result = path_string_copy_to_file_entry_path( NULL, 4, (system_character_t) '\\', &file_entry_path, &file_entry_path_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = path_string_copy_to_file_entry_path( path1, 0, (system_character_t) '\\', &file_entry_path, &file_entry_path_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = path_string_copy_to_file_entry_path( path1, (size_t) SSIZE_MAX + 1, (system_character_t) '\\', &file_entry_path, &file_entry_path_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = path_string_copy_to_file_entry_path( path1, 4, (system_character_t) '\\', NULL, &file_entry_path_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = path_string_copy_to_file_entry_path( path1, 4, (system_character_t) '\\', &file_entry_path, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( file_entry_path != NULL ) { memory_free( file_entry_path ); } if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) FSNTFS_TEST_RUN( "path_string_copy_hexadecimal_to_integer_32_bit", fsntfs_test_tools_path_string_copy_hexadecimal_to_integer_32_bit ) FSNTFS_TEST_RUN( "path_string_copy_from_file_entry_path", fsntfs_test_tools_path_string_copy_from_file_entry_path ) FSNTFS_TEST_RUN( "path_string_copy_to_file_entry_path", fsntfs_test_tools_path_string_copy_to_file_entry_path ) return( EXIT_SUCCESS ); on_error: return( EXIT_FAILURE ); } ================================================ FILE: tests/fsntfs_test_tools_signal.c ================================================ /* * Tools signal functions test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_unused.h" #include "../fsntfstools/fsntfstools_signal.h" void fsntfs_test_tools_signal_handler_function( fsntfstools_signal_t signal FSNTFS_TEST_ATTRIBUTE_UNUSED ) { FSNTFS_TEST_UNREFERENCED_PARAMETER( signal ) } #if defined( WINAPI ) /* Tests the fsntfstools_signal_handler function * Returns 1 if successful or 0 if not */ int fsntfs_test_tools_signal_handler( void ) { BOOL result = 0; /* Test regular cases */ result = fsntfstools_signal_handler( CTRL_C_EVENT ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, (int) TRUE ); result = fsntfstools_signal_handler( CTRL_LOGOFF_EVENT ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, (int) FALSE ); return( 1 ); on_error: return( 0 ); } #if defined( _MSC_VER ) /* TODO add tests for fsntfstools_signal_initialize_memory_debug */ #endif /* defined( _MSC_VER ) */ #endif /* defined( WINAPI ) */ /* Tests the fsntfstools_signal_attach function * Returns 1 if successful or 0 if not */ int fsntfs_test_tools_signal_attach( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = fsntfstools_signal_attach( fsntfs_test_tools_signal_handler_function, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = fsntfstools_signal_attach( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the fsntfstools_signal_detach function * Returns 1 if successful or 0 if not */ int fsntfs_test_tools_signal_detach( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = fsntfstools_signal_detach( &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( WINAPI ) FSNTFS_TEST_RUN( "fsntfstools_signal_handler", fsntfs_test_tools_signal_handler ) #if defined( _MSC_VER ) /* TODO add tests for fsntfstools_signal_initialize_memory_debug */ #endif /* defined( _MSC_VER ) */ #endif /* defined( WINAPI ) */ FSNTFS_TEST_RUN( "fsntfstools_signal_attach", fsntfs_test_tools_signal_attach ) FSNTFS_TEST_RUN( "fsntfstools_signal_detach", fsntfs_test_tools_signal_detach ) return( EXIT_SUCCESS ); on_error: return( EXIT_FAILURE ); } ================================================ FILE: tests/fsntfs_test_txf_data_values.c ================================================ /* * Library txf_data_values type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" #include "../libfsntfs/libfsntfs_txf_data_values.h" uint8_t fsntfs_test_txf_data_values_data1[ 104 ] = { 0x00, 0x01, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x09, 0x18, 0x00, 0x00, 0x00, 0x09, 0x00, 0x38, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x54, 0x00, 0x58, 0x00, 0x46, 0x00, 0x5f, 0x00, 0x44, 0x00, 0x41, 0x00, 0x54, 0x00, 0x41, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_txf_data_values_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_txf_data_values_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_txf_data_values_t *txf_data_values = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_txf_data_values_initialize( &txf_data_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "txf_data_values", txf_data_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_txf_data_values_free( &txf_data_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "txf_data_values", txf_data_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_txf_data_values_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); txf_data_values = (libfsntfs_txf_data_values_t *) 0x12345678UL; result = libfsntfs_txf_data_values_initialize( &txf_data_values, &error ); txf_data_values = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_txf_data_values_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_txf_data_values_initialize( &txf_data_values, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( txf_data_values != NULL ) { libfsntfs_txf_data_values_free( &txf_data_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "txf_data_values", txf_data_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_txf_data_values_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_txf_data_values_initialize( &txf_data_values, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( txf_data_values != NULL ) { libfsntfs_txf_data_values_free( &txf_data_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "txf_data_values", txf_data_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( txf_data_values != NULL ) { libfsntfs_txf_data_values_free( &txf_data_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_txf_data_values_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_txf_data_values_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_txf_data_values_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_txf_data_values_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_txf_data_values_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_txf_data_values_t *txf_data_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_txf_data_values_initialize( &txf_data_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "txf_data_values", txf_data_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_txf_data_values_read_data( txf_data_values, &( fsntfs_test_txf_data_values_data1[ 42 ] ), 56, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_txf_data_values_read_data( NULL, &( fsntfs_test_txf_data_values_data1[ 42 ] ), 56, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_txf_data_values_read_data( txf_data_values, NULL, 56, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_txf_data_values_read_data( txf_data_values, &( fsntfs_test_txf_data_values_data1[ 42 ] ), (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_txf_data_values_read_data( txf_data_values, &( fsntfs_test_txf_data_values_data1[ 42 ] ), 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_txf_data_values_free( &txf_data_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "txf_data_values", txf_data_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( txf_data_values != NULL ) { libfsntfs_txf_data_values_free( &txf_data_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_txf_data_values_read_from_mft_attribute function * Returns 1 if successful or 0 if not */ int fsntfs_test_txf_data_values_read_from_mft_attribute( void ) { libcerror_error_t *error = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; libfsntfs_txf_data_values_t *txf_data_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_txf_data_values_data1, 104, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_txf_data_values_initialize( &txf_data_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "txf_data_values", txf_data_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_txf_data_values_read_from_mft_attribute( txf_data_values, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_txf_data_values_read_from_mft_attribute( NULL, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_txf_data_values_read_from_mft_attribute( txf_data_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_txf_data_values_free( &txf_data_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "txf_data_values", txf_data_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( txf_data_values != NULL ) { libfsntfs_txf_data_values_free( &txf_data_values, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_txf_data_values_initialize", fsntfs_test_txf_data_values_initialize ); FSNTFS_TEST_RUN( "libfsntfs_txf_data_values_free", fsntfs_test_txf_data_values_free ); FSNTFS_TEST_RUN( "libfsntfs_txf_data_values_read_data", fsntfs_test_txf_data_values_read_data ); FSNTFS_TEST_RUN( "libfsntfs_txf_data_values_read_from_mft_attribute", fsntfs_test_txf_data_values_read_from_mft_attribute ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_unused.h ================================================ /* * Definitions to silence compiler warnings about unused function attributes/parameters. * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if !defined( _FSNTFS_TEST_UNUSED_H ) #define _FSNTFS_TEST_UNUSED_H #include #if !defined( FSNTFS_TEST_ATTRIBUTE_UNUSED ) #if defined( __GNUC__ ) && __GNUC__ >= 3 #define FSNTFS_TEST_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) #else #define FSNTFS_TEST_ATTRIBUTE_UNUSED #endif /* defined( __GNUC__ ) && __GNUC__ >= 3 */ #endif /* !defined( FSNTFS_TEST_ATTRIBUTE_UNUSED ) */ #if defined( _MSC_VER ) #define FSNTFS_TEST_UNREFERENCED_PARAMETER( parameter ) \ UNREFERENCED_PARAMETER( parameter ); #else #define FSNTFS_TEST_UNREFERENCED_PARAMETER( parameter ) \ /* parameter */ #endif /* defined( _MSC_VER ) */ #endif /* !defined( _FSNTFS_TEST_UNUSED_H ) */ ================================================ FILE: tests/fsntfs_test_usn_change_journal.c ================================================ /* * Library usn_change_journal type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_directory_entry.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_usn_change_journal.h" /* TODO implement */ #ifdef TODO #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_usn_change_journal_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_usn_change_journal_initialize( void ) { libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_attribute_t *data_attribute = NULL; libfsntfs_directory_entry_t *directory_entry = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_usn_change_journal_t *usn_change_journal = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; /* Test regular cases */ result = libfsntfs_usn_change_journal_initialize( &usn_change_journal, io_handle, file_io_handle, directory_entry, data_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "usn_change_journal", usn_change_journal ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_usn_change_journal_free( &usn_change_journal, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "usn_change_journal", usn_change_journal ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_usn_change_journal_initialize( NULL, io_handle, file_io_handle, directory_entry, data_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); usn_change_journal = (libfsntfs_usn_change_journal_t *) 0x12345678UL; result = libfsntfs_usn_change_journal_initialize( &usn_change_journal, io_handle, file_io_handle, directory_entry, data_attribute, &error ); usn_change_journal = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_usn_change_journal_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_usn_change_journal_initialize( &usn_change_journal, io_handle, file_io_handle, directory_entry, data_attribute, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( usn_change_journal != NULL ) { libfsntfs_usn_change_journal_free( &usn_change_journal, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "usn_change_journal", usn_change_journal ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_usn_change_journal_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_usn_change_journal_initialize( &usn_change_journal, io_handle, file_io_handle, directory_entry, data_attribute, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( usn_change_journal != NULL ) { libfsntfs_usn_change_journal_free( &usn_change_journal, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "usn_change_journal", usn_change_journal ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &data_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "data_attribute", data_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( usn_change_journal != NULL ) { libfsntfs_usn_change_journal_free( &usn_change_journal, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ #endif /* TODO */ /* Tests the libfsntfs_usn_change_journal_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_usn_change_journal_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_usn_change_journal_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* TODO: add tests for libfsntfs_usn_change_journal_initialize */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_RUN( "libfsntfs_usn_change_journal_free", fsntfs_test_usn_change_journal_free ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* TODO: add tests for libfsntfs_usn_change_journal_get_offset */ /* TODO: add tests for libfsntfs_usn_change_journal_read_usn_record */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); on_error: return( EXIT_FAILURE ); } ================================================ FILE: tests/fsntfs_test_volume.c ================================================ /* * Library volume type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_functions.h" #include "fsntfs_test_getopt.h" #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "../libfsntfs/libfsntfs_directory_entry.h" #include "../libfsntfs/libfsntfs_mft_entry.h" #include "../libfsntfs/libfsntfs_volume.h" #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) && SIZEOF_WCHAR_T != 2 && SIZEOF_WCHAR_T != 4 #error Unsupported size of wchar_t #endif /* Define to make fsntfs_test_volume generate verbose output #define FSNTFS_TEST_VOLUME_VERBOSE */ #if !defined( LIBFSNTFS_HAVE_BFIO ) LIBFSNTFS_EXTERN \ int libfsntfs_check_volume_signature_file_io_handle( libbfio_handle_t *file_io_handle, libcerror_error_t **error ); LIBFSNTFS_EXTERN \ int libfsntfs_volume_open_file_io_handle( libfsntfs_volume_t *volume, libbfio_handle_t *file_io_handle, int access_flags, libfsntfs_error_t **error ); #endif /* !defined( LIBFSNTFS_HAVE_BFIO ) */ /* Creates and opens a source volume * Returns 1 if successful or -1 on error */ int fsntfs_test_volume_open_source( libfsntfs_volume_t **volume, libbfio_handle_t *file_io_handle, libcerror_error_t **error ) { static char *function = "fsntfs_test_volume_open_source"; int result = 0; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } if( file_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file IO handle.", function ); return( -1 ); } if( libfsntfs_volume_initialize( volume, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to initialize volume.", function ); goto on_error; } result = libfsntfs_volume_open_file_io_handle( *volume, file_io_handle, LIBFSNTFS_OPEN_READ, error ); if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open volume.", function ); goto on_error; } return( 1 ); on_error: if( *volume != NULL ) { libfsntfs_volume_free( volume, NULL ); } return( -1 ); } /* Closes and frees a source volume * Returns 1 if successful or -1 on error */ int fsntfs_test_volume_close_source( libfsntfs_volume_t **volume, libcerror_error_t **error ) { static char *function = "fsntfs_test_volume_close_source"; int result = 0; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } if( libfsntfs_volume_close( *volume, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close volume.", function ); result = -1; } if( libfsntfs_volume_free( volume, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free volume.", function ); result = -1; } return( result ); } /* Tests the libfsntfs_volume_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_volume_t *volume = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 2; int number_of_memset_fail_tests = 1; int test_number = 0; #endif #if defined( HAVE_FSNTFS_TEST_RWLOCK ) number_of_malloc_fail_tests += 1; #endif /* Test regular cases */ result = libfsntfs_volume_initialize( &volume, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "volume", volume ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_volume_free( &volume, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume", volume ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); volume = (libfsntfs_volume_t *) 0x12345678UL; result = libfsntfs_volume_initialize( &volume, &error ); volume = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* TODO determine why HAVE_PROFILER causes tests to be fail */ #if defined( HAVE_FSNTFS_TEST_MEMORY ) && !defined( HAVE_PROFILER ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_volume_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_volume_initialize( &volume, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( volume != NULL ) { libfsntfs_volume_free( &volume, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume", volume ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_volume_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_volume_initialize( &volume, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( volume != NULL ) { libfsntfs_volume_free( &volume, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume", volume ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( volume != NULL ) { libfsntfs_volume_free( &volume, NULL ); } return( 0 ); } /* Tests the libfsntfs_volume_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_volume_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_open function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_open( const system_character_t *source ) { char narrow_source[ 256 ]; libcerror_error_t *error = NULL; libfsntfs_volume_t *volume = NULL; int result = 0; /* Initialize test */ result = fsntfs_test_get_narrow_source( source, narrow_source, 256, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_volume_initialize( &volume, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "volume", volume ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test open */ result = libfsntfs_volume_open( volume, narrow_source, LIBFSNTFS_OPEN_READ, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_open( NULL, narrow_source, LIBFSNTFS_OPEN_READ, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_open( volume, NULL, LIBFSNTFS_OPEN_READ, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_open( volume, narrow_source, -1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test open when already opened */ result = libfsntfs_volume_open( volume, narrow_source, LIBFSNTFS_OPEN_READ, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_volume_free( &volume, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume", volume ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( volume != NULL ) { libfsntfs_volume_free( &volume, NULL ); } return( 0 ); } #if defined( HAVE_WIDE_CHARACTER_TYPE ) /* Tests the libfsntfs_volume_open_wide function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_open_wide( const system_character_t *source ) { wchar_t wide_source[ 256 ]; libcerror_error_t *error = NULL; libfsntfs_volume_t *volume = NULL; int result = 0; /* Initialize test */ result = fsntfs_test_get_wide_source( source, wide_source, 256, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_volume_initialize( &volume, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "volume", volume ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test open */ result = libfsntfs_volume_open_wide( volume, wide_source, LIBFSNTFS_OPEN_READ, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_open_wide( NULL, wide_source, LIBFSNTFS_OPEN_READ, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_open_wide( volume, NULL, LIBFSNTFS_OPEN_READ, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_open_wide( volume, wide_source, -1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test open when already opened */ result = libfsntfs_volume_open_wide( volume, wide_source, LIBFSNTFS_OPEN_READ, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_volume_free( &volume, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume", volume ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( volume != NULL ) { libfsntfs_volume_free( &volume, NULL ); } return( 0 ); } #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */ /* Tests the libfsntfs_volume_open_file_io_handle function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_open_file_io_handle( const system_character_t *source ) { libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_volume_t *volume = NULL; size_t string_length = 0; int result = 0; /* Initialize test */ result = libbfio_file_initialize( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); string_length = system_string_length( source ); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libbfio_file_set_name_wide( file_io_handle, source, string_length, &error ); #else result = libbfio_file_set_name( file_io_handle, source, string_length, &error ); #endif FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_volume_initialize( &volume, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "volume", volume ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test open */ result = libfsntfs_volume_open_file_io_handle( volume, file_io_handle, LIBFSNTFS_OPEN_READ, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_open_file_io_handle( NULL, file_io_handle, LIBFSNTFS_OPEN_READ, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_open_file_io_handle( volume, NULL, LIBFSNTFS_OPEN_READ, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_open_file_io_handle( volume, file_io_handle, -1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test open when already opened */ result = libfsntfs_volume_open_file_io_handle( volume, file_io_handle, LIBFSNTFS_OPEN_READ, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_volume_free( &volume, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume", volume ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libbfio_handle_free( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( volume != NULL ) { libfsntfs_volume_free( &volume, NULL ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_volume_close function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_close( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_volume_close( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_open and libfsntfs_volume_close functions * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_open_close( const system_character_t *source ) { libcerror_error_t *error = NULL; libfsntfs_volume_t *volume = NULL; int result = 0; /* Initialize test */ result = libfsntfs_volume_initialize( &volume, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "volume", volume ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test open and close */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_volume_open_wide( volume, source, LIBFSNTFS_OPEN_READ, &error ); #else result = libfsntfs_volume_open( volume, source, LIBFSNTFS_OPEN_READ, &error ); #endif FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_volume_close( volume, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test open and close a second time to validate clean up on close */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfsntfs_volume_open_wide( volume, source, LIBFSNTFS_OPEN_READ, &error ); #else result = libfsntfs_volume_open( volume, source, LIBFSNTFS_OPEN_READ, &error ); #endif FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_volume_close( volume, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfsntfs_volume_free( &volume, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume", volume ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( volume != NULL ) { libfsntfs_volume_free( &volume, NULL ); } return( 0 ); } /* Tests the libfsntfs_volume_signal_abort function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_signal_abort( libfsntfs_volume_t *volume ) { libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_volume_signal_abort( volume, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_signal_abort( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_get_bytes_per_sector function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_get_bytes_per_sector( libfsntfs_volume_t *volume ) { libcerror_error_t *error = NULL; uint16_t bytes_per_sector = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_get_bytes_per_sector( volume, &bytes_per_sector, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_get_bytes_per_sector( NULL, &bytes_per_sector, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_bytes_per_sector( volume, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_get_cluster_block_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_get_cluster_block_size( libfsntfs_volume_t *volume ) { libcerror_error_t *error = NULL; size32_t cluster_block_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_get_cluster_block_size( volume, &cluster_block_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_get_cluster_block_size( NULL, &cluster_block_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_cluster_block_size( volume, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_get_mft_entry_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_get_mft_entry_size( libfsntfs_volume_t *volume ) { libcerror_error_t *error = NULL; size32_t mft_entry_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_get_mft_entry_size( volume, &mft_entry_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_get_mft_entry_size( NULL, &mft_entry_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_mft_entry_size( volume, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_get_index_entry_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_get_index_entry_size( libfsntfs_volume_t *volume ) { libcerror_error_t *error = NULL; size32_t index_entry_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_get_index_entry_size( volume, &index_entry_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_get_index_entry_size( NULL, &index_entry_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_index_entry_size( volume, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_get_utf8_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_get_utf8_name_size( libfsntfs_volume_t *volume ) { libcerror_error_t *error = NULL; size_t utf8_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_get_utf8_name_size( volume, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_get_utf8_name_size( NULL, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_utf8_name_size( volume, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_get_utf8_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_get_utf8_name( libfsntfs_volume_t *volume ) { uint8_t utf8_name[ 512 ]; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_volume_get_utf8_name( volume, utf8_name, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_get_utf8_name( NULL, utf8_name, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_utf8_name( volume, NULL, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_utf8_name( volume, utf8_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_utf8_name( volume, utf8_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_get_utf16_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_get_utf16_name_size( libfsntfs_volume_t *volume ) { libcerror_error_t *error = NULL; size_t utf16_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_get_utf16_name_size( volume, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_get_utf16_name_size( NULL, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_utf16_name_size( volume, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_get_utf16_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_get_utf16_name( libfsntfs_volume_t *volume ) { uint16_t utf16_name[ 512 ]; libcerror_error_t *error = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_volume_get_utf16_name( volume, utf16_name, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_get_utf16_name( NULL, utf16_name, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_utf16_name( volume, NULL, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_utf16_name( volume, utf16_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_utf16_name( volume, utf16_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_get_serial_number function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_get_serial_number( libfsntfs_volume_t *volume ) { libcerror_error_t *error = NULL; uint64_t serial_number = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_get_serial_number( volume, &serial_number, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_get_serial_number( NULL, &serial_number, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_serial_number( volume, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_get_number_of_file_entries function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_get_number_of_file_entries( libfsntfs_volume_t *volume ) { libcerror_error_t *error = NULL; uint64_t number_of_file_entries = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_get_number_of_file_entries( volume, &number_of_file_entries, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_get_number_of_file_entries( NULL, &number_of_file_entries, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_number_of_file_entries( volume, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_get_file_entry_by_index function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_get_file_entry_by_index( libfsntfs_volume_t *volume ) { libcerror_error_t *error = NULL; libfsntfs_file_entry_t *file_entry = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_volume_get_file_entry_by_index( volume, 0, &file_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_entry_free( &file_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_get_file_entry_by_index( NULL, 0, &file_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_file_entry_by_index( volume, 0xffffffffffffffffUL, &file_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_file_entry_by_index( volume, 0, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); file_entry = (libfsntfs_file_entry_t *) 0x12345678UL; result = libfsntfs_volume_get_file_entry_by_index( volume, 0, &file_entry, &error ); file_entry = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_entry != NULL ) { libfsntfs_file_entry_free( &file_entry, NULL ); } return( 0 ); } #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf8_path function * Returns 1 if successful or 0 if not */ int fsntfs_test_internal_volume_get_mft_and_directory_entry_by_utf8_path( libfsntfs_volume_t *volume ) { uint8_t utf8_path[ 6 ] = { '\\', '$', 'M', 'F', 'T', 0 }; libcerror_error_t *error = NULL; libfsntfs_directory_entry_t *directory_entry = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf8_path( (libfsntfs_internal_volume_t *) volume, utf8_path, 5, &mft_entry, &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "directory_entry", directory_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_directory_entry_free( &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "directory_entry", directory_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf8_path( NULL, utf8_path, 5, &mft_entry, &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf8_path( (libfsntfs_internal_volume_t *) volume, NULL, 5, &mft_entry, &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf8_path( (libfsntfs_internal_volume_t *) volume, utf8_path, (size_t) SSIZE_MAX + 1, &mft_entry, &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf8_path( (libfsntfs_internal_volume_t *) volume, utf8_path, 5, NULL, &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf8_path( (libfsntfs_internal_volume_t *) volume, utf8_path, 5, &mft_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); directory_entry = (libfsntfs_directory_entry_t *) 0x12345678UL; result = libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf8_path( (libfsntfs_internal_volume_t *) volume, utf8_path, 5, &mft_entry, NULL, &error ); directory_entry = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( directory_entry != NULL ) { libfsntfs_directory_entry_free( &directory_entry, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* Tests the libfsntfs_volume_get_file_entry_by_utf8_path function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_get_file_entry_by_utf8_path( libfsntfs_volume_t *volume ) { uint8_t utf8_path[ 6 ] = { '\\', '$', 'M', 'F', 'T', 0 }; libcerror_error_t *error = NULL; libfsntfs_file_entry_t *file_entry = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_volume_get_file_entry_by_utf8_path( volume, utf8_path, 5, &file_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_entry_free( &file_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_get_file_entry_by_utf8_path( NULL, utf8_path, 5, &file_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_file_entry_by_utf8_path( volume, NULL, 5, &file_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_file_entry_by_utf8_path( volume, utf8_path, 5, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); file_entry = (libfsntfs_file_entry_t *) 0x12345678UL; result = libfsntfs_volume_get_file_entry_by_utf8_path( volume, utf8_path, 5, &file_entry, &error ); file_entry = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_entry != NULL ) { libfsntfs_file_entry_free( &file_entry, NULL ); } return( 0 ); } #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf16_path function * Returns 1 if successful or 0 if not */ int fsntfs_test_internal_volume_get_mft_and_directory_entry_by_utf16_path( libfsntfs_volume_t *volume ) { uint16_t utf16_path[ 6 ] = { '\\', '$', 'M', 'F', 'T', 0 }; libcerror_error_t *error = NULL; libfsntfs_directory_entry_t *directory_entry = NULL; libfsntfs_mft_entry_t *mft_entry = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf16_path( (libfsntfs_internal_volume_t *) volume, utf16_path, 5, &mft_entry, &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_entry", mft_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "directory_entry", directory_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_directory_entry_free( &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "directory_entry", directory_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf16_path( NULL, utf16_path, 5, &mft_entry, &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf16_path( (libfsntfs_internal_volume_t *) volume, NULL, 5, &mft_entry, &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf16_path( (libfsntfs_internal_volume_t *) volume, utf16_path, (size_t) SSIZE_MAX + 1, &mft_entry, &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf16_path( (libfsntfs_internal_volume_t *) volume, utf16_path, 5, NULL, &directory_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf16_path( (libfsntfs_internal_volume_t *) volume, utf16_path, 5, &mft_entry, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); directory_entry = (libfsntfs_directory_entry_t *) 0x12345678UL; result = libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf16_path( (libfsntfs_internal_volume_t *) volume, utf16_path, 5, &mft_entry, NULL, &error ); directory_entry = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( directory_entry != NULL ) { libfsntfs_directory_entry_free( &directory_entry, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* Tests the libfsntfs_volume_get_file_entry_by_utf16_path function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_get_file_entry_by_utf16_path( libfsntfs_volume_t *volume ) { uint16_t utf16_path[ 6 ] = { '\\', '$', 'M', 'F', 'T', 0 }; libcerror_error_t *error = NULL; libfsntfs_file_entry_t *file_entry = NULL; int result = 0; /* Test regular cases */ result = libfsntfs_volume_get_file_entry_by_utf16_path( volume, utf16_path, 5, &file_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_entry_free( &file_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_get_file_entry_by_utf16_path( NULL, utf16_path, 5, &file_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_file_entry_by_utf16_path( volume, NULL, 5, &file_entry, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_file_entry_by_utf16_path( volume, utf16_path, 5, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_entry", file_entry ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); file_entry = (libfsntfs_file_entry_t *) 0x12345678UL; result = libfsntfs_volume_get_file_entry_by_utf16_path( volume, utf16_path, 5, &file_entry, &error ); file_entry = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_entry != NULL ) { libfsntfs_file_entry_free( &file_entry, NULL ); } return( 0 ); } /* Tests the libfsntfs_volume_get_root_directory function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_get_root_directory( libfsntfs_volume_t *volume ) { libcerror_error_t *error = NULL; libfsntfs_file_entry_t *root_directory = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_get_root_directory( volume, &root_directory, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "root_directory", root_directory ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_file_entry_free( &root_directory, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "root_directory", root_directory ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_get_root_directory( NULL, &root_directory, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "root_directory", root_directory ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_get_root_directory( volume, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "root_directory", root_directory ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( root_directory != NULL ) { libfsntfs_file_entry_free( &root_directory, NULL ); } return( 0 ); } /* Tests the libfsntfs_volume_get_usn_change_journal function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_get_usn_change_journal( libfsntfs_volume_t *volume ) { libcerror_error_t *error = NULL; libfsntfs_usn_change_journal_t *usn_change_journal = 0; int result = 0; int usn_change_journal_is_set = 0; /* Test regular cases */ result = libfsntfs_volume_get_usn_change_journal( volume, &usn_change_journal, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); usn_change_journal_is_set = result; if( usn_change_journal_is_set != 0 ) { FSNTFS_TEST_ASSERT_IS_NOT_NULL( "usn_change_journal", usn_change_journal ); result = libfsntfs_usn_change_journal_free( &usn_change_journal, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } /* Test error cases */ result = libfsntfs_volume_get_usn_change_journal( NULL, &usn_change_journal, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "usn_change_journal", usn_change_journal ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); if( usn_change_journal_is_set != 0 ) { result = libfsntfs_volume_get_usn_change_journal( volume, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "usn_change_journal", usn_change_journal ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( usn_change_journal != NULL ) { libfsntfs_usn_change_journal_free( &usn_change_journal, NULL ); } return( 0 ); } /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc, wchar_t * const argv[] ) #else int main( int argc, char * const argv[] ) #endif { libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_volume_t *volume = NULL; system_character_t *option_offset = NULL; system_character_t *source = NULL; system_integer_t option = 0; size_t string_length = 0; off64_t volume_offset = 0; int result = 0; while( ( option = fsntfs_test_getopt( argc, argv, _SYSTEM_STRING( "o:" ) ) ) != (system_integer_t) -1 ) { switch( option ) { case (system_integer_t) '?': default: fprintf( stderr, "Invalid argument: %" PRIs_SYSTEM ".\n", argv[ optind - 1 ] ); return( EXIT_FAILURE ); case (system_integer_t) 'o': option_offset = optarg; break; } } if( optind < argc ) { source = argv[ optind ]; } if( option_offset != NULL ) { string_length = system_string_length( option_offset ); result = fsntfs_test_system_string_copy_from_64_bit_in_decimal( option_offset, string_length + 1, (uint64_t *) &volume_offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } #if defined( HAVE_DEBUG_OUTPUT ) && defined( FSNTFS_TEST_VOLUME_VERBOSE ) libfsntfs_notify_set_verbose( 1 ); libfsntfs_notify_set_stream( stderr, NULL ); #endif FSNTFS_TEST_RUN( "libfsntfs_volume_initialize", fsntfs_test_volume_initialize ); FSNTFS_TEST_RUN( "libfsntfs_volume_free", fsntfs_test_volume_free ); #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) if( source != NULL ) { result = libbfio_file_range_initialize( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); string_length = system_string_length( source ); #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libbfio_file_range_set_name_wide( file_io_handle, source, string_length, &error ); #else result = libbfio_file_range_set_name( file_io_handle, source, string_length, &error ); #endif FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libbfio_file_range_set( file_io_handle, volume_offset, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_check_volume_signature_file_io_handle( file_io_handle, &error ); FSNTFS_TEST_ASSERT_NOT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } if( ( result != 0 ) && ( volume_offset == 0 ) ) { FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_open", fsntfs_test_volume_open, source ); #if defined( HAVE_WIDE_CHARACTER_TYPE ) FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_open_wide", fsntfs_test_volume_open_wide, source ); #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_open_file_io_handle", fsntfs_test_volume_open_file_io_handle, source ); FSNTFS_TEST_RUN( "libfsntfs_volume_close", fsntfs_test_volume_close ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_open_close", fsntfs_test_volume_open_close, source ); /* TODO: add tests for libfsntfs_internal_volume_open_read */ /* TODO: add tests for libfsntfs_internal_volume_read_bitmap */ /* TODO: add tests for libfsntfs_internal_volume_read_security_descriptors */ } if( result != 0 ) { /* Initialize volume for tests */ result = fsntfs_test_volume_open_source( &volume, file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "volume", volume ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_signal_abort", fsntfs_test_volume_signal_abort, volume ); /* TODO: add tests for libfsntfs_volume_has_bitlocker_drive_encryption */ /* TODO: add tests for libfsntfs_volume_has_volume_shadow_snapshots */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_get_bytes_per_sector", fsntfs_test_volume_get_bytes_per_sector, volume ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_get_cluster_block_size", fsntfs_test_volume_get_cluster_block_size, volume ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_get_mft_entry_size", fsntfs_test_volume_get_mft_entry_size, volume ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_get_index_entry_size", fsntfs_test_volume_get_index_entry_size, volume ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_get_utf8_name_size", fsntfs_test_volume_get_utf8_name_size, volume ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_get_utf8_name", fsntfs_test_volume_get_utf8_name, volume ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_get_utf16_name_size", fsntfs_test_volume_get_utf16_name_size, volume ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_get_utf16_name", fsntfs_test_volume_get_utf16_name, volume ); /* TODO: add tests for libfsntfs_volume_get_version */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_get_serial_number", fsntfs_test_volume_get_serial_number, volume ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_get_number_of_file_entries", fsntfs_test_volume_get_number_of_file_entries, volume ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_get_file_entry_by_index", fsntfs_test_volume_get_file_entry_by_index, volume ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf8_path", fsntfs_test_internal_volume_get_mft_and_directory_entry_by_utf8_path, volume ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_get_file_entry_by_utf8_path", fsntfs_test_volume_get_file_entry_by_utf8_path, volume ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_internal_volume_get_mft_and_directory_entry_by_utf16_path", fsntfs_test_internal_volume_get_mft_and_directory_entry_by_utf16_path, volume ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_get_file_entry_by_utf16_path", fsntfs_test_volume_get_file_entry_by_utf16_path, volume ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_get_root_directory", fsntfs_test_volume_get_root_directory, volume ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_get_usn_change_journal", fsntfs_test_volume_get_usn_change_journal, volume ); /* Clean up */ result = fsntfs_test_volume_close_source( &volume, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume", volume ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } if( file_io_handle != NULL ) { result = libbfio_handle_free( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); } #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ return( EXIT_SUCCESS ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( volume != NULL ) { libfsntfs_volume_free( &volume, NULL ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } return( EXIT_FAILURE ); } ================================================ FILE: tests/fsntfs_test_volume_header.c ================================================ /* * Library volume_header type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_functions.h" #include "fsntfs_test_libbfio.h" #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_volume_header.h" uint8_t fsntfs_test_volume_header_data1[ 512 ] = { 0xeb, 0x52, 0x90, 0x4e, 0x54, 0x46, 0x53, 0x20, 0x20, 0x20, 0x20, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x3f, 0x00, 0x20, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0xc0, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x23, 0x56, 0xed, 0x50, 0x92, 0xed, 0x50, 0xba, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x33, 0xc0, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0xfb, 0xb8, 0xc0, 0x07, 0x8e, 0xd8, 0xe8, 0x16, 0x00, 0xb8, 0x00, 0x0d, 0x8e, 0xc0, 0x33, 0xdb, 0xc6, 0x06, 0x0e, 0x00, 0x10, 0xe8, 0x53, 0x00, 0x68, 0x00, 0x0d, 0x68, 0x6a, 0x02, 0xcb, 0x8a, 0x16, 0x24, 0x00, 0xb4, 0x08, 0xcd, 0x13, 0x73, 0x05, 0xb9, 0xff, 0xff, 0x8a, 0xf1, 0x66, 0x0f, 0xb6, 0xc6, 0x40, 0x66, 0x0f, 0xb6, 0xd1, 0x80, 0xe2, 0x3f, 0xf7, 0xe2, 0x86, 0xcd, 0xc0, 0xed, 0x06, 0x41, 0x66, 0x0f, 0xb7, 0xc9, 0x66, 0xf7, 0xe1, 0x66, 0xa3, 0x20, 0x00, 0xc3, 0xb4, 0x41, 0xbb, 0xaa, 0x55, 0x8a, 0x16, 0x24, 0x00, 0xcd, 0x13, 0x72, 0x0f, 0x81, 0xfb, 0x55, 0xaa, 0x75, 0x09, 0xf6, 0xc1, 0x01, 0x74, 0x04, 0xfe, 0x06, 0x14, 0x00, 0xc3, 0x66, 0x60, 0x1e, 0x06, 0x66, 0xa1, 0x10, 0x00, 0x66, 0x03, 0x06, 0x1c, 0x00, 0x66, 0x3b, 0x06, 0x20, 0x00, 0x0f, 0x82, 0x3a, 0x00, 0x1e, 0x66, 0x6a, 0x00, 0x66, 0x50, 0x06, 0x53, 0x66, 0x68, 0x10, 0x00, 0x01, 0x00, 0x80, 0x3e, 0x14, 0x00, 0x00, 0x0f, 0x85, 0x0c, 0x00, 0xe8, 0xb3, 0xff, 0x80, 0x3e, 0x14, 0x00, 0x00, 0x0f, 0x84, 0x61, 0x00, 0xb4, 0x42, 0x8a, 0x16, 0x24, 0x00, 0x16, 0x1f, 0x8b, 0xf4, 0xcd, 0x13, 0x66, 0x58, 0x5b, 0x07, 0x66, 0x58, 0x66, 0x58, 0x1f, 0xeb, 0x2d, 0x66, 0x33, 0xd2, 0x66, 0x0f, 0xb7, 0x0e, 0x18, 0x00, 0x66, 0xf7, 0xf1, 0xfe, 0xc2, 0x8a, 0xca, 0x66, 0x8b, 0xd0, 0x66, 0xc1, 0xea, 0x10, 0xf7, 0x36, 0x1a, 0x00, 0x86, 0xd6, 0x8a, 0x16, 0x24, 0x00, 0x8a, 0xe8, 0xc0, 0xe4, 0x06, 0x0a, 0xcc, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x0f, 0x82, 0x19, 0x00, 0x8c, 0xc0, 0x05, 0x20, 0x00, 0x8e, 0xc0, 0x66, 0xff, 0x06, 0x10, 0x00, 0xff, 0x0e, 0x0e, 0x00, 0x0f, 0x85, 0x6f, 0xff, 0x07, 0x1f, 0x66, 0x61, 0xc3, 0xa0, 0xf8, 0x01, 0xe8, 0x09, 0x00, 0xa0, 0xfb, 0x01, 0xe8, 0x03, 0x00, 0xfb, 0xeb, 0xfe, 0xb4, 0x01, 0x8b, 0xf0, 0xac, 0x3c, 0x00, 0x74, 0x09, 0xb4, 0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10, 0xeb, 0xf2, 0xc3, 0x0d, 0x0a, 0x41, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x6f, 0x63, 0x63, 0x75, 0x72, 0x72, 0x65, 0x64, 0x00, 0x0d, 0x0a, 0x4e, 0x54, 0x4c, 0x44, 0x52, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x00, 0x0d, 0x0a, 0x4e, 0x54, 0x4c, 0x44, 0x52, 0x20, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x00, 0x0d, 0x0a, 0x50, 0x72, 0x65, 0x73, 0x73, 0x20, 0x43, 0x74, 0x72, 0x6c, 0x2b, 0x41, 0x6c, 0x74, 0x2b, 0x44, 0x65, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0xa0, 0xb3, 0xc9, 0x00, 0x00, 0x55, 0xaa }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_volume_header_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_header_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_volume_header_t *volume_header = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_volume_header_initialize( &volume_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "volume_header", volume_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_volume_header_free( &volume_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume_header", volume_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_header_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); volume_header = (libfsntfs_volume_header_t *) 0x12345678UL; result = libfsntfs_volume_header_initialize( &volume_header, &error ); volume_header = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_volume_header_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_volume_header_initialize( &volume_header, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( volume_header != NULL ) { libfsntfs_volume_header_free( &volume_header, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume_header", volume_header ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_volume_header_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_volume_header_initialize( &volume_header, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( volume_header != NULL ) { libfsntfs_volume_header_free( &volume_header, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume_header", volume_header ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( volume_header != NULL ) { libfsntfs_volume_header_free( &volume_header, NULL ); } return( 0 ); } /* Tests the libfsntfs_volume_header_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_header_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_volume_header_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_header_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_header_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_volume_header_t *volume_header = NULL; int result = 0; /* Initialize test */ result = libfsntfs_volume_header_initialize( &volume_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "volume_header", volume_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_volume_header_read_data( volume_header, fsntfs_test_volume_header_data1, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_header_read_data( NULL, fsntfs_test_volume_header_data1, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_header_read_data( volume_header, NULL, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_header_read_data( volume_header, fsntfs_test_volume_header_data1, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_header_read_data( volume_header, fsntfs_test_volume_header_data1, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where signature is invalid */ byte_stream_copy_from_uint64_little_endian( &( fsntfs_test_volume_header_data1[ 3 ] ), 0xffffffffffffffffUL ); result = libfsntfs_volume_header_read_data( volume_header, fsntfs_test_volume_header_data1, 512, &error ); byte_stream_copy_from_uint64_little_endian( &( fsntfs_test_volume_header_data1[ 3 ] ), 0x202020205346544eUL ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where bytes per sector is invalid */ byte_stream_copy_from_uint16_little_endian( &( fsntfs_test_volume_header_data1[ 11 ] ), 0xffff ); result = libfsntfs_volume_header_read_data( volume_header, fsntfs_test_volume_header_data1, 512, &error ); byte_stream_copy_from_uint16_little_endian( &( fsntfs_test_volume_header_data1[ 11 ] ), 512 ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where sectors per cluster block is invalid */ fsntfs_test_volume_header_data1[ 13 ] = 0xc0; result = libfsntfs_volume_header_read_data( volume_header, fsntfs_test_volume_header_data1, 512, &error ); fsntfs_test_volume_header_data1[ 13 ] = 0x01; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where cluster block size is invalid */ fsntfs_test_volume_header_data1[ 13 ] = 0x1f; result = libfsntfs_volume_header_read_data( volume_header, fsntfs_test_volume_header_data1, 512, &error ); fsntfs_test_volume_header_data1[ 13 ] = 0x01; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where total number of sectors is invalid */ byte_stream_copy_from_uint64_little_endian( &( fsntfs_test_volume_header_data1[ 40 ] ), 0x0080000000000001UL ); result = libfsntfs_volume_header_read_data( volume_header, fsntfs_test_volume_header_data1, 512, &error ); byte_stream_copy_from_uint64_little_endian( &( fsntfs_test_volume_header_data1[ 40 ] ), 0x0000000000003ec0UL ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where MFT entry size is invalid */ fsntfs_test_volume_header_data1[ 64 ] = 0x00; result = libfsntfs_volume_header_read_data( volume_header, fsntfs_test_volume_header_data1, 512, &error ); fsntfs_test_volume_header_data1[ 64 ] = 0x02; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where MFT entry size is invalid */ fsntfs_test_volume_header_data1[ 64 ] = 0xdf; result = libfsntfs_volume_header_read_data( volume_header, fsntfs_test_volume_header_data1, 512, &error ); fsntfs_test_volume_header_data1[ 64 ] = 0x02; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where MFT entry size is invalid */ fsntfs_test_volume_header_data1[ 64 ] = 0xff; result = libfsntfs_volume_header_read_data( volume_header, fsntfs_test_volume_header_data1, 512, &error ); fsntfs_test_volume_header_data1[ 64 ] = 0x02; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where index entry size is invalid */ fsntfs_test_volume_header_data1[ 68 ] = 0x00; result = libfsntfs_volume_header_read_data( volume_header, fsntfs_test_volume_header_data1, 512, &error ); fsntfs_test_volume_header_data1[ 68 ] = 0x02; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where index entry size is invalid */ fsntfs_test_volume_header_data1[ 68 ] = 0xdf; result = libfsntfs_volume_header_read_data( volume_header, fsntfs_test_volume_header_data1, 512, &error ); fsntfs_test_volume_header_data1[ 68 ] = 0x02; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test error case where index entry size is invalid */ fsntfs_test_volume_header_data1[ 68 ] = 0xff; result = libfsntfs_volume_header_read_data( volume_header, fsntfs_test_volume_header_data1, 512, &error ); fsntfs_test_volume_header_data1[ 68 ] = 0x02; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_volume_header_free( &volume_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume_header", volume_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( volume_header != NULL ) { libfsntfs_volume_header_free( &volume_header, NULL ); } return( 0 ); } /* Tests the libfsntfs_volume_header_read_file_io_handle function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_header_read_file_io_handle( void ) { libbfio_handle_t *file_io_handle = NULL; libcerror_error_t *error = NULL; libfsntfs_volume_header_t *volume_header = NULL; int result = 0; /* Initialize test */ result = libfsntfs_volume_header_initialize( &volume_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "volume_header", volume_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize file IO handle */ result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_volume_header_data1, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_volume_header_read_file_io_handle( volume_header, file_io_handle, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_header_read_file_io_handle( NULL, file_io_handle, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_header_read_file_io_handle( volume_header, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_header_read_file_io_handle( volume_header, file_io_handle, -1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up file IO handle */ result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test data too small */ result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_volume_header_data1, 8, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_volume_header_read_file_io_handle( volume_header, file_io_handle, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test data invalid */ result = fsntfs_test_open_file_io_handle( &file_io_handle, fsntfs_test_volume_header_data1, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "file_io_handle", file_io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); byte_stream_copy_from_uint64_little_endian( &( fsntfs_test_volume_header_data1[ 3 ] ), 0xffffffffffffffffUL ); result = libfsntfs_volume_header_read_file_io_handle( volume_header, file_io_handle, 0, &error ); byte_stream_copy_from_uint64_little_endian( &( fsntfs_test_volume_header_data1[ 3 ] ), 0x202020205346544eUL ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = fsntfs_test_close_file_io_handle( &file_io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Clean up */ result = libfsntfs_volume_header_free( &volume_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume_header", volume_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } if( volume_header != NULL ) { libfsntfs_volume_header_free( &volume_header, NULL ); } return( 0 ); } /* Tests the libfsntfs_volume_header_get_bytes_per_sector function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_header_get_bytes_per_sector( libfsntfs_volume_header_t *volume_header ) { libcerror_error_t *error = NULL; uint16_t bytes_per_sector = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_header_get_bytes_per_sector( volume_header, &bytes_per_sector, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT16( "bytes_per_sector", bytes_per_sector, 512 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_header_get_bytes_per_sector( NULL, &bytes_per_sector, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_header_get_bytes_per_sector( volume_header, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_header_get_cluster_block_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_header_get_cluster_block_size( libfsntfs_volume_header_t *volume_header ) { libcerror_error_t *error = NULL; size32_t cluster_block_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_header_get_cluster_block_size( volume_header, &cluster_block_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT32( "cluster_block_size", (uint32_t) cluster_block_size, 512 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_header_get_cluster_block_size( NULL, &cluster_block_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_header_get_cluster_block_size( volume_header, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_header_get_mft_entry_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_header_get_mft_entry_size( libfsntfs_volume_header_t *volume_header ) { libcerror_error_t *error = NULL; size32_t mft_entry_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_header_get_mft_entry_size( volume_header, &mft_entry_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT32( "mft_entry_size", (uint32_t) mft_entry_size, 1024 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_header_get_mft_entry_size( NULL, &mft_entry_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_header_get_mft_entry_size( volume_header, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_header_get_index_entry_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_header_get_index_entry_size( libfsntfs_volume_header_t *volume_header ) { libcerror_error_t *error = NULL; size32_t index_entry_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_header_get_index_entry_size( volume_header, &index_entry_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT32( "index_entry_size", (uint32_t) index_entry_size, 1024 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_header_get_index_entry_size( NULL, &index_entry_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_header_get_index_entry_size( volume_header, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_header_get_volume_serial_number function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_header_get_volume_serial_number( libfsntfs_volume_header_t *volume_header ) { libcerror_error_t *error = NULL; uint64_t volume_serial_number = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_header_get_volume_serial_number( volume_header, &volume_serial_number, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_UINT64( "volume_serial_number", volume_serial_number, (uint64_t) 0xba50ed9250ed5623UL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_header_get_volume_serial_number( NULL, &volume_serial_number, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_header_get_volume_serial_number( volume_header, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_header_get_mft_offset function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_header_get_mft_offset( libfsntfs_volume_header_t *volume_header ) { libcerror_error_t *error = NULL; off64_t mft_offset = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_header_get_mft_offset( volume_header, &mft_offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_INT64( "mft_offset", mft_offset, (int64_t) 0x0029d600UL ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_header_get_mft_offset( NULL, &mft_offset, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_header_get_mft_offset( volume_header, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_volume_header_t *volume_header = NULL; int result = 0; #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_volume_header_initialize", fsntfs_test_volume_header_initialize ); FSNTFS_TEST_RUN( "libfsntfs_volume_header_free", fsntfs_test_volume_header_free ); FSNTFS_TEST_RUN( "libfsntfs_volume_header_read_data", fsntfs_test_volume_header_read_data ); FSNTFS_TEST_RUN( "libfsntfs_volume_header_read_file_io_handle", fsntfs_test_volume_header_read_file_io_handle ); #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize test */ result = libfsntfs_volume_header_initialize( &volume_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "volume_header", volume_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_volume_header_read_data( volume_header, fsntfs_test_volume_header_data1, 512, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Run tests */ FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_header_get_bytes_per_sector", fsntfs_test_volume_header_get_bytes_per_sector, volume_header ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_header_get_cluster_block_size", fsntfs_test_volume_header_get_cluster_block_size, volume_header ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_header_get_mft_entry_size", fsntfs_test_volume_header_get_mft_entry_size, volume_header ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_header_get_index_entry_size", fsntfs_test_volume_header_get_index_entry_size, volume_header ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_header_get_volume_serial_number", fsntfs_test_volume_header_get_volume_serial_number, volume_header ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_header_get_mft_offset", fsntfs_test_volume_header_get_mft_offset, volume_header ); /* Clean up */ result = libfsntfs_volume_header_free( &volume_header, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume_header", volume_header ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( volume_header != NULL ) { libfsntfs_volume_header_free( &volume_header, NULL ); } return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_volume_information_attribute.c ================================================ /* * Library volume_information_attributes functions test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_attribute.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_volume_information_attribute.h" uint8_t fsntfs_test_volume_information_attribute_data1[ 40 ] = { 0x70, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_volume_information_attribute_get_version function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_information_attribute_get_version( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; intptr_t *value = NULL; uint32_t type = 0; uint8_t major_version = 0; uint8_t minor_version = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_information_attribute_get_version( attribute, &major_version, &minor_version, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_information_attribute_get_version( NULL, &major_version, &minor_version, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_information_attribute_get_version( attribute, NULL, &minor_version, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_information_attribute_get_version( attribute, &major_version, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); type = ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type; ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = 0; result = libfsntfs_volume_information_attribute_get_version( attribute, &major_version, &minor_version, &error ); ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = type; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); value = ( (libfsntfs_internal_attribute_t *) attribute )->value; ( (libfsntfs_internal_attribute_t *) attribute )->value = NULL; result = libfsntfs_volume_information_attribute_get_version( attribute, &major_version, &minor_version, &error ); ( (libfsntfs_internal_attribute_t *) attribute )->value = value; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_information_attribute_get_flags function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_information_attribute_get_flags( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; intptr_t *value = NULL; uint32_t type = 0; uint16_t flags = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_information_attribute_get_flags( attribute, &flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_information_attribute_get_flags( NULL, &flags, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_information_attribute_get_flags( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); type = ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type; ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = 0; result = libfsntfs_volume_information_attribute_get_flags( attribute, &flags, &error ); ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = type; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); value = ( (libfsntfs_internal_attribute_t *) attribute )->value; ( (libfsntfs_internal_attribute_t *) attribute )->value = NULL; result = libfsntfs_volume_information_attribute_get_flags( attribute, &flags, &error ); ( (libfsntfs_internal_attribute_t *) attribute )->value = value; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_attribute_t *attribute = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; #endif FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize attribute for tests */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_volume_information_attribute_data1, 40, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_attribute_initialize( &attribute, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_internal_attribute_read_value( (libfsntfs_internal_attribute_t *) attribute, io_handle, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_information_attribute_get_version", fsntfs_test_volume_information_attribute_get_version, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_information_attribute_get_flags", fsntfs_test_volume_information_attribute_get_flags, attribute ); /* Clean up */ result = libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( attribute != NULL ) { libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &attribute, &error ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, &error ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_volume_information_values.c ================================================ /* * Library volume_information_values type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" #include "../libfsntfs/libfsntfs_standard_information_values.h" #include "../libfsntfs/libfsntfs_volume_information_values.h" uint8_t fsntfs_test_volume_information_values_data1[ 40 ] = { 0x70, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_volume_information_values_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_information_values_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_volume_information_values_t *volume_information_values = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_volume_information_values_initialize( &volume_information_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "volume_information_values", volume_information_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_volume_information_values_free( &volume_information_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume_information_values", volume_information_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_information_values_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); volume_information_values = (libfsntfs_volume_information_values_t *) 0x12345678UL; result = libfsntfs_volume_information_values_initialize( &volume_information_values, &error ); volume_information_values = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_volume_information_values_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_volume_information_values_initialize( &volume_information_values, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( volume_information_values != NULL ) { libfsntfs_volume_information_values_free( &volume_information_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume_information_values", volume_information_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_volume_information_values_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_volume_information_values_initialize( &volume_information_values, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( volume_information_values != NULL ) { libfsntfs_volume_information_values_free( &volume_information_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume_information_values", volume_information_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( volume_information_values != NULL ) { libfsntfs_volume_information_values_free( &volume_information_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_volume_information_values_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_information_values_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_volume_information_values_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_information_values_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_information_values_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_volume_information_values_t *volume_information_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_volume_information_values_initialize( &volume_information_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "volume_information_values", volume_information_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_volume_information_values_read_data( volume_information_values, &( fsntfs_test_volume_information_values_data1[ 24 ] ), 12, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_information_values_read_data( NULL, &( fsntfs_test_volume_information_values_data1[ 24 ] ), 12, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_information_values_read_data( volume_information_values, NULL, 12, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_information_values_read_data( volume_information_values, &( fsntfs_test_volume_information_values_data1[ 24 ] ), (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_information_values_read_data( volume_information_values, &( fsntfs_test_volume_information_values_data1[ 24 ] ), 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_volume_information_values_free( &volume_information_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume_information_values", volume_information_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( volume_information_values != NULL ) { libfsntfs_volume_information_values_free( &volume_information_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_volume_information_values_read_from_mft_attribute function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_information_values_read_from_mft_attribute( void ) { libcerror_error_t *error = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; libfsntfs_volume_information_values_t *volume_information_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_volume_information_values_data1, 40, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_volume_information_values_initialize( &volume_information_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "volume_information_values", volume_information_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_volume_information_values_read_from_mft_attribute( volume_information_values, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_information_values_read_from_mft_attribute( NULL, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_information_values_read_from_mft_attribute( volume_information_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_volume_information_values_free( &volume_information_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume_information_values", volume_information_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( volume_information_values != NULL ) { libfsntfs_volume_information_values_free( &volume_information_values, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_volume_information_values_initialize", fsntfs_test_volume_information_values_initialize ); FSNTFS_TEST_RUN( "libfsntfs_volume_information_values_free", fsntfs_test_volume_information_values_free ); FSNTFS_TEST_RUN( "libfsntfs_volume_information_values_read_data", fsntfs_test_volume_information_values_read_data ); FSNTFS_TEST_RUN( "libfsntfs_volume_information_values_read_from_mft_attribute", fsntfs_test_volume_information_values_read_from_mft_attribute ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_volume_name_attribute.c ================================================ /* * Library volume_name_attributes functions test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_attribute.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_volume_name_attribute.h" uint8_t fsntfs_test_volume_name_attribute_data1[ 48 ] = { 0x60, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x56, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_volume_name_attribute_get_utf8_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_name_attribute_get_utf8_name_size( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; size_t utf8_name_size = 0; uint32_t type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_name_attribute_get_utf8_name_size( attribute, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf8_name_size", utf8_name_size, (size_t) 11 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_name_attribute_get_utf8_name_size( NULL, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_name_attribute_get_utf8_name_size( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); type = ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type; ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = 0; result = libfsntfs_volume_name_attribute_get_utf8_name_size( attribute, &utf8_name_size, &error ); ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = type; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_name_attribute_get_utf8_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_name_attribute_get_utf8_name( libfsntfs_attribute_t *attribute ) { uint8_t utf8_name[ 16 ]; libcerror_error_t *error = NULL; uint32_t type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_name_attribute_get_utf8_name( attribute, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_name_attribute_get_utf8_name( NULL, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_name_attribute_get_utf8_name( attribute, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_name_attribute_get_utf8_name( attribute, utf8_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_name_attribute_get_utf8_name( attribute, utf8_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); type = ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type; ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = 0; result = libfsntfs_volume_name_attribute_get_utf8_name( attribute, utf8_name, 16, &error ); ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = type; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_name_attribute_get_utf16_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_name_attribute_get_utf16_name_size( libfsntfs_attribute_t *attribute ) { libcerror_error_t *error = NULL; size_t utf16_name_size = 0; uint32_t type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_name_attribute_get_utf16_name_size( attribute, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf16_name_size", utf16_name_size, (size_t) 11 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_name_attribute_get_utf16_name_size( NULL, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_name_attribute_get_utf16_name_size( attribute, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); type = ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type; ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = 0; result = libfsntfs_volume_name_attribute_get_utf16_name_size( attribute, &utf16_name_size, &error ); ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = type; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_name_attribute_get_utf16_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_name_attribute_get_utf16_name( libfsntfs_attribute_t *attribute ) { uint16_t utf16_name[ 16 ]; libcerror_error_t *error = NULL; uint32_t type = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_name_attribute_get_utf16_name( attribute, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_name_attribute_get_utf16_name( NULL, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_name_attribute_get_utf16_name( attribute, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_name_attribute_get_utf16_name( attribute, utf16_name, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_name_attribute_get_utf16_name( attribute, utf16_name, (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); type = ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type; ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = 0; result = libfsntfs_volume_name_attribute_get_utf16_name( attribute, utf16_name, 16, &error ); ( (libfsntfs_internal_attribute_t *) attribute )->mft_attribute->type = type; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_attribute_t *attribute = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; int result = 0; #endif FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize attribute for tests */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_volume_name_attribute_data1, 48, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_attribute_initialize( &attribute, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_internal_attribute_read_value( (libfsntfs_internal_attribute_t *) attribute, io_handle, NULL, 0, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_name_attribute_get_utf8_name_size", fsntfs_test_volume_name_attribute_get_utf8_name_size, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_name_attribute_get_utf8_name", fsntfs_test_volume_name_attribute_get_utf8_name, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_name_attribute_get_utf16_name_size", fsntfs_test_volume_name_attribute_get_utf16_name_size, attribute ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_name_attribute_get_utf16_name", fsntfs_test_volume_name_attribute_get_utf16_name, attribute ); /* Clean up */ result = libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "attribute", attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( attribute != NULL ) { libfsntfs_internal_attribute_free( (libfsntfs_internal_attribute_t **) &attribute, &error ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, &error ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/fsntfs_test_volume_name_values.c ================================================ /* * Library volume_name_values type test program * * Copyright (C) 2010-2026, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #if defined( HAVE_STDLIB_H ) || defined( WINAPI ) #include #endif #include "fsntfs_test_libcerror.h" #include "fsntfs_test_libfsntfs.h" #include "fsntfs_test_macros.h" #include "fsntfs_test_memory.h" #include "fsntfs_test_unused.h" #include "../libfsntfs/libfsntfs_io_handle.h" #include "../libfsntfs/libfsntfs_mft_attribute.h" #include "../libfsntfs/libfsntfs_standard_information_values.h" #include "../libfsntfs/libfsntfs_volume_name_values.h" uint8_t fsntfs_test_volume_name_values_data1[ 48 ] = { 0x60, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x56, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) /* Tests the libfsntfs_volume_name_values_initialize function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_name_values_initialize( void ) { libcerror_error_t *error = NULL; libfsntfs_volume_name_values_t *volume_name_values = NULL; int result = 0; #if defined( HAVE_FSNTFS_TEST_MEMORY ) int number_of_malloc_fail_tests = 1; int number_of_memset_fail_tests = 1; int test_number = 0; #endif /* Test regular cases */ result = libfsntfs_volume_name_values_initialize( &volume_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "volume_name_values", volume_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_volume_name_values_free( &volume_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume_name_values", volume_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_name_values_initialize( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); volume_name_values = (libfsntfs_volume_name_values_t *) 0x12345678UL; result = libfsntfs_volume_name_values_initialize( &volume_name_values, &error ); volume_name_values = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) for( test_number = 0; test_number < number_of_malloc_fail_tests; test_number++ ) { /* Test libfsntfs_volume_name_values_initialize with malloc failing */ fsntfs_test_malloc_attempts_before_fail = test_number; result = libfsntfs_volume_name_values_initialize( &volume_name_values, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; if( volume_name_values != NULL ) { libfsntfs_volume_name_values_free( &volume_name_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume_name_values", volume_name_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } for( test_number = 0; test_number < number_of_memset_fail_tests; test_number++ ) { /* Test libfsntfs_volume_name_values_initialize with memset failing */ fsntfs_test_memset_attempts_before_fail = test_number; result = libfsntfs_volume_name_values_initialize( &volume_name_values, &error ); if( fsntfs_test_memset_attempts_before_fail != -1 ) { fsntfs_test_memset_attempts_before_fail = -1; if( volume_name_values != NULL ) { libfsntfs_volume_name_values_free( &volume_name_values, NULL ); } } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume_name_values", volume_name_values ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } } #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( volume_name_values != NULL ) { libfsntfs_volume_name_values_free( &volume_name_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_volume_name_values_free function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_name_values_free( void ) { libcerror_error_t *error = NULL; int result = 0; /* Test error cases */ result = libfsntfs_volume_name_values_free( NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_name_values_read_data function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_name_values_read_data( void ) { libcerror_error_t *error = NULL; libfsntfs_volume_name_values_t *volume_name_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_volume_name_values_initialize( &volume_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "volume_name_values", volume_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_volume_name_values_read_data( volume_name_values, &( fsntfs_test_volume_name_values_data1[ 24 ] ), 20, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_name_values_read_data( volume_name_values, &( fsntfs_test_volume_name_values_data1[ 24 ] ), 20, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_volume_name_values_free( &volume_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume_name_values", volume_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Initialize test */ result = libfsntfs_volume_name_values_initialize( &volume_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "volume_name_values", volume_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_name_values_read_data( NULL, &( fsntfs_test_volume_name_values_data1[ 24 ] ), 20, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); volume_name_values->name = (uint8_t *) 0x12345678UL; result = libfsntfs_volume_name_values_read_data( volume_name_values, &( fsntfs_test_volume_name_values_data1[ 24 ] ), 20, &error ); volume_name_values->name = NULL; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_name_values_read_data( volume_name_values, NULL, 20, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_name_values_read_data( volume_name_values, &( fsntfs_test_volume_name_values_data1[ 24 ] ), (size_t) SSIZE_MAX + 1, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); #if defined( HAVE_FSNTFS_TEST_MEMORY ) /* Test libfsntfs_volume_name_values_read_data with malloc failing */ fsntfs_test_malloc_attempts_before_fail = 0; result = libfsntfs_volume_name_values_read_data( volume_name_values, &( fsntfs_test_volume_name_values_data1[ 24 ] ), 20, &error ); if( fsntfs_test_malloc_attempts_before_fail != -1 ) { fsntfs_test_malloc_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #if defined( OPTIMIZATION_DISABLED ) /* Test libfsntfs_volume_name_values_read_data with memcpy failing */ fsntfs_test_memcpy_attempts_before_fail = 0; result = libfsntfs_volume_name_values_read_data( volume_name_values, &( fsntfs_test_volume_name_values_data1[ 24 ] ), 20, &error ); if( fsntfs_test_memcpy_attempts_before_fail != -1 ) { fsntfs_test_memcpy_attempts_before_fail = -1; } else { FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); } #endif /* defined( OPTIMIZATION_DISABLED ) */ #endif /* defined( HAVE_FSNTFS_TEST_MEMORY ) */ /* Clean up */ result = libfsntfs_volume_name_values_free( &volume_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume_name_values", volume_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( volume_name_values != NULL ) { libfsntfs_volume_name_values_free( &volume_name_values, NULL ); } return( 0 ); } /* Tests the libfsntfs_volume_name_values_read_from_mft_attribute function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_name_values_read_from_mft_attribute( void ) { libcerror_error_t *error = NULL; libfsntfs_io_handle_t *io_handle = NULL; libfsntfs_mft_attribute_t *mft_attribute = NULL; libfsntfs_volume_name_values_t *volume_name_values = NULL; int result = 0; /* Initialize test */ result = libfsntfs_io_handle_initialize( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); io_handle->cluster_block_size = 4096; result = libfsntfs_mft_attribute_initialize( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_read_data( mft_attribute, io_handle, fsntfs_test_volume_name_values_data1, 48, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_volume_name_values_initialize( &volume_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "volume_name_values", volume_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test regular cases */ result = libfsntfs_volume_name_values_read_from_mft_attribute( volume_name_values, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_name_values_read_from_mft_attribute( NULL, mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); result = libfsntfs_volume_name_values_read_from_mft_attribute( volume_name_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Clean up */ result = libfsntfs_volume_name_values_free( &volume_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume_name_values", volume_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_mft_attribute_free( &mft_attribute, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "mft_attribute", mft_attribute ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_io_handle_free( &io_handle, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "io_handle", io_handle ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( volume_name_values != NULL ) { libfsntfs_volume_name_values_free( &volume_name_values, NULL ); } if( mft_attribute != NULL ) { libfsntfs_mft_attribute_free( &mft_attribute, NULL ); } if( io_handle != NULL ) { libfsntfs_io_handle_free( &io_handle, NULL ); } return( 0 ); } /* Tests the libfsntfs_volume_name_values_get_utf8_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_name_values_get_utf8_name_size( libfsntfs_volume_name_values_t *volume_name_values ) { libcerror_error_t *error = NULL; uint8_t *name = NULL; size_t name_size = 0; size_t utf8_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_name_values_get_utf8_name_size( volume_name_values, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf8_name_size", utf8_name_size, (size_t) 11 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test with empty name */ name = volume_name_values->name; name_size = volume_name_values->name_size; volume_name_values->name = NULL; volume_name_values->name_size = 0; result = libfsntfs_volume_name_values_get_utf8_name_size( volume_name_values, &utf8_name_size, &error ); volume_name_values->name = name; volume_name_values->name_size = name_size; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf8_name_size", utf8_name_size, (size_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_name_values_get_utf8_name_size( NULL, &utf8_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); name = volume_name_values->name; name_size = volume_name_values->name_size; volume_name_values->name = NULL; volume_name_values->name_size = 0; result = libfsntfs_volume_name_values_get_utf8_name_size( volume_name_values, NULL, &error ); volume_name_values->name = name; volume_name_values->name_size = name_size; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test libfsntfs_volume_name_values_get_utf8_name_size with failing libuna_utf8_string_size_from_utf16_stream */ result = libfsntfs_volume_name_values_get_utf8_name_size( volume_name_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_name_values_get_utf8_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_name_values_get_utf8_name( libfsntfs_volume_name_values_t *volume_name_values ) { uint8_t utf8_name[ 16 ]; libcerror_error_t *error = NULL; uint8_t *name = NULL; size_t name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_name_values_get_utf8_name( volume_name_values, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test with empty name */ name = volume_name_values->name; name_size = volume_name_values->name_size; volume_name_values->name = NULL; volume_name_values->name_size = 0; result = libfsntfs_volume_name_values_get_utf8_name( volume_name_values, utf8_name, 16, &error ); volume_name_values->name = name; volume_name_values->name_size = name_size; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_name_values_get_utf8_name( NULL, utf8_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); name = volume_name_values->name; name_size = volume_name_values->name_size; volume_name_values->name = NULL; volume_name_values->name_size = 0; result = libfsntfs_volume_name_values_get_utf8_name( volume_name_values, NULL, 16, &error ); volume_name_values->name = name; volume_name_values->name_size = name_size; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); name = volume_name_values->name; name_size = volume_name_values->name_size; volume_name_values->name = NULL; volume_name_values->name_size = 0; result = libfsntfs_volume_name_values_get_utf8_name( volume_name_values, utf8_name, 0, &error ); volume_name_values->name = name; volume_name_values->name_size = name_size; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); name = volume_name_values->name; name_size = volume_name_values->name_size; volume_name_values->name = NULL; volume_name_values->name_size = 0; result = libfsntfs_volume_name_values_get_utf8_name( volume_name_values, utf8_name, (size_t) SSIZE_MAX + 1, &error ); volume_name_values->name = name; volume_name_values->name_size = name_size; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test fsntfs_test_volume_name_values_get_utf8_name with failing libuna_utf8_string_copy_from_utf16_stream */ result = libfsntfs_volume_name_values_get_utf8_name( volume_name_values, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_name_values_get_utf16_name_size function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_name_values_get_utf16_name_size( libfsntfs_volume_name_values_t *volume_name_values ) { libcerror_error_t *error = NULL; uint8_t *name = NULL; size_t name_size = 0; size_t utf16_name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_name_values_get_utf16_name_size( volume_name_values, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf16_name_size", utf16_name_size, (size_t) 11 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test with empty name */ name = volume_name_values->name; name_size = volume_name_values->name_size; volume_name_values->name = NULL; volume_name_values->name_size = 0; result = libfsntfs_volume_name_values_get_utf16_name_size( volume_name_values, &utf16_name_size, &error ); volume_name_values->name = name; volume_name_values->name_size = name_size; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_EQUAL_SIZE( "utf16_name_size", utf16_name_size, (size_t) 0 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_name_values_get_utf16_name_size( NULL, &utf16_name_size, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); name = volume_name_values->name; name_size = volume_name_values->name_size; volume_name_values->name = NULL; volume_name_values->name_size = 0; result = libfsntfs_volume_name_values_get_utf16_name_size( volume_name_values, NULL, &error ); volume_name_values->name = name; volume_name_values->name_size = name_size; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test libfsntfs_volume_name_values_get_utf16_name_size with failing libuna_utf16_string_size_from_utf16_stream */ result = libfsntfs_volume_name_values_get_utf16_name_size( volume_name_values, NULL, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } /* Tests the libfsntfs_volume_name_values_get_utf16_name function * Returns 1 if successful or 0 if not */ int fsntfs_test_volume_name_values_get_utf16_name( libfsntfs_volume_name_values_t *volume_name_values ) { uint16_t utf16_name[ 16 ]; libcerror_error_t *error = NULL; uint8_t *name = NULL; size_t name_size = 0; int result = 0; /* Test regular cases */ result = libfsntfs_volume_name_values_get_utf16_name( volume_name_values, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test with empty name */ name = volume_name_values->name; name_size = volume_name_values->name_size; volume_name_values->name = NULL; volume_name_values->name_size = 0; result = libfsntfs_volume_name_values_get_utf16_name( volume_name_values, utf16_name, 16, &error ); volume_name_values->name = name; volume_name_values->name_size = name_size; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); /* Test error cases */ result = libfsntfs_volume_name_values_get_utf16_name( NULL, utf16_name, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); name = volume_name_values->name; name_size = volume_name_values->name_size; volume_name_values->name = NULL; volume_name_values->name_size = 0; result = libfsntfs_volume_name_values_get_utf16_name( volume_name_values, NULL, 16, &error ); volume_name_values->name = name; volume_name_values->name_size = name_size; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); name = volume_name_values->name; name_size = volume_name_values->name_size; volume_name_values->name = NULL; volume_name_values->name_size = 0; result = libfsntfs_volume_name_values_get_utf16_name( volume_name_values, utf16_name, 0, &error ); volume_name_values->name = name; volume_name_values->name_size = name_size; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); name = volume_name_values->name; name_size = volume_name_values->name_size; volume_name_values->name = NULL; volume_name_values->name_size = 0; result = libfsntfs_volume_name_values_get_utf16_name( volume_name_values, utf16_name, (size_t) SSIZE_MAX + 1, &error ); volume_name_values->name = name; volume_name_values->name_size = name_size; FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); /* Test fsntfs_test_volume_name_values_get_utf16_name with failing libuna_utf16_string_copy_from_utf16_stream */ result = libfsntfs_volume_name_values_get_utf16_name( volume_name_values, NULL, 16, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, -1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "error", error ); libcerror_error_free( &error ); return( 1 ); on_error: if( error != NULL ) { libcerror_error_free( &error ); } return( 0 ); } #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ /* The main program */ #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) int wmain( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, wchar_t * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #else int main( int argc FSNTFS_TEST_ATTRIBUTE_UNUSED, char * const argv[] FSNTFS_TEST_ATTRIBUTE_UNUSED ) #endif { #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) libcerror_error_t *error = NULL; libfsntfs_volume_name_values_t *volume_name_values = NULL; int result = 0; #endif FSNTFS_TEST_UNREFERENCED_PARAMETER( argc ) FSNTFS_TEST_UNREFERENCED_PARAMETER( argv ) #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) FSNTFS_TEST_RUN( "libfsntfs_volume_name_values_initialize", fsntfs_test_volume_name_values_initialize ); FSNTFS_TEST_RUN( "libfsntfs_volume_name_values_free", fsntfs_test_volume_name_values_free ); FSNTFS_TEST_RUN( "libfsntfs_volume_name_values_read_data", fsntfs_test_volume_name_values_read_data ); FSNTFS_TEST_RUN( "libfsntfs_volume_name_values_read_from_mft_attribute", fsntfs_test_volume_name_values_read_from_mft_attribute ); #if !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) /* Initialize volume_name_values for tests */ result = libfsntfs_volume_name_values_initialize( &volume_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NOT_NULL( "volume_name_values", volume_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); result = libfsntfs_volume_name_values_read_data( volume_name_values, &( fsntfs_test_volume_name_values_data1[ 24 ] ), 20, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_name_values_get_utf8_name_size", fsntfs_test_volume_name_values_get_utf8_name_size, volume_name_values ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_name_values_get_utf8_name", fsntfs_test_volume_name_values_get_utf8_name, volume_name_values ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_name_values_get_utf16_name_size", fsntfs_test_volume_name_values_get_utf16_name_size, volume_name_values ); FSNTFS_TEST_RUN_WITH_ARGS( "libfsntfs_volume_name_values_get_utf16_name", fsntfs_test_volume_name_values_get_utf16_name, volume_name_values ); /* Clean up */ result = libfsntfs_volume_name_values_free( &volume_name_values, &error ); FSNTFS_TEST_ASSERT_EQUAL_INT( "result", result, 1 ); FSNTFS_TEST_ASSERT_IS_NULL( "volume_name_values", volume_name_values ); FSNTFS_TEST_ASSERT_IS_NULL( "error", error ); #endif /* !defined( __BORLANDC__ ) || ( __BORLANDC__ >= 0x0560 ) */ #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ return( EXIT_SUCCESS ); #if defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) on_error: if( error != NULL ) { libcerror_error_free( &error ); } if( volume_name_values != NULL ) { libfsntfs_volume_name_values_free( &volume_name_values, NULL ); } return( EXIT_FAILURE ); #endif /* defined( __GNUC__ ) && !defined( LIBFSNTFS_DLL_IMPORT ) */ } ================================================ FILE: tests/lsan.suppressions ================================================ leak:/lib*/libpython* ================================================ FILE: tests/pkgbuild.sh ================================================ #!/bin/sh # Script to build a MacOS pkg # # Version: 20241015 set -e make install DESTDIR=${PWD}/osx-pkg mkdir -p ${PWD}/osx-pkg/usr/share/doc/libfsntfs cp AUTHORS COPYING COPYING.LESSER NEWS README ${PWD}/osx-pkg/usr/share/doc/libfsntfs VERSION=`sed '5!d; s/^ \[//;s/\],$//' configure.ac` pkgbuild --root osx-pkg --identifier com.github.libyal.libfsntfs --version ${VERSION} --ownership recommended ../libfsntfs-${VERSION}.pkg ================================================ FILE: tests/pyfsntfs_test_attribute.py ================================================ #!/usr/bin/env python # # Python-bindings attribute type test script # # Copyright (C) 2010-2026, Joachim Metz # # Refer to AUTHORS for acknowledgements. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . import argparse import os import sys import unittest import pyfsntfs class DataRangeFileObject(object): """File-like object that maps an in-file data range.""" def __init__(self, path, range_offset, range_size): """Initializes a file-like object. Args: path (str): path of the file that contains the data range. range_offset (int): offset where the data range starts. range_size (int): size of the data range starts, or None to indicate the range should continue to the end of the parent file-like object. """ if range_size is None: stat_object = os.stat(path) range_size = stat_object.st_size super(DataRangeFileObject, self).__init__() self._current_offset = 0 self._file_object = open(path, "rb") self._range_offset = range_offset self._range_size = range_size def __enter__(self): """Enters a with statement.""" return self def __exit__(self, unused_type, unused_value, unused_traceback): """Exits a with statement.""" return def close(self): """Closes the file-like object.""" if self._file_object: self._file_object.close() self._file_object = None def get_offset(self): """Retrieves the current offset into the file-like object. Returns: int: current offset in the data range. """ return self._current_offset def get_size(self): """Retrieves the size of the file-like object. Returns: int: size of the data range. """ return self._range_size def read(self, size=None): """Reads a byte string from the file-like object at the current offset. The function will read a byte string of the specified size or all of the remaining data if no size was specified. Args: size (Optional[int]): number of bytes to read, where None is all remaining data. Returns: bytes: data read. Raises: IOError: if the read failed. """ if (self._range_offset < 0 or (self._range_size is not None and self._range_size < 0)): raise IOError("Invalid data range.") if self._current_offset < 0: raise IOError( "Invalid current offset: {0:d} value less than zero.".format( self._current_offset)) if (self._range_size is not None and self._current_offset >= self._range_size): return b"" if size is None: size = self._range_size if self._range_size is not None and self._current_offset + size > self._range_size: size = self._range_size - self._current_offset self._file_object.seek( self._range_offset + self._current_offset, os.SEEK_SET) data = self._file_object.read(size) self._current_offset += len(data) return data def seek(self, offset, whence=os.SEEK_SET): """Seeks to an offset within the file-like object. Args: offset (int): offset to seek to. whence (Optional(int)): value that indicates whether offset is an absolute or relative position within the file. Raises: IOError: if the seek failed. """ if self._current_offset < 0: raise IOError( "Invalid current offset: {0:d} value less than zero.".format( self._current_offset)) if whence == os.SEEK_CUR: offset += self._current_offset elif whence == os.SEEK_END: offset += self._range_size elif whence != os.SEEK_SET: raise IOError("Unsupported whence.") if offset < 0: raise IOError("Invalid offset value less than zero.") self._current_offset = offset class AttributeTypeTests(unittest.TestCase): """Tests the attribute type.""" def test_get_attribute_type(self): """Tests the get_attribute_type function and attribute_type property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) if not fsntfs_file_entry.number_of_attributes: raise unittest.SkipTest('missing attributes') fsntfs_attribute = fsntfs_file_entry.get_attribute(0) self.assertIsNotNone(fsntfs_attribute) attribute_type = fsntfs_attribute.get_attribute_type() self.assertIsNotNone(attribute_type) self.assertIsNotNone(fsntfs_attribute.attribute_type) finally: fsntfs_volume.close() def test_get_attribute_name(self): """Tests the get_attribute_name function and attribute_name property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) if not fsntfs_file_entry.number_of_attributes: raise unittest.SkipTest('missing attributes') fsntfs_attribute = fsntfs_file_entry.get_attribute(0) self.assertIsNotNone(fsntfs_attribute) attribute_name = fsntfs_attribute.get_attribute_name() self.assertIsNone(attribute_name) self.assertIsNone(fsntfs_attribute.attribute_name) finally: fsntfs_volume.close() def test_get_data_size(self): """Tests the get_data_size function and data_size property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) if not fsntfs_file_entry.number_of_attributes: raise unittest.SkipTest('missing attributes') fsntfs_attribute = fsntfs_file_entry.get_attribute(0) self.assertIsNotNone(fsntfs_attribute) data_size = fsntfs_attribute.get_data_size() self.assertIsNotNone(data_size) self.assertIsNotNone(fsntfs_attribute.data_size) finally: fsntfs_volume.close() def test_get_valid_data_size(self): """Tests the get_valid_data_size function and valid_data_size property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) if not fsntfs_file_entry.number_of_attributes: raise unittest.SkipTest('missing attributes') fsntfs_attribute = fsntfs_file_entry.get_attribute(0) self.assertIsNotNone(fsntfs_attribute) valid_data_size = fsntfs_attribute.get_valid_data_size() self.assertIsNotNone(valid_data_size) self.assertIsNotNone(fsntfs_attribute.valid_data_size) finally: fsntfs_volume.close() if __name__ == "__main__": argument_parser = argparse.ArgumentParser() argument_parser.add_argument( "-o", "--offset", dest="offset", action="store", default=None, type=int, help="offset of the source file.") argument_parser.add_argument( "source", nargs="?", action="store", metavar="PATH", default=None, help="path of the source file.") options, unknown_options = argument_parser.parse_known_args() unknown_options.insert(0, sys.argv[0]) setattr(unittest, "offset", options.offset) setattr(unittest, "source", options.source) unittest.main(argv=unknown_options, verbosity=2) ================================================ FILE: tests/pyfsntfs_test_file_entry.py ================================================ #!/usr/bin/env python # # Python-bindings file_entry type test script # # Copyright (C) 2010-2026, Joachim Metz # # Refer to AUTHORS for acknowledgements. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . import argparse import os import random import sys import unittest import pyfsntfs class DataRangeFileObject(object): """File-like object that maps an in-file data range.""" def __init__(self, path, range_offset, range_size): """Initializes a file-like object. Args: path (str): path of the file that contains the data range. range_offset (int): offset where the data range starts. range_size (int): size of the data range starts, or None to indicate the range should continue to the end of the parent file-like object. """ if range_size is None: stat_object = os.stat(path) range_size = stat_object.st_size super(DataRangeFileObject, self).__init__() self._current_offset = 0 self._file_object = open(path, "rb") self._range_offset = range_offset self._range_size = range_size def __enter__(self): """Enters a with statement.""" return self def __exit__(self, unused_type, unused_value, unused_traceback): """Exits a with statement.""" return def close(self): """Closes the file-like object.""" if self._file_object: self._file_object.close() self._file_object = None def get_offset(self): """Retrieves the current offset into the file-like object. Returns: int: current offset in the data range. """ return self._current_offset def get_size(self): """Retrieves the size of the file-like object. Returns: int: size of the data range. """ return self._range_size def read(self, size=None): """Reads a byte string from the file-like object at the current offset. The function will read a byte string of the specified size or all of the remaining data if no size was specified. Args: size (Optional[int]): number of bytes to read, where None is all remaining data. Returns: bytes: data read. Raises: IOError: if the read failed. """ if (self._range_offset < 0 or (self._range_size is not None and self._range_size < 0)): raise IOError("Invalid data range.") if self._current_offset < 0: raise IOError( "Invalid current offset: {0:d} value less than zero.".format( self._current_offset)) if (self._range_size is not None and self._current_offset >= self._range_size): return b"" if size is None: size = self._range_size if self._range_size is not None and self._current_offset + size > self._range_size: size = self._range_size - self._current_offset self._file_object.seek( self._range_offset + self._current_offset, os.SEEK_SET) data = self._file_object.read(size) self._current_offset += len(data) return data def seek(self, offset, whence=os.SEEK_SET): """Seeks to an offset within the file-like object. Args: offset (int): offset to seek to. whence (Optional(int)): value that indicates whether offset is an absolute or relative position within the file. Raises: IOError: if the seek failed. """ if self._current_offset < 0: raise IOError( "Invalid current offset: {0:d} value less than zero.".format( self._current_offset)) if whence == os.SEEK_CUR: offset += self._current_offset elif whence == os.SEEK_END: offset += self._range_size elif whence != os.SEEK_SET: raise IOError("Unsupported whence.") if offset < 0: raise IOError("Invalid offset value less than zero.") self._current_offset = offset class FileEntryTypeTests(unittest.TestCase): """Tests the file_entry type.""" def test_get_size(self): """Tests the get_size function and size property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) size = fsntfs_file_entry.get_size() self.assertIsNotNone(size) self.assertIsNotNone(fsntfs_file_entry.size) finally: fsntfs_volume.close() def test_get_number_of_extents(self): """Tests the get_number_of_extents function and number_of_extents property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) number_of_extents = fsntfs_file_entry.get_number_of_extents() self.assertIsNotNone(number_of_extents) self.assertIsNotNone(fsntfs_file_entry.number_of_extents) finally: fsntfs_volume.close() def test_get_extent(self): """Tests the get_extent function.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) if not fsntfs_file_entry.number_of_extents: raise unittest.SkipTest('missing extents') extent = fsntfs_file_entry.get_extent(0) self.assertIsNotNone(extent) finally: fsntfs_volume.close() def test_is_empty(self): """Tests the is_empty function.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) is_empty = fsntfs_file_entry.is_empty() self.assertFalse(is_empty) finally: fsntfs_volume.close() def test_is_allocated(self): """Tests the is_allocated function.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) is_allocated = fsntfs_file_entry.is_allocated() self.assertTrue(is_allocated) finally: fsntfs_volume.close() def test_has_directory_entries_index(self): """Tests the has_directory_entries_index function.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) has_directory_entries_index = fsntfs_file_entry.has_directory_entries_index() self.assertFalse(has_directory_entries_index) finally: fsntfs_volume.close() def test_has_default_data_stream(self): """Tests the has_default_data_stream function.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) has_default_data_stream = fsntfs_file_entry.has_default_data_stream() self.assertTrue(has_default_data_stream) finally: fsntfs_volume.close() def test_get_file_reference(self): """Tests the get_file_reference function and file_reference property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) file_reference = fsntfs_file_entry.get_file_reference() self.assertIsNotNone(file_reference) self.assertIsNotNone(fsntfs_file_entry.file_reference) finally: fsntfs_volume.close() def test_get_base_record_file_reference(self): """Tests the get_base_record_file_reference function and base_record_file_reference property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) base_record_file_reference = fsntfs_file_entry.get_base_record_file_reference() self.assertIsNotNone(base_record_file_reference) self.assertIsNotNone(fsntfs_file_entry.base_record_file_reference) finally: fsntfs_volume.close() # TODO: add tests for parent_file_reference # TODO: add tests for get_parent_file_reference_by_attribute_index def test_get_journal_sequence_number(self): """Tests the get_journal_sequence_number function and journal_sequence_number property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) journal_sequence_number = fsntfs_file_entry.get_journal_sequence_number() self.assertIsNotNone(journal_sequence_number) self.assertIsNotNone(fsntfs_file_entry.journal_sequence_number) finally: fsntfs_volume.close() def test_get_creation_time(self): """Tests the get_creation_time function and creation_time property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) creation_time = fsntfs_file_entry.get_creation_time() self.assertIsNotNone(creation_time) self.assertIsNotNone(fsntfs_file_entry.creation_time) finally: fsntfs_volume.close() def test_get_creation_time_as_integer(self): """Tests the get_creation_time_as_integer function.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) creation_time = fsntfs_file_entry.get_creation_time_as_integer() self.assertIsNotNone(creation_time) finally: fsntfs_volume.close() def test_get_modification_time(self): """Tests the get_modification_time function and modification_time property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) modification_time = fsntfs_file_entry.get_modification_time() self.assertIsNotNone(modification_time) self.assertIsNotNone(fsntfs_file_entry.modification_time) finally: fsntfs_volume.close() def test_get_modification_time_as_integer(self): """Tests the get_modification_time_as_integer function.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) modification_time = fsntfs_file_entry.get_modification_time_as_integer() self.assertIsNotNone(modification_time) finally: fsntfs_volume.close() def test_get_access_time(self): """Tests the get_access_time function and access_time property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) access_time = fsntfs_file_entry.get_access_time() self.assertIsNotNone(access_time) self.assertIsNotNone(fsntfs_file_entry.access_time) finally: fsntfs_volume.close() def test_get_access_time_as_integer(self): """Tests the get_access_time_as_integer function.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) access_time = fsntfs_file_entry.get_access_time_as_integer() self.assertIsNotNone(access_time) finally: fsntfs_volume.close() def test_get_entry_modification_time(self): """Tests the get_entry_modification_time function and entry_modification_time property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) entry_modification_time = fsntfs_file_entry.get_entry_modification_time() self.assertIsNotNone(entry_modification_time) self.assertIsNotNone(fsntfs_file_entry.entry_modification_time) finally: fsntfs_volume.close() def test_get_entry_modification_time_as_integer(self): """Tests the get_entry_modification_time_as_integer function.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) entry_modification_time = fsntfs_file_entry.get_entry_modification_time_as_integer() self.assertIsNotNone(entry_modification_time) finally: fsntfs_volume.close() def test_get_name(self): """Tests the get_name function and name property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) name = fsntfs_file_entry.get_name() self.assertIsNotNone(name) self.assertIsNotNone(fsntfs_file_entry.name) finally: fsntfs_volume.close() def test_get_name_attribute_index(self): """Tests the get_name_attribute_index function and name_attribute_index property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) name_attribute_index = fsntfs_file_entry.get_name_attribute_index() self.assertIsNotNone(name_attribute_index) self.assertIsNotNone(fsntfs_file_entry.name_attribute_index) finally: fsntfs_volume.close() def test_get_file_attribute_flags(self): """Tests the get_file_attribute_flags function and file_attribute_flags property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) file_attribute_flags = fsntfs_file_entry.get_file_attribute_flags() self.assertIsNotNone(file_attribute_flags) self.assertIsNotNone(fsntfs_file_entry.file_attribute_flags) finally: fsntfs_volume.close() # TODO: add tests for path_hint def test_get_symbolic_link_target(self): """Tests the get_symbolic_link_target function and symbolic_link_target property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) symbolic_link_target = fsntfs_file_entry.get_symbolic_link_target() self.assertIsNone(symbolic_link_target) self.assertIsNone(fsntfs_file_entry.symbolic_link_target) finally: fsntfs_volume.close() def test_get_security_descriptor_data(self): """Tests the get_security_descriptor_data function and security_descriptor_data property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_root_directory() self.assertIsNotNone(fsntfs_file_entry) security_descriptor_data = fsntfs_file_entry.get_security_descriptor_data() self.assertIsNotNone(security_descriptor_data) self.assertIsNotNone(fsntfs_file_entry.security_descriptor_data) finally: fsntfs_volume.close() def test_get_number_of_attributes(self): """Tests the get_number_of_attributes function and number_of_attributes property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) number_of_attributes = fsntfs_file_entry.get_number_of_attributes() self.assertIsNotNone(number_of_attributes) self.assertIsNotNone(fsntfs_file_entry.number_of_attributes) finally: fsntfs_volume.close() def test_get_attribute(self): """Tests the get_attribute function.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) if not fsntfs_file_entry.number_of_attributes: raise unittest.SkipTest('missing attributes') attribute = fsntfs_file_entry.get_attribute(0) self.assertIsNotNone(attribute) finally: fsntfs_volume.close() def test_get_number_of_alternate_data_streams(self): """Tests the get_number_of_alternate_data_streams function and number_of_alternate_data_streams property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) number_of_alternate_data_streams = fsntfs_file_entry.get_number_of_alternate_data_streams() self.assertIsNotNone(number_of_alternate_data_streams) self.assertIsNotNone(fsntfs_file_entry.number_of_alternate_data_streams) finally: fsntfs_volume.close() # TODO: add tests for get_alternate_data_stream # TODO: add tests for has_alternate_data_stream_by_name # TODO: add tests for get_alternate_data_stream_by_name def test_get_number_of_sub_file_entries(self): """Tests the get_number_of_sub_file_entries function and number_of_sub_file_entries property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(fsntfs_file_entry) number_of_sub_file_entries = fsntfs_file_entry.get_number_of_sub_file_entries() self.assertIsNotNone(number_of_sub_file_entries) self.assertIsNotNone(fsntfs_file_entry.number_of_sub_file_entries) finally: fsntfs_volume.close() # TODO: add tests for get_sub_file_entry if __name__ == "__main__": argument_parser = argparse.ArgumentParser() argument_parser.add_argument( "-o", "--offset", dest="offset", action="store", default=None, type=int, help="offset of the source file.") argument_parser.add_argument( "source", nargs="?", action="store", metavar="PATH", default=None, help="path of the source file.") options, unknown_options = argument_parser.parse_known_args() unknown_options.insert(0, sys.argv[0]) setattr(unittest, "offset", options.offset) setattr(unittest, "source", options.source) unittest.main(argv=unknown_options, verbosity=2) ================================================ FILE: tests/pyfsntfs_test_support.py ================================================ #!/usr/bin/env python # # Python-bindings support functions test script # # Copyright (C) 2010-2026, Joachim Metz # # Refer to AUTHORS for acknowledgements. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . import argparse import os import sys import unittest import pyfsntfs class SupportFunctionsTests(unittest.TestCase): """Tests the support functions.""" def test_get_version(self): """Tests the get_version function.""" version = pyfsntfs.get_version() self.assertIsNotNone(version) if __name__ == "__main__": argument_parser = argparse.ArgumentParser() argument_parser.add_argument( "source", nargs="?", action="store", metavar="PATH", default=None, help="path of the source file.") options, unknown_options = argument_parser.parse_known_args() unknown_options.insert(0, sys.argv[0]) setattr(unittest, "source", options.source) unittest.main(argv=unknown_options, verbosity=2) ================================================ FILE: tests/pyfsntfs_test_volume.py ================================================ #!/usr/bin/env python # # Python-bindings volume type test script # # Copyright (C) 2010-2026, Joachim Metz # # Refer to AUTHORS for acknowledgements. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . import argparse import os import sys import unittest import pyfsntfs class DataRangeFileObject(object): """File-like object that maps an in-file data range.""" def __init__(self, path, range_offset, range_size): """Initializes a file-like object. Args: path (str): path of the file that contains the data range. range_offset (int): offset where the data range starts. range_size (int): size of the data range starts, or None to indicate the range should continue to the end of the parent file-like object. """ if range_size is None: stat_object = os.stat(path) range_size = stat_object.st_size super(DataRangeFileObject, self).__init__() self._current_offset = 0 self._file_object = open(path, "rb") self._range_offset = range_offset self._range_size = range_size def __enter__(self): """Enters a with statement.""" return self def __exit__(self, unused_type, unused_value, unused_traceback): """Exits a with statement.""" return def close(self): """Closes the file-like object.""" if self._file_object: self._file_object.close() self._file_object = None def get_offset(self): """Retrieves the current offset into the file-like object. Returns: int: current offset in the data range. """ return self._current_offset def get_size(self): """Retrieves the size of the file-like object. Returns: int: size of the data range. """ return self._range_size def read(self, size=None): """Reads a byte string from the file-like object at the current offset. The function will read a byte string of the specified size or all of the remaining data if no size was specified. Args: size (Optional[int]): number of bytes to read, where None is all remaining data. Returns: bytes: data read. Raises: IOError: if the read failed. """ if (self._range_offset < 0 or (self._range_size is not None and self._range_size < 0)): raise IOError("Invalid data range.") if self._current_offset < 0: raise IOError( "Invalid current offset: {0:d} value less than zero.".format( self._current_offset)) if (self._range_size is not None and self._current_offset >= self._range_size): return b"" if size is None: size = self._range_size if self._range_size is not None and self._current_offset + size > self._range_size: size = self._range_size - self._current_offset self._file_object.seek( self._range_offset + self._current_offset, os.SEEK_SET) data = self._file_object.read(size) self._current_offset += len(data) return data def seek(self, offset, whence=os.SEEK_SET): """Seeks to an offset within the file-like object. Args: offset (int): offset to seek to. whence (Optional(int)): value that indicates whether offset is an absolute or relative position within the file. Raises: IOError: if the seek failed. """ if self._current_offset < 0: raise IOError( "Invalid current offset: {0:d} value less than zero.".format( self._current_offset)) if whence == os.SEEK_CUR: offset += self._current_offset elif whence == os.SEEK_END: offset += self._range_size elif whence != os.SEEK_SET: raise IOError("Unsupported whence.") if offset < 0: raise IOError("Invalid offset value less than zero.") self._current_offset = offset class VolumeTypeTests(unittest.TestCase): """Tests the volume type.""" def test_signal_abort(self): """Tests the signal_abort function.""" fsntfs_volume = pyfsntfs.volume() fsntfs_volume.signal_abort() def test_open(self): """Tests the open function.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest("missing source") test_offset = getattr(unittest, "offset", None) if test_offset: raise unittest.SkipTest("unsupported source with offset") fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open(test_source) with self.assertRaises(IOError): fsntfs_volume.open(test_source) fsntfs_volume.close() with self.assertRaises(TypeError): fsntfs_volume.open(None) with self.assertRaises(ValueError): fsntfs_volume.open(test_source, mode="w") def test_open_file_object(self): """Tests the open_file_object function.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest("missing source") if not os.path.isfile(test_source): raise unittest.SkipTest("source not a regular file") fsntfs_volume = pyfsntfs.volume() test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume.open_file_object(file_object) with self.assertRaises(IOError): fsntfs_volume.open_file_object(file_object) fsntfs_volume.close() with self.assertRaises(TypeError): fsntfs_volume.open_file_object(None) with self.assertRaises(ValueError): fsntfs_volume.open_file_object(file_object, mode="w") def test_close(self): """Tests the close function.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest("missing source") fsntfs_volume = pyfsntfs.volume() with self.assertRaises(IOError): fsntfs_volume.close() def test_open_close(self): """Tests the open and close functions.""" test_source = getattr(unittest, "source", None) if not test_source: return test_offset = getattr(unittest, "offset", None) if test_offset: raise unittest.SkipTest("unsupported source with offset") fsntfs_volume = pyfsntfs.volume() # Test open and close. fsntfs_volume.open(test_source) fsntfs_volume.close() # Test open and close a second time to validate clean up on close. fsntfs_volume.open(test_source) fsntfs_volume.close() if os.path.isfile(test_source): with open(test_source, "rb") as file_object: # Test open_file_object and close. fsntfs_volume.open_file_object(file_object) fsntfs_volume.close() # Test open_file_object and close a second time to validate clean up on close. fsntfs_volume.open_file_object(file_object) fsntfs_volume.close() # Test open_file_object and close and dereferencing file_object. fsntfs_volume.open_file_object(file_object) del file_object fsntfs_volume.close() def test_get_bytes_per_sector(self): """Tests the get_bytes_per_sector function and bytes_per_sector property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest("missing source") fsntfs_volume = pyfsntfs.volume() test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) try: bytes_per_sector = fsntfs_volume.get_bytes_per_sector() self.assertIsNotNone(bytes_per_sector) self.assertIsNotNone(fsntfs_volume.bytes_per_sector) finally: fsntfs_volume.close() def test_get_cluster_block_size(self): """Tests the get_cluster_block_size function and cluster_block_size property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest("missing source") fsntfs_volume = pyfsntfs.volume() test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) try: cluster_block_size = fsntfs_volume.get_cluster_block_size() self.assertIsNotNone(cluster_block_size) self.assertIsNotNone(fsntfs_volume.cluster_block_size) finally: fsntfs_volume.close() def test_get_mft_entry_size(self): """Tests the get_mft_entry_size function and mft_entry_size property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest("missing source") fsntfs_volume = pyfsntfs.volume() test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) try: mft_entry_size = fsntfs_volume.get_mft_entry_size() self.assertIsNotNone(mft_entry_size) self.assertIsNotNone(fsntfs_volume.mft_entry_size) finally: fsntfs_volume.close() def test_get_index_entry_size(self): """Tests the get_index_entry_size function and index_entry_size property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest("missing source") fsntfs_volume = pyfsntfs.volume() test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) try: index_entry_size = fsntfs_volume.get_index_entry_size() self.assertIsNotNone(index_entry_size) self.assertIsNotNone(fsntfs_volume.index_entry_size) finally: fsntfs_volume.close() def test_get_name(self): """Tests the get_name function and name property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest("missing source") fsntfs_volume = pyfsntfs.volume() test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) try: name = fsntfs_volume.get_name() self.assertIsNotNone(name) self.assertIsNotNone(fsntfs_volume.name) finally: fsntfs_volume.close() def test_get_serial_number(self): """Tests the get_serial_number function and serial_number property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest("missing source") fsntfs_volume = pyfsntfs.volume() test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) try: serial_number = fsntfs_volume.get_serial_number() self.assertIsNotNone(serial_number) self.assertIsNotNone(fsntfs_volume.serial_number) finally: fsntfs_volume.close() def test_get_number_of_file_entries(self): """Tests the get_number_of_file_entries function and number_of_file_entries property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest("missing source") fsntfs_volume = pyfsntfs.volume() test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) try: number_of_file_entries = fsntfs_volume.get_number_of_file_entries() self.assertIsNotNone(number_of_file_entries) self.assertIsNotNone(fsntfs_volume.number_of_file_entries) finally: fsntfs_volume.close() def test_get_file_entry(self): """Tests the get_file_entry function.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) if not fsntfs_volume.number_of_file_entries: raise unittest.SkipTest('missing file entries') try: file_entry = fsntfs_volume.get_file_entry(0) self.assertIsNotNone(file_entry) finally: fsntfs_volume.close() def test_get_file_entry_by_path(self): """Tests the get_file_entry_by_path function.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest('missing source') test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) try: file_entry = fsntfs_volume.get_file_entry_by_path('\\$MFT') self.assertIsNotNone(file_entry) finally: fsntfs_volume.close() def test_get_root_directory(self): """Tests the get_root_directory function and root_directory property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest("missing source") fsntfs_volume = pyfsntfs.volume() test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) try: root_directory = fsntfs_volume.get_root_directory() self.assertIsNotNone(root_directory) finally: fsntfs_volume.close() def test_get_usn_change_journal(self): """Tests the get_usn_change_journal function and usn_change_journal property.""" test_source = getattr(unittest, "source", None) if not test_source: raise unittest.SkipTest("missing source") fsntfs_volume = pyfsntfs.volume() test_offset = getattr(unittest, "offset", None) with DataRangeFileObject( test_source, test_offset or 0, None) as file_object: fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object) try: _ = fsntfs_volume.get_usn_change_journal() finally: fsntfs_volume.close() if __name__ == "__main__": argument_parser = argparse.ArgumentParser() argument_parser.add_argument( "-o", "--offset", dest="offset", action="store", default=None, type=int, help="offset of the source file.") argument_parser.add_argument( "source", nargs="?", action="store", metavar="PATH", default=None, help="path of the source file.") options, unknown_options = argument_parser.parse_known_args() unknown_options.insert(0, sys.argv[0]) setattr(unittest, "offset", options.offset) setattr(unittest, "source", options.source) unittest.main(argv=unknown_options, verbosity=2) ================================================ FILE: tests/runtests.py ================================================ #!/usr/bin/env python # # Script to run Python test scripts. # # Version: 20231024 import glob import os import sys import unittest test_profile = ".pyfsntfs" input_glob = "*" option_sets = ["offset"] def ReadIgnoreList(test_profile): """Reads the test profile ignore file if it exists. Args: test_profile (str): test profile. Returns: set[str]: ignore list. """ ignore_file_path = os.path.join("tests", "input", test_profile, "ignore") if os.path.isfile(ignore_file_path): with open(ignore_file_path, "r", encoding="utf-8") as file_object: return set([line.strip() for line in file_object.readlines()]) return set() if __name__ == "__main__": print(f"Using Python version {sys.version!s}") test_loader = unittest.TestLoader() test_runner = unittest.TextTestRunner(verbosity=2) test_scripts = test_loader.discover("tests", pattern="*.py") ignore_list = ReadIgnoreList(test_profile) test_set = None source_file = None for test_set in glob.glob(os.path.join("tests", "input", "*")): test_set = test_set.rsplit(os.path.sep, maxsplit=1)[-1] if not test_set or test_set[0] == '.' or test_set in ignore_list: continue source_files = glob.glob(os.path.join( "tests", "input", test_set, input_glob)) if source_files: source_file = source_files[0] break setattr(unittest, "source", source_file) if source_file: for option_set in option_sets: test_file = os.path.basename(source_file) test_options_file_path = os.path.join( "tests", "input", test_profile, test_set, f"{test_file:s}.{option_set:s}") if os.path.isfile(test_options_file_path): with open(test_options_file_path, "r", encoding="utf-8") as file_object: lines = [line.strip() for line in file_object.readlines()] if lines[0] == "# libyal test data options": for line in lines[1:]: key, value = line.split("=", maxsplit=1) if key == 'offset': value = int(value) setattr(unittest, key, value) test_results = test_runner.run(test_scripts) if not test_results.wasSuccessful(): sys.exit(1) ================================================ FILE: tests/runtests.sh ================================================ #!/bin/sh # Script to run tests # # Version: 20201121 if test -f ${PWD}/libfsntfs/.libs/libfsntfs.1.dylib && test -f ./pyfsntfs/.libs/pyfsntfs.so; then install_name_tool -change /usr/local/lib/libfsntfs.1.dylib ${PWD}/libfsntfs/.libs/libfsntfs.1.dylib ./pyfsntfs/.libs/pyfsntfs.so; fi make check CHECK_WITH_STDERR=1; RESULT=$?; if test ${RESULT} -ne 0 && test -f tests/test-suite.log; then cat tests/test-suite.log; fi exit ${RESULT}; ================================================ FILE: tests/syncsharedlibs.sh ================================================ #!/bin/sh # Script that synchronizes the shared library dependencies # # Version: 20201121 EXIT_SUCCESS=0; EXIT_FAILURE=1; GIT_URL_PREFIX="https://github.com/libyal"; SHARED_LIBS="libcerror libcthreads libcdata libclocale libcnotify libcsplit libuna libcfile libcpath libbfio libfcache libfdata libfdatetime libfguid libfwnt libhmac"; USE_HEAD=""; if test "$1" = "--use-head"; then USE_HEAD="--use-head"; fi OLDIFS=$IFS; IFS=" "; for SHARED_LIB in ${SHARED_LIBS}; do GIT_URL="${GIT_URL_PREFIX}/${SHARED_LIB}.git"; git clone --quiet ${GIT_URL} ${SHARED_LIB}-$$; if ! test -d ${SHARED_LIB}-$$; then echo "Unable to git clone: ${GIT_URL}"; IFS=$OLDIFS; exit ${EXIT_FAILURE}; fi (cd ${SHARED_LIB}-$$ && git fetch --quiet --all --tags --prune) LATEST_TAG=`cd ${SHARED_LIB}-$$ && git describe --tags --abbrev=0`; if test -n ${LATEST_TAG} && test -z ${USE_HEAD}; then echo "Synchronizing: ${SHARED_LIB} from ${GIT_URL} tag ${LATEST_TAG}"; (cd ${SHARED_LIB}-$$ && git checkout --quiet tags/${LATEST_TAG}); else echo "Synchronizing: ${SHARED_LIB} from ${GIT_URL} HEAD"; fi (cd ${SHARED_LIB}-$$ && ./synclibs.sh ${USE_HEAD} && ./autogen.sh); CONFIGURE_OPTIONS=""; (cd ${SHARED_LIB}-$$ && ./configure --help | grep -- '--enable-wide-character-type' > /dev/null); if test $? -eq 0; then CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS} --enable-wide-character-type"; fi (cd ${SHARED_LIB}-$$ && ./configure --prefix=/usr ${CONFIGURE_OPTIONS} && make && sudo make install); rm -rf ${SHARED_LIB}-$$; done IFS=$OLDIFS; exit ${EXIT_SUCCESS}; ================================================ FILE: tests/test_fsntfsinfo.ps1 ================================================ # Info tool testing script # # Version: 20251224 $ExitSuccess = 0 $ExitFailure = 1 $ExitIgnore = 77 $Profiles = @("fsntfsinfo", "fsntfsinfo_fs", "fsntfsinfo_mft", "fsntfsinfo_usn") $OptionsPerProfile = @("", "-H", "-Eall", "-U") $OptionSets = "offset" $InputGlob = "*" Function GetTestExecutablesDirectory { $TestExecutablesDirectory = "" ForEach (${VSDirectory} in ("msvscpp", "vs2008", "vs2010", "vs2012", "vs2013", "vs2015", "vs2017", "vs2019", "vs2022")) { ForEach (${VSConfiguration} in ("Release", "VSDebug")) { ForEach (${VSPlatform} in ("Win32", "x64")) { $TestExecutablesDirectory = "..\${VSDirectory}\${VSConfiguration}\${VSPlatform}" If (Test-Path ${TestExecutablesDirectory}) { Return ${TestExecutablesDirectory} } } $TestExecutablesDirectory = "..\${VSDirectory}\${VSConfiguration}" If (Test-Path ${TestExecutablesDirectory}) { Return ${TestExecutablesDirectory} } } } Return ${TestExecutablesDirectory} } Function ReadIgnoreList { param( [string]$TestProfileDirectory ) $IgnoreFile = "${TestProfileDirectory}\ignore" $IgnoreList = "" If (Test-Path -Path ${IgnoreFile} -PathType Leaf) { $IgnoreList = Get-Content -Path ${IgnoreFile} | Where {$_ -notmatch '^#.*'} } Return $IgnoreList } $TestExecutablesDirectory = GetTestExecutablesDirectory If (-Not (Test-Path ${TestExecutablesDirectory})) { Write-Host "Missing test executables directory." -foreground Red Exit ${ExitFailure} } $TestExecutable = "${TestExecutablesDirectory}\fsntfsinfo.exe" If (-Not (Test-Path -Path "input")) { Exit ${ExitIgnore} } $Result = ${ExitSuccess} For ($ProfileIndex = 0; $ProfileIndex -le ($Profiles.length - 1); $ProfileIndex += 1) { $TestProfile = $Profiles[$ProfileIndex] $Options = $OptionsPerProfile[$ProfileIndex] $TestProfileDirectory = "input\.${TestProfile}" If (-Not (Test-Path -Path ${TestProfileDirectory} -PathType Container)) { New-Item -ItemType "directory" -Path ${TestProfileDirectory} | Out-Null } $IgnoreList = ReadIgnoreList ${TestProfileDirectory} ForEach ($TestSetInputDirectory in Get-ChildItem -Path "input" -Exclude ".*") { If (-Not (Test-Path -Path ${TestSetInputDirectory} -PathType Container)) { Continue } If (${TestSetInputDirectory} -Contains ${IgnoreList}) { Continue } $TestSetName = ${TestSetInputDirectory}.Name If (Test-Path -Path "${TestProfileDirectory}\${TestSetName}\files" -PathType Leaf) { $InputFiles = Get-Content -Path "${TestProfileDirectory}\${TestSetName}\files" | Where {$_ -ne ""} $InputFiles = $InputFiles -replace "^","${TestSetInputDirectory}\" } Else { $InputFiles = Get-ChildItem -Path ${TestSetInputDirectory} -Include ${InputGlob} } ForEach ($InputFile in ${InputFiles}) { $InputFileName = ${InputFile}.Name $TestedWithOptions = $False $TmpDir = "tmp${PID}" New-Item -Name ${TmpDir} -ItemType "directory" | Out-Null Push-Location ${TmpDir} Try { ForEach ($OptionSet in ${OptionSets} -split " ") { $TestDataOptionFile = "..\${TestProfileDirectory}\${TestSetName}\${InputFileName}.${OptionSet}" If (-Not (Test-Path -Path "${TestDataOptionFile}" -PathType Leaf)) { Continue } $OptionsHeader = Get-content -Path "${TestDataOptionFile}" -First 1 If (-Not (${OptionsHeader} -match "^# libyal test data options")) { Continue } $InputOptions = Get-content -Path "${TestDataOptionFile}" | Select-Object -Skip 1 $InputOptions = $InputOptions -replace "^offset=","-o" $InputOptions = $InputOptions -replace "^password=","-p" $InputOptions = $InputOptions -replace "^recovery_password=","-r" $InputOptions = $InputOptions -replace "^startup_key=","-s" $InputOptions = $InputOptions -replace "^virtual_address=","-v" $TestLog = "${InputFileName}-${OptionSet}.log" Invoke-Expression "..\${TestExecutable} ${Options} ${InputOptions} ${InputFile} > ${TestLog}" $Result = $LastExitCode If (${Result} -ne ${ExitSuccess}) { Break } $TestedWithOptions = $True } If ((${Result} -eq ${ExitSuccess}) -And (-Not (${TestedWithOptions}))) { $TestLog = "${InputFileName}.log" Invoke-Expression "..\${TestExecutable} ${Options} ${InputFile} > ${TestLog}" $Result = $LastExitCode } If (${Result} -eq ${ExitSuccess}) { # Strip header with version. (Get-Content ${TestLog} | Select-Object -Skip 2) | Set-Content ${TestLog} $StoredTestLog = "..\${TestProfileDirectory}\${TestSetName}\${TestLog}" If (Test-Path -Path ${StoredTestLog} -PathType Leaf) { $Difference = Compare-Object -ReferenceObject (Get-Content -Path ${StoredTestLog}) -DifferenceObject (Get-Content -Path ${TestLog}) If (${Difference}) { $Result = ${ExitFailure} } } Else { Move-Item -Path ${TestLog} -Destination ${StoredTestLog} } } } Finally { Pop-Location Remove-Item ${TmpDir} -Force -Recurse } } If (${Result} -ne ${ExitSuccess}) { Break } } } Exit ${Result} ================================================ FILE: tests/test_fsntfsinfo.sh ================================================ #!/usr/bin/env bash # Info tool testing script # # Version: 20240413 EXIT_SUCCESS=0; EXIT_FAILURE=1; EXIT_IGNORE=77; PROFILES=("fsntfsinfo" "fsntfsinfo_fs" "fsntfsinfo_mft" "fsntfsinfo_usn"); OPTIONS_PER_PROFILE=("" "-H" "-Eall" "-U"); OPTION_SETS=("offset"); INPUT_GLOB="*"; if test -n "${SKIP_TOOLS_TESTS}" || test -n "${SKIP_TOOLS_END_TO_END_TESTS}"; then exit ${EXIT_IGNORE}; fi TEST_EXECUTABLE="../fsntfstools/fsntfsinfo"; if ! test -x "${TEST_EXECUTABLE}"; then TEST_EXECUTABLE="../fsntfstools/fsntfsinfo.exe"; fi if ! test -x "${TEST_EXECUTABLE}"; then echo "Missing test executable: ${TEST_EXECUTABLE}"; exit ${EXIT_FAILURE}; fi TEST_DIRECTORY=`dirname $0`; TEST_RUNNER="${TEST_DIRECTORY}/test_runner.sh"; if ! test -f "${TEST_RUNNER}"; then echo "Missing test runner: ${TEST_RUNNER}"; exit ${EXIT_FAILURE}; fi source ${TEST_RUNNER}; if ! test -d "input"; then echo "Test input directory not found."; exit ${EXIT_IGNORE}; fi RESULT=`ls input/* | tr ' ' '\n' | wc -l`; if test ${RESULT} -eq ${EXIT_SUCCESS}; then echo "No files or directories found in the test input directory"; exit ${EXIT_IGNORE}; fi for PROFILE_INDEX in ${!PROFILES[*]}; do TEST_PROFILE=${PROFILES[${PROFILE_INDEX}]}; TEST_PROFILE_DIRECTORY=$(get_test_profile_directory "input" "${TEST_PROFILE}"); IGNORE_LIST=$(read_ignore_list "${TEST_PROFILE_DIRECTORY}"); IFS=" " read -a PROFILE_OPTIONS <<< ${OPTIONS_PER_PROFILE[${PROFILE_INDEX}]}; RESULT=${EXIT_SUCCESS}; for TEST_SET_INPUT_DIRECTORY in input/*; do if ! test -d "${TEST_SET_INPUT_DIRECTORY}"; then continue; fi TEST_SET=`basename ${TEST_SET_INPUT_DIRECTORY}`; if check_for_test_set_in_ignore_list "${TEST_SET}" "${IGNORE_LIST}"; then continue; fi TEST_SET_DIRECTORY=$(get_test_set_directory "${TEST_PROFILE_DIRECTORY}" "${TEST_SET_INPUT_DIRECTORY}"); RESULT=${EXIT_SUCCESS}; if test -f "${TEST_SET_DIRECTORY}/files"; then IFS="" read -a INPUT_FILES <<< $(cat ${TEST_SET_DIRECTORY}/files | sed "s?^?${TEST_SET_INPUT_DIRECTORY}/?"); else IFS="" read -a INPUT_FILES <<< $(ls -1d ${TEST_SET_INPUT_DIRECTORY}/${INPUT_GLOB}); fi for INPUT_FILE in "${INPUT_FILES[@]}"; do TESTED_WITH_OPTIONS=0; for OPTION_SET in ${OPTION_SETS[@]}; do TEST_DATA_OPTION_FILE=$(get_test_data_option_file "${TEST_SET_DIRECTORY}" "${INPUT_FILE}" "${OPTION_SET}"); if test -f ${TEST_DATA_OPTION_FILE}; then TESTED_WITH_OPTIONS=1; IFS=" " read -a OPTIONS <<< $(read_test_data_option_file "${TEST_SET_DIRECTORY}" "${INPUT_FILE}" "${OPTION_SET}"); run_test_on_input_file "${TEST_SET_DIRECTORY}" "fsntfsinfo" "with_stdout_reference" "${OPTION_SET}" "${TEST_EXECUTABLE}" "${INPUT_FILE}" "${PROFILE_OPTIONS[@]}" "${OPTIONS[@]}"; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi fi done if test ${TESTED_WITH_OPTIONS} -eq 0; then run_test_on_input_file "${TEST_SET_DIRECTORY}" "fsntfsinfo" "with_stdout_reference" "" "${TEST_EXECUTABLE}" "${INPUT_FILE}" "${PROFILE_OPTIONS[@]}"; RESULT=$?; fi if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi done # Ignore failures due to corrupted data. if test "${TEST_SET}" = "corrupted"; then RESULT=${EXIT_SUCCESS}; fi if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi done done exit ${RESULT}; ================================================ FILE: tests/test_fsntfsinfo_bodyfile.ps1 ================================================ # Info tool testing script # # Version: 20230410 $ExitSuccess = 0 $ExitFailure = 1 $ExitIgnore = 77 $Profiles = @("fsntfsinfo_bodyfile_fs", "fsntfsinfo_bodyfile_mft") $OptionsPerProfile = @("-Bbodyfile -H", "-Bbodyfile -Eall") $OptionSets = "offset" $InputGlob = "*" Function GetTestExecutablesDirectory { $TestExecutablesDirectory = "" ForEach (${VSDirectory} in ("msvscpp", "vs2008", "vs2010", "vs2012", "vs2013", "vs2015", "vs2017", "vs2019", "vs2022")) { ForEach (${VSConfiguration} in ("Release", "VSDebug")) { ForEach (${VSPlatform} in ("Win32", "x64")) { $TestExecutablesDirectory = "..\${VSDirectory}\${VSConfiguration}\${VSPlatform}" If (Test-Path ${TestExecutablesDirectory}) { Return ${TestExecutablesDirectory} } } $TestExecutablesDirectory = "..\${VSDirectory}\${VSConfiguration}" If (Test-Path ${TestExecutablesDirectory}) { Return ${TestExecutablesDirectory} } } } Return ${TestExecutablesDirectory} } Function ReadIgnoreList { param( [string]$TestProfileDirectory ) $IgnoreFile = "${TestProfileDirectory}\ignore" $IgnoreList = "" If (Test-Path -Path ${IgnoreFile} -PathType "Leaf") { $IgnoreList = Get-Content -Path ${IgnoreFile} | Where {$_ -notmatch '^#.*'} } Return $IgnoreList } $TestExecutablesDirectory = GetTestExecutablesDirectory If (-Not (Test-Path ${TestExecutablesDirectory})) { Write-Host "Missing test executables directory." -foreground Red Exit ${ExitFailure} } $TestExecutable = "${TestExecutablesDirectory}\fsntfsinfo.exe" If (-Not (Test-Path -Path "input")) { Exit ${ExitIgnore} } $Result = ${ExitSuccess} For ($ProfileIndex = 0; $ProfileIndex -le ($Profiles.length - 1); $ProfileIndex += 1) { $TestProfile = $Profiles[$ProfileIndex] $Options = $OptionsPerProfile[$ProfileIndex] $TestProfileDirectory = "input\.${TestProfile}" If (-Not (Test-Path -Path ${TestProfileDirectory} -PathType "Container")) { New-Item -ItemType "directory" -Path ${TestProfileDirectory} | Out-Null } $IgnoreList = ReadIgnoreList ${TestProfileDirectory} # Note that the trailing backtick is needed. Get-ChildItem -Path "input" -Exclude ".*" | ForEach-Object ` { $TestSetDirectory = $_ If (-Not (Test-Path -Path ${TestSetDirectory} -PathType Container)) { Continue } $TestSetName = ${TestSetDirectory}.Name If (${IgnoreList}.Contains(${TestSetName})) { Continue } If (-Not (Test-Path -Path "${TestProfileDirectory}\${TestSetName}" -PathType Container)) { New-Item -Name "${TestProfileDirectory}\${TestSetName}" -ItemType "directory" | Out-Null } If (Test-Path -Path "${TestProfileDirectory}\${TestSetName}\files" -PathType Container) { $InputFiles = Get-content -Path "${TestProfileDirectory}\${TestSetName}\files" } Else { $InputFiles = Get-ChildItem -Path "${TestSetDirectory}\${InputGlob}" } ForEach ($InputFile in ${InputFiles}) { $InputFileName = ${InputFile}.Name $TestedWithOptions = $False $TmpDir = "tmp${PID}" New-Item -Name ${TmpDir} -ItemType "directory" | Out-Null Push-Location ${TmpDir} Try { ForEach ($OptionSet in ${OptionSets} -split " ") { $TestDataOptionFile = "..\${TestProfileDirectory}\${TestSetName}\${InputFileName}.${OptionSet}" If (-Not (Test-Path -Path "${TestDataOptionFile}" -PathType "Leaf")) { Continue } $InputOptions = Get-content -Path "${TestDataOptionFile}" -First 1 $TestLog = "${InputFileName}-${OptionSet}.log" Invoke-Expression "..\${TestExecutable} ${Options} ${InputOptions} ${InputFile} > ${TestLog}" $Result = $LastExitCode If (${Result} -ne ${ExitSuccess}) { Break } $TestedWithOptions = $True } If ((${Result} -eq ${ExitSuccess}) -And (-Not (${TestedWithOptions}))) { $TestLog = "${InputFileName}.log" Invoke-Expression "..\${TestExecutable} ${Options} ${InputFile} > ${TestLog}" $Result = $LastExitCode } If (${Result} -eq ${ExitSuccess}) { $TestResults = "bodyfile" $StoredTestResults = "..\${TestProfileDirectory}\${TestSetName}\${InputFileName}-bodyfile" If (Test-Path -Path ${StoredTestResults} -PathType "Leaf") { $Difference = Compare-Object -ReferenceObject (Get-Content -Path ${StoredTestResults}) -DifferenceObject (Get-Content -Path ${TestResults}) If (${Difference}) { $Result = ${ExitFailure} } } Else { Move-Item -Path ${TestResults} -Destination ${StoredTestResults} } } } Finally { Pop-Location Remove-Item ${TmpDir} -Force -Recurse } } If (${Result} -ne ${ExitSuccess}) { Break } } } Exit ${Result} ================================================ FILE: tests/test_fsntfsinfo_bodyfile.sh ================================================ #!/usr/bin/env bash # Info tool testing script # # Version: 20240413 EXIT_SUCCESS=0; EXIT_FAILURE=1; EXIT_IGNORE=77; PROFILES=("fsntfsinfo_bodyfile_fs" "fsntfsinfo_bodyfile_mft"); OPTIONS_PER_PROFILE=("-Bbodyfile -H" "-Bbodyfile -Eall"); OPTION_SETS=("offset"); INPUT_GLOB="*"; test_callback() { local TMPDIR=$1; local TEST_SET_DIRECTORY=$2; local TEST_OUTPUT=$3; local TEST_EXECUTABLE=$4; local TEST_INPUT=$5; shift 5; local ARGUMENTS=("$@"); TEST_EXECUTABLE=$( readlink_f "${TEST_EXECUTABLE}" ); INPUT_FILE_FULL_PATH=$( readlink_f "${INPUT_FILE}" ); (cd ${TMPDIR} && run_test_with_input_and_arguments "${TEST_EXECUTABLE}" "${INPUT_FILE_FULL_PATH}" ${ARGUMENTS[@]} >/dev/null); local RESULT=$?; if test ${RESULT} -eq ${EXIT_SUCCESS}; then local TEST_RESULTS="${TMPDIR}/bodyfile"; local STORED_TEST_RESULTS="${TEST_SET_DIRECTORY}/${TEST_OUTPUT}-bodyfile.gz"; if test -f "${STORED_TEST_RESULTS}"; then # Using zcat here since zdiff has issues on Mac OS X. # Note that zcat on Mac OS X requires the input from stdin. zcat < "${STORED_TEST_RESULTS}" | diff "${TEST_RESULTS}" -; RESULT=$?; else gzip ${TEST_RESULTS}; mv "${TEST_RESULTS}.gz" "${TEST_SET_DIRECTORY}/${TEST_OUTPUT}-bodyfile.gz"; fi fi return ${RESULT}; } if ! test -z ${SKIP_TOOLS_TESTS}; then exit ${EXIT_IGNORE}; fi TEST_EXECUTABLE="../fsntfstools/fsntfsinfo"; if ! test -x "${TEST_EXECUTABLE}"; then TEST_EXECUTABLE="../fsntfstools/fsntfsinfo.exe"; fi if ! test -x "${TEST_EXECUTABLE}"; then echo "Missing test executable: ${TEST_EXECUTABLE}"; exit ${EXIT_FAILURE}; fi TEST_DIRECTORY=`dirname $0`; TEST_RUNNER="${TEST_DIRECTORY}/test_runner.sh"; if ! test -f "${TEST_RUNNER}"; then echo "Missing test runner: ${TEST_RUNNER}"; exit ${EXIT_FAILURE}; fi source ${TEST_RUNNER}; if ! test -d "input"; then echo "Test input directory not found."; exit ${EXIT_IGNORE}; fi RESULT=`ls input/* | tr ' ' '\n' | wc -l`; if test ${RESULT} -eq ${EXIT_SUCCESS}; then echo "No files or directories found in the test input directory"; exit ${EXIT_IGNORE}; fi for PROFILE_INDEX in ${!PROFILES[*]}; do TEST_PROFILE=${PROFILES[${PROFILE_INDEX}]}; TEST_PROFILE_DIRECTORY=$(get_test_profile_directory "input" "${TEST_PROFILE}"); IGNORE_LIST=$(read_ignore_list "${TEST_PROFILE_DIRECTORY}"); IFS=" " read -a PROFILE_OPTIONS <<< ${OPTIONS_PER_PROFILE[${PROFILE_INDEX}]}; RESULT=${EXIT_SUCCESS}; for TEST_SET_INPUT_DIRECTORY in input/*; do if ! test -d "${TEST_SET_INPUT_DIRECTORY}"; then continue; fi TEST_SET=`basename ${TEST_SET_INPUT_DIRECTORY}`; if check_for_test_set_in_ignore_list "${TEST_SET}" "${IGNORE_LIST}"; then continue; fi TEST_SET_DIRECTORY=$(get_test_set_directory "${TEST_PROFILE_DIRECTORY}" "${TEST_SET_INPUT_DIRECTORY}"); RESULT=${EXIT_SUCCESS}; if test -f "${TEST_SET_DIRECTORY}/files"; then IFS="" read -a INPUT_FILES <<< $(cat ${TEST_SET_DIRECTORY}/files | sed "s?^?${TEST_SET_INPUT_DIRECTORY}/?"); else IFS="" read -a INPUT_FILES <<< $(ls -1d ${TEST_SET_INPUT_DIRECTORY}/${INPUT_GLOB}); fi for INPUT_FILE in "${INPUT_FILES[@]}"; do TESTED_WITH_OPTIONS=0; for OPTION_SET in ${OPTION_SETS[@]}; do TEST_DATA_OPTION_FILE=$(get_test_data_option_file "${TEST_SET_DIRECTORY}" "${INPUT_FILE}" "${OPTION_SET}"); if test -f ${TEST_DATA_OPTION_FILE}; then TESTED_WITH_OPTIONS=1; IFS=" " read -a OPTIONS <<< $(read_test_data_option_file "${TEST_SET_DIRECTORY}" "${INPUT_FILE}" "${OPTION_SET}"); run_test_on_input_file "${TEST_SET_DIRECTORY}" "fsntfsinfo" "with_callback" "${OPTION_SET}" "${TEST_EXECUTABLE}" "${INPUT_FILE}" "${PROFILE_OPTIONS[@]}" "${OPTIONS[@]}"; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi fi done if test ${TESTED_WITH_OPTIONS} -eq 0; then run_test_on_input_file "${TEST_SET_DIRECTORY}" "fsntfsinfo" "with_callback" "" "${TEST_EXECUTABLE}" "${INPUT_FILE}" "${PROFILE_OPTIONS[@]}"; RESULT=$?; fi if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi done # Ignore failures due to corrupted data. if test "${TEST_SET}" = "corrupted"; then RESULT=${EXIT_SUCCESS}; fi if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi done done exit ${RESULT}; ================================================ FILE: tests/test_library.ps1 ================================================ # Tests library functions and types. # # Version: 20251224 $ExitSuccess = 0 $ExitFailure = 1 $ExitIgnore = 77 $LibraryTests = "attribute attribute_list_entry bitmap_values buffer_data_handle cluster_block cluster_block_data cluster_block_stream cluster_block_vector compressed_block compressed_block_data_handle compressed_block_vector compressed_data_handle compression compression_unit_data_handle compression_unit_descriptor data_run data_stream directory_entries_tree directory_entry error extent file_entry file_name_attribute file_name_values file_system fixup_values index index_entry index_entry_header index_entry_vector index_node index_node_header index_root_header index_value io_handle logged_utility_stream_values mft mft_attribute mft_attribute_list mft_attribute_list_entry mft_entry mft_entry_header name notify object_identifier_values path_hint profiler reparse_point_attribute reparse_point_values sds_index_value security_descriptor_index security_descriptor_index_value security_descriptor_values standard_information_values txf_data_values usn_change_journal volume_header volume_information_attribute volume_information_values volume_name_attribute volume_name_values" $LibraryTestsWithInput = "mft_metadata_file support volume" $OptionSets = "offset" $InputGlob = "*" Function GetTestExecutablesDirectory { $TestExecutablesDirectory = "" ForEach (${VSDirectory} in ("msvscpp", "vs2008", "vs2010", "vs2012", "vs2013", "vs2015", "vs2017", "vs2019", "vs2022")) { ForEach (${VSConfiguration} in ("Release", "VSDebug")) { ForEach (${VSPlatform} in ("Win32", "x64")) { $TestExecutablesDirectory = "..\${VSDirectory}\${VSConfiguration}\${VSPlatform}" If (Test-Path ${TestExecutablesDirectory}) { Return ${TestExecutablesDirectory} } } $TestExecutablesDirectory = "..\${VSDirectory}\${VSConfiguration}" If (Test-Path ${TestExecutablesDirectory}) { Return ${TestExecutablesDirectory} } } } Return ${TestExecutablesDirectory} } Function ReadIgnoreList { param( [string]$TestProfileDirectory ) $IgnoreFile = "${TestProfileDirectory}\ignore" $IgnoreList = "" If (Test-Path -Path ${IgnoreFile} -PathType Leaf) { $IgnoreList = Get-Content -Path ${IgnoreFile} | Where {$_ -notmatch '^#.*'} } Return $IgnoreList } Function RunTest { param( [string]$TestType ) $TestDescription = "Testing: ${TestName}" $TestExecutable = "${TestExecutablesDirectory}\fsntfs_test_${TestName}.exe" If (-Not (Test-Path -Path ${TestExecutable} -PathType Leaf)) { Write-Host "${TestDescription} (" -nonewline Write-Host "SKIP" -foreground Cyan -nonewline Write-Host ")" Return ${ExitIgnore} } $Output = Invoke-Expression ${TestExecutable} $Result = ${LastExitCode} If (${Result} -ne ${ExitSuccess}) { Write-Host ${Output} -foreground Red } Write-Host "${TestDescription} (" -nonewline If (${Result} -ne ${ExitSuccess}) { Write-Host "FAIL" -foreground Red -nonewline } Else { Write-Host "PASS" -foreground Green -nonewline } Write-Host ")" Return ${Result} } Function RunTestWithInput { param( [string]$TestType ) $TestDescription = "Testing: ${TestName}" $TestExecutable = "${TestExecutablesDirectory}\fsntfs_test_${TestName}.exe" If (-Not (Test-Path -Path ${TestExecutable} -PathType Leaf)) { Write-Host "${TestDescription} (" -nonewline Write-Host "SKIP" -foreground Cyan -nonewline Write-Host ")" Return ${ExitIgnore} } $TestProfileDirectory = "input\.libfsntfs" If (-Not (Test-Path -Path ${TestProfileDirectory} -PathType Container)) { New-Item -ItemType "directory" -Path ${TestProfileDirectory} } $IgnoreList = ReadIgnoreList ${TestProfileDirectory} $Result = ${ExitSuccess} ForEach ($TestSetInputDirectory in Get-ChildItem -Path "input" -Exclude ".*") { If (-Not (Test-Path -Path ${TestSetInputDirectory} -PathType Container)) { Continue } If (${TestSetInputDirectory} -Contains ${IgnoreList}) { Continue } $TestSetName = ${TestSetInputDirectory}.Name If (Test-Path -Path "${TestProfileDirectory}\${TestSetName}\files" -PathType Leaf) { $InputFiles = Get-Content -Path "${TestProfileDirectory}\${TestSetName}\files" | Where {$_ -ne ""} $InputFiles = $InputFiles -replace "^","${TestSetInputDirectory}\" } Else { $InputFiles = Get-ChildItem -Path ${TestSetInputDirectory} -Include ${InputGlob} } ForEach ($InputFile in ${InputFiles}) { $TestedWithOptions = $False ForEach ($OptionSet in ${OptionSets} -split " ") { $InputFileName = ${InputFile}.Name $TestDataOptionFile = "${TestProfileDirectory}\${TestSetName}\${InputFileName}.${OptionSet}" If (-Not (Test-Path -Path "${TestDataOptionFile}" -PathType Leaf)) { Continue } $OptionsHeader = Get-content -Path "${TestDataOptionFile}" -First 1 If (-Not (${OptionsHeader} -match "^# libyal test data options")) { Continue } $InputOptions = Get-content -Path "${TestDataOptionFile}" | Select-Object -Skip 1 $InputOptions = $InputOptions -replace "^offset=","-o" $InputOptions = $InputOptions -replace "^password=","-p" $InputOptions = $InputOptions -replace "^recovery_password=","-r" $InputOptions = $InputOptions -replace "^startup_key=","-s" $InputOptions = $InputOptions -replace "^virtual_address=","-v" $Output = Invoke-Expression "${TestExecutable} ${InputOptions} ${InputFile}" $Result = $LastExitCode If (${Result} -ne ${ExitSuccess}) { Break } $TestedWithOptions = $True } If ((${Result} -eq ${ExitSuccess}) -And (-Not (${TestedWithOptions}))) { $Output = Invoke-Expression "${TestExecutable} ${InputFile}" $Result = ${LastExitCode} } If (${Result} -ne ${ExitSuccess}) { Break } } If (${Result} -ne ${ExitSuccess}) { Break } } If (${Result} -ne ${ExitSuccess}) { Write-Host ${Output} -foreground Red } Write-Host "${TestDescription} (" -nonewline If (${Result} -ne ${ExitSuccess}) { Write-Host "FAIL" -foreground Red -nonewline } Else { Write-Host "PASS" -foreground Green -nonewline } Write-Host ")" Return ${Result} } $TestExecutablesDirectory = GetTestExecutablesDirectory If (-Not (Test-Path ${TestExecutablesDirectory})) { Write-Host "Missing test executables directory." -foreground Red Exit ${ExitFailure} } $Result = ${ExitIgnore} Foreach (${TestName} in ${LibraryTests} -split " ") { # Split will return an array of a single empty string when LibraryTests is empty. If (-Not (${TestName})) { Continue } $Result = RunTest ${TestName} If ((${Result} -ne ${ExitSuccess}) -And (${Result} -ne ${ExitIgnore})) { Break } } Foreach (${TestName} in ${LibraryTestsWithInput} -split " ") { # Split will return an array of a single empty string when LibraryTestsWithInput is empty. If (-Not (${TestName})) { Continue } If (Test-Path -Path "input" -PathType Container) { $Result = RunTestWithInput ${TestName} } Else { $Result = RunTest ${TestName} } If ((${Result} -ne ${ExitSuccess}) -And (${Result} -ne ${ExitIgnore})) { Break } } Exit ${Result} ================================================ FILE: tests/test_library.sh ================================================ #!/usr/bin/env bash # Tests library functions and types. # # Version: 20240413 EXIT_SUCCESS=0; EXIT_FAILURE=1; EXIT_IGNORE=77; LIBRARY_TESTS="attribute attribute_list_entry bitmap_values buffer_data_handle cluster_block cluster_block_data cluster_block_stream cluster_block_vector compressed_block compressed_block_data_handle compressed_block_vector compressed_data_handle compression compression_unit_data_handle compression_unit_descriptor data_run data_stream directory_entries_tree directory_entry error extent file_entry file_name_attribute file_name_values file_system fixup_values index index_entry index_entry_header index_entry_vector index_node index_node_header index_root_header index_value io_handle logged_utility_stream_values mft mft_attribute mft_attribute_list mft_attribute_list_entry mft_entry mft_entry_header name notify object_identifier_values path_hint profiler reparse_point_attribute reparse_point_values sds_index_value security_descriptor_index security_descriptor_index_value security_descriptor_values standard_information_values txf_data_values usn_change_journal volume_header volume_information_attribute volume_information_values volume_name_attribute volume_name_values"; LIBRARY_TESTS_WITH_INPUT="mft_metadata_file support volume"; OPTION_SETS=("offset"); INPUT_GLOB="*"; run_test() { local TEST_NAME=$1; local TEST_DESCRIPTION="Testing: ${TEST_NAME}"; local TEST_EXECUTABLE="./fsntfs_test_${TEST_NAME}"; if ! test -x "${TEST_EXECUTABLE}"; then TEST_EXECUTABLE="${TEST_EXECUTABLE}.exe"; fi # TODO: add support for TEST_PROFILE and OPTION_SETS? run_test_with_arguments "${TEST_DESCRIPTION}" "${TEST_EXECUTABLE}"; local RESULT=$?; return ${RESULT}; } run_test_with_input() { local TEST_NAME=$1; local TEST_DESCRIPTION="Testing: ${TEST_NAME}"; local TEST_EXECUTABLE="./fsntfs_test_${TEST_NAME}"; if ! test -x "${TEST_EXECUTABLE}"; then TEST_EXECUTABLE="${TEST_EXECUTABLE}.exe"; fi if ! test -d "input"; then echo "Test input directory not found."; return ${EXIT_IGNORE}; fi local RESULT=`ls input/* | tr ' ' '\n' | wc -l`; if test ${RESULT} -eq ${EXIT_SUCCESS}; then echo "No files or directories found in the test input directory"; return ${EXIT_IGNORE}; fi local TEST_PROFILE_DIRECTORY=$(get_test_profile_directory "input" "libfsntfs"); local IGNORE_LIST=$(read_ignore_list "${TEST_PROFILE_DIRECTORY}"); RESULT=${EXIT_SUCCESS}; for TEST_SET_INPUT_DIRECTORY in input/*; do if ! test -d "${TEST_SET_INPUT_DIRECTORY}"; then continue; fi if check_for_directory_in_ignore_list "${TEST_SET_INPUT_DIRECTORY}" "${IGNORE_LIST}"; then continue; fi local TEST_SET_DIRECTORY=$(get_test_set_directory "${TEST_PROFILE_DIRECTORY}" "${TEST_SET_INPUT_DIRECTORY}"); if test -f "${TEST_SET_DIRECTORY}/files"; then IFS="" read -a INPUT_FILES <<< $(cat ${TEST_SET_DIRECTORY}/files | sed "s?^?${TEST_SET_INPUT_DIRECTORY}/?"); else IFS="" read -a INPUT_FILES <<< $(ls -1d ${TEST_SET_INPUT_DIRECTORY}/${INPUT_GLOB}); fi for INPUT_FILE in "${INPUT_FILES[@]}"; do OPTION_INPUT_FILE="${INPUT_FILE}"; if test "${OSTYPE}" = "msys"; then # A test executable built with MinGW expects a Windows path. INPUT_FILE=`echo ${INPUT_FILE} | sed 's?/?\\\\?g'`; fi local TESTED_WITH_OPTIONS=0; for OPTION_SET in ${OPTION_SETS[@]}; do local TEST_DATA_OPTION_FILE=$(get_test_data_option_file "${TEST_SET_DIRECTORY}" "${OPTION_INPUT_FILE}" "${OPTION_SET}"); if test -f ${TEST_DATA_OPTION_FILE}; then TESTED_WITH_OPTIONS=1; IFS=" " read -a OPTIONS <<< $(read_test_data_option_file "${TEST_SET_DIRECTORY}" "${INPUT_FILE}" "${OPTION_SET}"); run_test_on_input_file "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "default" "${OPTION_SET}" "${TEST_EXECUTABLE}" "${INPUT_FILE}" "${OPTIONS[@]}"; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi fi done if test ${TESTED_WITH_OPTIONS} -eq 0; then run_test_on_input_file "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "default" "" "${TEST_EXECUTABLE}" "${INPUT_FILE}"; RESULT=$?; fi if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi done if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi done return ${RESULT}; } if test -n "${SKIP_LIBRARY_TESTS}"; then exit ${EXIT_IGNORE}; fi TEST_DIRECTORY=`dirname $0`; TEST_RUNNER="${TEST_DIRECTORY}/test_runner.sh"; if ! test -f "${TEST_RUNNER}"; then echo "Missing test runner: ${TEST_RUNNER}"; exit ${EXIT_FAILURE}; fi source ${TEST_RUNNER}; RESULT=${EXIT_IGNORE}; for TEST_NAME in ${LIBRARY_TESTS}; do run_test "${TEST_NAME}"; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi done if test ${RESULT} -ne ${EXIT_SUCCESS} && test ${RESULT} -ne ${EXIT_IGNORE}; then exit ${RESULT}; fi for TEST_NAME in ${LIBRARY_TESTS_WITH_INPUT}; do if test -d "input"; then run_test_with_input "${TEST_NAME}"; RESULT=$?; else run_test "${TEST_NAME}"; RESULT=$?; fi if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi done exit ${RESULT}; ================================================ FILE: tests/test_manpage.sh ================================================ #!/usr/bin/env bash # Tests man pages. # # Version: 20240413 EXIT_SUCCESS=0; EXIT_FAILURE=1; EXIT_IGNORE=77; run_test() { local INPUT_FILE=$1; local RESULT=0 TEST_NAME=`basename ${INPUT_FILE}`; echo -n "Testing man with input: ${TEST_NAME}"; LC_ALL=en_US.UTF-8 MANROFFSEQ='' MANWIDTH=80 man --warnings -E UTF-8 -l -Tutf8 -Z ${INPUT_FILE} > /dev/null 2> ${TMPDIR}/${TEST_NAME}.warnings; RESULT=$?; # For now line break warnings are ignored. if test -f ${TMPDIR}/${TEST_NAME}.warnings; then sed "/can't break line/ d" -i ${TMPDIR}/${TEST_NAME}.warnings; fi if test -s ${TMPDIR}/${TEST_NAME}.warnings; then RESULT=${EXIT_FAILURE}; fi if test ${RESULT} -ne ${EXIT_SUCCESS}; then echo " (FAIL)"; else echo " (PASS)"; fi if test -s ${TMPDIR}/${TEST_NAME}.warnings; then cat ${TMPDIR}/${TEST_NAME}.warnings; fi return ${RESULT}; } if test "${OSTYPE}" = "msys"; then exit ${EXIT_IGNORE}; fi TEST_DIRECTORY=`dirname $0`; TEST_RUNNER="${TEST_DIRECTORY}/test_runner.sh"; if ! test -f "${TEST_RUNNER}"; then echo "Missing test runner: ${TEST_RUNNER}"; exit ${EXIT_FAILURE}; fi source ${TEST_RUNNER}; assert_availability_binary man; RESULT=${EXIT_IGNORE}; TMPDIR="tmp$$"; rm -rf ${TMPDIR}; mkdir ${TMPDIR}; MANUALS_PATH="../manuals"; if ! test -d ${MANUALS_PATH}; then MANUALS_PATH="manuals"; fi if ! test -d ${MANUALS_PATH}; then echo "Manuals directory not found."; exit ${EXIT_IGNORE}; fi for INPUT_FILE in ${MANUALS_PATH}/*.[13]; do run_test "${INPUT_FILE}"; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi done rm -rf ${TMPDIR}; exit ${RESULT}; ================================================ FILE: tests/test_python_module.sh ================================================ #!/usr/bin/env bash # Tests Python module functions and types. # # Version: 20240417 EXIT_SUCCESS=0; EXIT_FAILURE=1; EXIT_NO_TESTS_RAN=5; EXIT_IGNORE=77; TEST_FUNCTIONS="support"; TEST_FUNCTIONS_WITH_INPUT="attribute file_entry volume"; OPTION_SETS=("offset"); TEST_TOOL_DIRECTORY="."; INPUT_GLOB="*"; LIBRARY_NAME="libfsntfs"; PYTHON_MODULE="pyfsntfs"; test_python_function() { local TEST_FUNCTION=$1; local TEST_DESCRIPTION="Testing Python-bindings functions: ${TEST_FUNCTION}"; local TEST_SCRIPT="${TEST_TOOL_DIRECTORY}/${PYTHON_MODULE}_test_${TEST_FUNCTION}.py"; run_test_with_arguments "${TEST_DESCRIPTION}" "${TEST_SCRIPT}"; local RESULT=$?; return ${RESULT}; } test_python_function_with_input() { local TEST_FUNCTION=$1; local TEST_DESCRIPTION="Testing Python-bindings functions: ${TEST_FUNCTION}"; local TEST_SCRIPT="${TEST_TOOL_DIRECTORY}/${PYTHON_MODULE}_test_${TEST_FUNCTION}.py"; if ! test -d "input"; then echo "Test input directory not found."; return ${EXIT_IGNORE}; fi local RESULT=`ls input/* | tr ' ' '\n' | wc -l`; if test ${RESULT} -eq ${EXIT_SUCCESS}; then echo "No files or directories found in the test input directory"; return ${EXIT_IGNORE}; fi local TEST_PROFILE_DIRECTORY=$(get_test_profile_directory "input" "${PYTHON_MODULE}"); local IGNORE_LIST=$(read_ignore_list "${TEST_PROFILE_DIRECTORY}"); RESULT=${EXIT_SUCCESS}; for TEST_SET_INPUT_DIRECTORY in input/*; do if ! test -d "${TEST_SET_INPUT_DIRECTORY}"; then continue; fi if check_for_directory_in_ignore_list "${TEST_SET_INPUT_DIRECTORY}" "${IGNORE_LIST}"; then continue; fi local TEST_SET_DIRECTORY=$(get_test_set_directory "${TEST_PROFILE_DIRECTORY}" "${TEST_SET_INPUT_DIRECTORY}"); if test -f "${TEST_SET_DIRECTORY}/files"; then IFS="" read -a INPUT_FILES <<< $(cat ${TEST_SET_DIRECTORY}/files | sed "s?^?${TEST_SET_INPUT_DIRECTORY}/?"); else IFS="" read -a INPUT_FILES <<< $(ls -1d ${TEST_SET_INPUT_DIRECTORY}/${INPUT_GLOB}); fi for INPUT_FILE in "${INPUT_FILES[@]}"; do local TESTED_WITH_OPTIONS=0; for OPTION_SET in ${OPTION_SETS[@]}; do local TEST_DATA_OPTION_FILE=$(get_test_data_option_file "${TEST_SET_DIRECTORY}" "${INPUT_FILE}" "${OPTION_SET}"); if test -f ${TEST_DATA_OPTION_FILE}; then TESTED_WITH_OPTIONS=1; IFS=" " read -a OPTIONS <<< $(read_test_data_option_file "${TEST_SET_DIRECTORY}" "${INPUT_FILE}" "${OPTION_SET}"); run_test_on_input_file "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "default" "${OPTION_SET}" "${TEST_SCRIPT}" "${INPUT_FILE}" "${OPTIONS[@]}"; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi fi done if test ${TESTED_WITH_OPTIONS} -eq 0; then run_test_on_input_file "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "default" "" "${TEST_SCRIPT}" "${INPUT_FILE}"; RESULT=$?; fi if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi done if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi done return ${RESULT}; } if test -n "${SKIP_PYTHON_TESTS}"; then exit ${EXIT_IGNORE}; fi TEST_DIRECTORY=`dirname $0`; TEST_RUNNER="${TEST_DIRECTORY}/test_runner.sh"; if ! test -f "${TEST_RUNNER}"; then echo "Missing test runner: ${TEST_RUNNER}"; exit ${EXIT_FAILURE}; fi source ${TEST_RUNNER}; PLATFORM=`uname -s | sed 's/-.*$//'`; if test "${PLATFORM}" = "MINGW64_NT" || test "${PLATFORM}" = "MSYS_NT"; then cp ../${LIBRARY_NAME}/.libs/*.dll ../${PYTHON_MODULE}/.libs/; cp ../${PYTHON_MODULE}/.libs/${PYTHON_MODULE}.dll ../${PYTHON_MODULE}/.libs/${PYTHON_MODULE}.pyd; fi RESULT=${EXIT_IGNORE}; for TEST_FUNCTION in ${TEST_FUNCTIONS}; do test_python_function "${TEST_FUNCTION}"; RESULT=$?; if test ${RESULT} -eq ${EXIT_NO_TESTS_RAN}; then RESULT=${EXIT_IGNORE}; fi if test ${RESULT} -ne ${EXIT_SUCCESS} && test ${RESULT} -ne ${EXIT_IGNORE}; then break; fi done if test ${RESULT} -ne ${EXIT_SUCCESS} && test ${RESULT} -ne ${EXIT_IGNORE}; then exit ${RESULT}; fi for TEST_FUNCTION in ${TEST_FUNCTIONS_WITH_INPUT}; do if test -d "input"; then test_python_function_with_input "${TEST_FUNCTION}"; RESULT=$?; else test_python_function "${TEST_FUNCTION}"; RESULT=$?; fi if test ${RESULT} -eq ${EXIT_NO_TESTS_RAN}; then RESULT=${EXIT_IGNORE}; fi if test ${RESULT} -ne ${EXIT_SUCCESS} && test ${RESULT} -ne ${EXIT_IGNORE}; then break; fi done exit ${RESULT}; ================================================ FILE: tests/test_runner.sh ================================================ #!/usr/bin/env bash # Bash functions to run an executable for testing. # # Version: 20231119 # # When CHECK_WITH_ASAN is set to a non-empty value the test executable # is run with asan, otherwise it is run without. # # When CHECK_WITH_GDB is set to a non-empty value the test executable # is run with gdb, otherwise it is run without. # # When CHECK_WITH_STDERR is set to a non-empty value the test executable # is run with error output to stderr. # # When CHECK_WITH_VALGRIND is set to a non-empty value the test executable # is run with valgrind, otherwise it is run without. # # PYTHON is used to determine the Python interpreter. EXIT_SUCCESS=0; EXIT_FAILURE=1; EXIT_IGNORE=77; # Checks the availability of a binary and exits if not available. # # Arguments: # a string containing the name of the binary # assert_availability_binary() { local BINARY=$1; which ${BINARY} > /dev/null 2>&1; if test $? -ne ${EXIT_SUCCESS}; then echo "Missing binary: ${BINARY}"; echo ""; exit ${EXIT_FAILURE}; fi } # Checks the availability of binaries and exits if not available. # # Globals: # CHECK_WITH_GDB # CHECK_WITH_VALGRIND # assert_availability_binaries() { assert_availability_binary cat; assert_availability_binary cut; assert_availability_binary diff; assert_availability_binary file; assert_availability_binary gzip; assert_availability_binary ls; assert_availability_binary readlink; assert_availability_binary sed; assert_availability_binary tr; assert_availability_binary uname; assert_availability_binary wc; assert_availability_binary zcat; if test -n "${CHECK_WITH_GDB}"; then assert_availability_binary gdb; elif test -n "${CHECK_WITH_VALGRIND}"; then assert_availability_binary valgrind; fi } # Checks if the test set is in the ignore list. # # Arguments: # a string containing the test set # a string containing space separated ignore list # # Returns: # an integer containing the exit status to indicate the input directory # was found in the ignore list. # check_for_test_set_in_ignore_list() { local TEST_SET=$1; local IGNORE_LIST=$2; local IFS=" "; for LIST_ELEMENT in ${IGNORE_LIST}; do if test "${LIST_ELEMENT}" = "${TEST_SET}"; then return ${EXIT_SUCCESS}; fi done return ${EXIT_FAILURE}; } # Checks if the input directory is in the ignore list. # # Arguments: # a string containing the path of the test input directory # a string containing space separated ignore list # # Returns: # an integer containing the exit status to indicate the input directory # was found in the ignore list. # check_for_directory_in_ignore_list() { local INPUT_DIRECTORY=$1; local IGNORE_LIST=$2; local INPUT_BASENAME=`basename ${INPUT_DIRECTORY}`; local IFS=" "; for LIST_ELEMENT in ${IGNORE_LIST}; do if test "${LIST_ELEMENT}" = "${INPUT_BASENAME}"; then return ${EXIT_SUCCESS}; fi done return ${EXIT_FAILURE}; } # Searches for the binary variant of the executable in case the test executable # refers to a libtool shell script. # # Arguments: # a string containing the path of the test executable # # Returns: # a string containing the path of the binary variant of the test executable # find_binary_executable() { local TEST_EXECUTABLE=$1; TEST_EXECUTABLE=$( readlink_f "${TEST_EXECUTABLE}" ); # Note that the behavior of `file -bi` is not helpful on Mac OS X. local EXECUTABLE_TYPE=`file -b ${TEST_EXECUTABLE}`; # Check if the test executable is a libtool shell script. # Linux: POSIX shell script, ASCII text executable, with very long lines # Mac OS X: POSIX shell script text executable echo "${EXECUTABLE_TYPE}" | grep "POSIX shell script" > /dev/null 2>&1; RESULT=$?; if test ${RESULT} -eq ${EXIT_SUCCESS}; then local TEST_EXECUTABLE_BASENAME=`basename ${TEST_EXECUTABLE}`; local TEST_EXECUTABLE_DIRNAME=`dirname ${TEST_EXECUTABLE}`; TEST_EXECUTABLE="${TEST_EXECUTABLE_DIRNAME}/.libs/${TEST_EXECUTABLE_BASENAME}"; if test -x ${TEST_EXECUTABLE}; then # Note that the behavior of `file -bi` is not helpful on Mac OS X. EXECUTABLE_TYPE=`file -b ${TEST_EXECUTABLE}`; # Linux: ELF 64-bit LSB executable, x86-64, ... # Mac OS X: Mach-O 64-bit executable x86_64 echo "${EXECUTABLE_TYPE}" | grep "executable" > /dev/null 2>&1; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then echo "Invalid test executable: ${TEST_EXECUTABLE}"; exit ${EXIT_FAILURE}; fi fi fi echo ${TEST_EXECUTABLE}; } # Searches for the path to the binary variant of the library. # # Arguments: # a string containing the path of the test executable # # Returns: # a string containing the path of the binary variant of the library. # find_binary_library_path() { local TEST_EXECUTABLE=$1; local LIBRARY_NAME=`dirname ${TEST_EXECUTABLE}`; local NAME=`basename ${LIBRARY_NAME}`; if test ${NAME} = ".libs"; then LIBRARY_NAME=`dirname ${LIBRARY_NAME}`; NAME=`basename ${LIBRARY_NAME}`; fi if test ${NAME} = "tests"; then LIBRARY_NAME=`dirname ${LIBRARY_NAME}`; NAME=`basename ${LIBRARY_NAME}`; fi echo ${LIBRARY_NAME} | grep 'tools' > /dev/null 2>&1; if test $? -eq ${EXIT_SUCCESS}; then LIBRARY_NAME=`basename ${LIBRARY_NAME} | sed 's/\(.*\)tools$/lib\1/'`; else LIBRARY_NAME=`basename ${LIBRARY_NAME} | sed 's/^py//' | sed 's/^\([^_]*\)_test_.*$/lib\1/'`; fi TEST_EXECUTABLE=`dirname ${TEST_EXECUTABLE}`; TEST_EXECUTABLE=`dirname ${TEST_EXECUTABLE}`; TEST_EXECUTABLE=`dirname ${TEST_EXECUTABLE}`; local LIBRARY_PATH="${TEST_EXECUTABLE}/${LIBRARY_NAME}/.libs"; if ! test -d "${LIBRARY_PATH}"; then LIBRARY_PATH="../${LIBRARY_NAME}/.libs"; fi echo "${LIBRARY_PATH}"; } # Searches for the path to the binary variant of the Python module # # Arguments: # a string containing the path of the test executable # # Returns: # a string containing the path of the binary variant of the Python module # find_binary_python_module_path() { local TEST_EXECUTABLE=$1; local PYTHON_MODULE_NAME=`basename ${TEST_EXECUTABLE} | sed 's/^py\(.*\)_test_.*$/py\1/'`; TEST_EXECUTABLE=`dirname ${TEST_EXECUTABLE}`; TEST_EXECUTABLE=`dirname ${TEST_EXECUTABLE}`; TEST_EXECUTABLE=`dirname ${TEST_EXECUTABLE}`; local PYTHON_MODULE_PATH="${TEST_EXECUTABLE}/${PYTHON_MODULE_NAME}/.libs"; if ! test -d "${PYTHON_MODULE_PATH}"; then PYTHON_MODULE_PATH="../${PYTHON_MODULE_NAME}/.libs"; fi echo "${PYTHON_MODULE_PATH}"; } # Determines the test data option file. # # Arguments: # a string containing the path of the test set directory # a string containing the path of the test input file # a string containing the name of the test data option set # # Returns: # a string containing the test input files # get_test_data_option_file() { local TEST_SET_DIRECTORY=$1; local INPUT_FILE=$2; local OPTION_SET=$3; local INPUT_NAME=`basename "${INPUT_FILE}"`; local TEST_DATA_OPTION_FILE="${TEST_SET_DIRECTORY}/${INPUT_NAME}.${OPTION_SET}"; echo "${TEST_DATA_OPTION_FILE}"; } # Determines the test profile directory. # The directory is created if it does not exist. # # Arguments: # a string containing the path of the test input directory # a string containing the name of the test profile # # Returns: # a string containing the path of the test profile directory # get_test_profile_directory() { local TEST_INPUT_DIRECTORY=$1; local TEST_PROFILE=$2; local TEST_PROFILE_DIRECTORY="${TEST_INPUT_DIRECTORY}/.${TEST_PROFILE}"; if ! test -d "${TEST_PROFILE_DIRECTORY}"; then mkdir "${TEST_PROFILE_DIRECTORY}"; fi echo "${TEST_PROFILE_DIRECTORY}"; } # Determines the test set directory. # The directory is created if it does not exist. # # Arguments: # a string containing the path of the test profile directory # a string containing the path of the test set input directory # # Returns: # a string containing the path of the test set directory # get_test_set_directory() { local TEST_PROFILE_DIRECTORY=$1; local TEST_SET_INPUT_DIRECTORY=$2; local TEST_SET=`basename ${TEST_SET_INPUT_DIRECTORY}`; local TEST_SET_DIRECTORY="${TEST_PROFILE_DIRECTORY}/${TEST_SET}"; if ! test -d "${TEST_SET_DIRECTORY}"; then mkdir "${TEST_SET_DIRECTORY}"; fi echo "${TEST_SET_DIRECTORY}"; } # Provides a cross-platform variant of "readlink -f" # # Arguments: # a string containing a path # # Returns: # a string containing the path with all symbolic links resolved # readlink_f() { local TARGET="$1" if test -f "${TARGET}"; then while test -L "${TARGET}"; do TARGET=`readlink "${TARGET}"`; done fi local BASENAME=`basename "${TARGET}"`; local DIRNAME=`dirname "${TARGET}"`; DIRNAME=`(cd "${DIRNAME}" && pwd -P)`; echo "${DIRNAME}/${BASENAME}"; } # Reads the test profile ignore file if it exists. # # Arguments: # a string containing the path of the test profile directory # # Returns: # a string containing a space separated ignore list # read_ignore_list() { local TEST_PROFILE_DIRECTORY=$1; local IGNORE_FILE="${TEST_PROFILE_DIRECTORY}/ignore"; local IGNORE_LIST=""; if test -f "${IGNORE_FILE}"; then IGNORE_LIST=`cat ${IGNORE_FILE} | sed '/^#/d' | tr '\n' ' '`; fi echo ${IGNORE_LIST}; } # Reads a test data option file. # # Arguments: # a string containing the path of the test set directory # a string containing the path of the test input file # a string containing the name of the test data option set # # Returns: # a string containing the test data specific options # read_test_data_option_file() { local TEST_SET_DIRECTORY=$1; local INPUT_FILE=$2; local OPTION_SET=$3; local TEST_DATA_OPTION_FILE="${INPUT_FILE}.${OPTION_SET}"; if ! test -f "${TEST_DATA_OPTION_FILE}"; then TEST_DATA_OPTION_FILE=$(get_test_data_option_file "${TEST_SET_DIRECTORY}" "${INPUT_FILE}" "${OPTION_SET}"); fi local OPTIONS_STRING=`head -n 1 "${TEST_DATA_OPTION_FILE}" | sed 's/[\r\n]*$//'`; if test "${OPTIONS_STRING}" = "# libyal test data options"; then OPTIONS_STRING=`tail -n +2 "${TEST_DATA_OPTION_FILE}" | sed 's/^offset=/-o/;s/^password=/-p/;s/^recovery_password=/-r/;s/^startup_key=/-s/;s/virtual_address=/-v/' | tr '\n' ' '`; fi echo "${OPTIONS_STRING}"; } # Runs the test with optional arguments. # # Globals: # CHECK_WITH_ASAN # CHECK_WITH_GDB # CHECK_WITH_STDERR # CHECK_WITH_VALGRIND # # Arguments: # a string containing the test description # a string containing the path of the test executable # an array containing the arguments for the test executable # # Returns: # an integer containg the exit status of the test executable # run_test_with_arguments() { local TEST_DESCRIPTION=$1; local TEST_EXECUTABLE=$2; shift 2; local ARGUMENTS=("$@"); if ! test -f "${TEST_EXECUTABLE}"; then echo "Missing test executable: ${TEST_EXECUTABLE}"; echo ""; return ${EXIT_FAILURE}; fi local PLATFORM=`uname -s | sed 's/-.*$//'`; # Note that the behavior of `file -bi` is not helpful on Mac OS X. local EXECUTABLE_TYPE=`file -b ${TEST_EXECUTABLE}`; # Check if the test executable is a Python script. # Linux: Python script, ASCII text executable # Mac OS X: a python script text executable echo "${EXECUTABLE_TYPE}" | grep -i "python script" > /dev/null 2>&1; local IS_PYTHON_SCRIPT=$?; if test ${IS_PYTHON_SCRIPT} -eq 0 && test -z ${PYTHON}; then local PYTHON=`which python 2> /dev/null`; if ! test -x ${PYTHON}; then echo "Missing executable: ${PYTHON}"; exit ${EXIT_FAILURE}; fi fi local RESULT=0; if test -n "${CHECK_WITH_ASAN}"; then local TEST_EXECUTABLE=$( find_binary_executable ${TEST_EXECUTABLE} ); local LIBRARY_PATH=$( find_binary_library_path ${TEST_EXECUTABLE} ); local PYTHON_MODULE_PATH=$( find_binary_python_module_path ${TEST_EXECUTABLE} ); local LSAN_SUPPRESSIONS="lsan.suppressions"; if ! test -f ${LSAN_SUPPRESSIONS}; then LSAN_SUPPRESSIONS="../lsan.suppressions"; fi if test "${PLATFORM}" = "Darwin"; then if test ${IS_PYTHON_SCRIPT} -eq 0; then LSAN_OPTIONS=suppressions="${LSAN_SUPPRESSIONS}" DYLD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; else LSAN_OPTIONS=suppressions="${LSAN_SUPPRESSIONS}" DYLD_LIBRARY_PATH="${LIBRARY_PATH}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; fi else local CONFIG_LOG="../config.log"; if ! test -f ${CONFIG_LOG}; then CONFIG_LOG="../../config.log"; fi local CC=`cat ${CONFIG_LOG} | grep -e "^CC=" | sed "s/CC='\\(.*\\)'/\1/"`; local LIBASAN=""; if test -z ${CC} || test ${CC} != "clang"; then local LDCONFIG=`which ldconfig 2> /dev/null`; if test -z ${LDCONFIG} || ! test -x ${LDCONFIG}; then LDCONFIG="/sbin/ldconfig"; fi if test -z ${LDCONFIG} || ! test -x ${LDCONFIG}; then echo "Missing binary: ldconfig"; echo ""; exit ${EXIT_FAILURE}; fi LIBASAN=`${LDCONFIG} -p | grep libasan | sed 's/^.* => //' | sort | tail -n 1`; if ! test -f ${LIBASAN}; then echo "Missing library: ${BINARY}"; echo ""; exit ${EXIT_FAILURE}; fi fi if test ${IS_PYTHON_SCRIPT} -eq 0; then LSAN_OPTIONS=suppressions="${LSAN_SUPPRESSIONS}" LD_PRELOAD="${LIBASAN}" LD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; else LSAN_OPTIONS=suppressions="${LSAN_SUPPRESSIONS}" LD_PRELOAD="${LIBASAN}" LD_LIBRARY_PATH="${LIBRARY_PATH}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; fi fi elif test -n "${CHECK_WITH_GDB}"; then local TEST_EXECUTABLE=$( find_binary_executable ${TEST_EXECUTABLE} ); local LIBRARY_PATH=$( find_binary_library_path ${TEST_EXECUTABLE} ); local PYTHON_MODULE_PATH=$( find_binary_python_module_path ${TEST_EXECUTABLE} ); if test "${PLATFORM}" = "Darwin"; then if test ${IS_PYTHON_SCRIPT} -eq 0; then DYLD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" gdb -ex "set non-stop on" -ex "run" -ex "quit" --args "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; else DYLD_LIBRARY_PATH="${LIBRARY_PATH}" gdb -ex "set non-stop on" -ex "run" -ex "quit" --args "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; fi elif test "${PLATFORM}" = "CYGWIN_NT"; then if test ${IS_PYTHON_SCRIPT} -eq 0; then PATH="${LIBRARY_PATH}:${PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" gdb -ex "set non-stop on" -ex "run" -ex "quit" --args "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; else PATH="${LIBRARY_PATH}:${PATH}" gdb -ex "set non-stop on" -ex "run" -ex "quit" --args "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; fi else if test ${IS_PYTHON_SCRIPT} -eq 0; then LD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" gdb -ex "set non-stop on" -ex "run" -ex "quit" --args "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; else LD_LIBRARY_PATH="${LIBRARY_PATH}" gdb -ex "set non-stop on" -ex "run" -ex "quit" --args "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; fi fi elif test -n "${CHECK_WITH_VALGRIND}"; then local TEST_EXECUTABLE=$( find_binary_executable ${TEST_EXECUTABLE} ); local LIBRARY_PATH=$( find_binary_library_path ${TEST_EXECUTABLE} ); local PYTHON_MODULE_PATH=$( find_binary_python_module_path ${TEST_EXECUTABLE} ); local VALGRIND_LOG="valgrind.log-$$"; local VALGRIND_OPTIONS=("--tool=memcheck" "--leak-check=full" "--show-leak-kinds=definite,indirect,possible" "--track-origins=yes" "--log-file=${VALGRIND_LOG}"); if test "${PLATFORM}" = "Darwin"; then if test ${IS_PYTHON_SCRIPT} -eq 0; then DYLD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" valgrind ${VALGRIND_OPTIONS[@]} "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; else DYLD_LIBRARY_PATH="${LIBRARY_PATH}" valgrind ${VALGRIND_OPTIONS[@]} "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; fi elif test "${PLATFORM}" = "CYGWIN_NT"; then if test ${IS_PYTHON_SCRIPT} -eq 0; then PATH="${LIBRARY_PATH}:${PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" valgrind ${VALGRIND_OPTIONS[@]} "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; else PATH="${LIBRARY_PATH}:${PATH}" valgrind ${VALGRIND_OPTIONS[@]} "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; fi else if test ${IS_PYTHON_SCRIPT} -eq 0; then LD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" valgrind ${VALGRIND_OPTIONS[@]} "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; else LD_LIBRARY_PATH="${LIBRARY_PATH}" valgrind ${VALGRIND_OPTIONS[@]} "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; fi fi if test ${RESULT} -eq ${EXIT_SUCCESS}; then grep "All heap blocks were freed -- no leaks are possible" ${VALGRIND_LOG} > /dev/null 2>&1; if test $? -ne ${EXIT_SUCCESS}; then # Ignore "still reachable" # Also see: http://valgrind.org/docs/manual/faq.html#faq.deflost grep "definitely lost: 0 bytes in 0 blocks" ${VALGRIND_LOG} > /dev/null 2>&1; RESULT_DIRECTLY_LOST=$?; grep "indirectly lost: 0 bytes in 0 blocks" ${VALGRIND_LOG} > /dev/null 2>&1; RESULT_INDIRECTLY_LOST=$?; grep "possibly lost: 0 bytes in 0 blocks" ${VALGRIND_LOG} > /dev/null 2>&1; RESULT_POSSIBLY_LOST=$?; grep "suppressed: 0 bytes in 0 blocks" ${VALGRIND_LOG} > /dev/null 2>&1; RESULT_SUPPRESSED=$?; if test ${RESULT_DIRECTLY_LOST} -ne ${EXIT_SUCCESS} || test ${RESULT_INDIRECTLY_LOST} -ne ${EXIT_SUCCESS} || test ${RESULT_POSSIBLY_LOST} -ne ${EXIT_SUCCESS} || test ${RESULT_SUPPRESSED} -ne ${EXIT_SUCCESS}; then echo "Memory leakage detected."; cat ${VALGRIND_LOG}; RESULT=${EXIT_FAILURE}; fi fi # Detect valgrind warnings. local NUMBER_OF_LINES=`wc -l ${VALGRIND_LOG} | awk '{ print $1 }'`; if test ${NUMBER_OF_LINES} -ne 15 && test ${NUMBER_OF_LINES} -ne 22; then echo "Unsupported number of lines: ${NUMBER_OF_LINES}"; cat ${VALGRIND_LOG}; RESULT=${EXIT_FAILURE}; fi fi rm -f ${VALGRIND_LOG}; elif test ${IS_PYTHON_SCRIPT} -eq 0; then if ! test -f "${TEST_EXECUTABLE}"; then echo "Invalid test Python script: ${TEST_EXECUTABLE}"; echo ""; return ${EXIT_FAILURE}; fi local TEST_EXECUTABLE=$( find_binary_executable ${TEST_EXECUTABLE} ); local LIBRARY_PATH=$( find_binary_library_path ${TEST_EXECUTABLE} ); local PYTHON_MODULE_PATH=$( find_binary_python_module_path ${TEST_EXECUTABLE} ); if test "${PLATFORM}" = "Darwin"; then if test -n "${CHECK_WITH_STDERR}"; then DYLD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; else DYLD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} 2> /dev/null; RESULT=$?; fi elif test "${PLATFORM}" = "CYGWIN_NT"; then if test -n "${CHECK_WITH_STDERR}"; then PATH="${LIBRARY_PATH}:${PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; else PATH="${LIBRARY_PATH}:${PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} 2> /dev/null; RESULT=$?; fi else if test -n "${CHECK_WITH_STDERR}"; then LD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]}; RESULT=$?; else LD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} 2> /dev/null; RESULT=$?; fi fi else if ! test -x "${TEST_EXECUTABLE}"; then echo "Invalid test executable: ${TEST_EXECUTABLE}"; echo ""; return ${EXIT_FAILURE}; fi if test -n "${CHECK_WITH_STDERR}"; then ${TEST_EXECUTABLE} ${ARGUMENTS[@]}; RESULT=$?; else ${TEST_EXECUTABLE} ${ARGUMENTS[@]} 2> /dev/null; RESULT=$?; fi fi if test -n "${TEST_DESCRIPTION}"; then echo -n "${TEST_DESCRIPTION}"; if test ${RESULT} -ne ${EXIT_SUCCESS}; then echo " (FAIL)"; else echo " (PASS)"; fi fi return ${RESULT}; } # Runs the test with an input file and optional arguments. # # Globals: # CHECK_WITH_ASAN # CHECK_WITH_GDB # CHECK_WITH_STDERR # CHECK_WITH_VALGRIND # # Arguments: # a string containing the path of the test executable # a string containing the path of the test input file # an array containing the arguments for the test executable # # Returns: # an integer containg the exit status of the test executable # run_test_with_input_and_arguments() { local TEST_EXECUTABLE=$1; local INPUT_FILE=$2; shift 2; local ARGUMENTS=("$@"); if ! test -f "${TEST_EXECUTABLE}"; then echo "Missing test executable: ${TEST_EXECUTABLE}"; echo ""; return ${EXIT_FAILURE}; fi local PLATFORM=`uname -s | sed 's/-.*$//'`; # Note that the behavior of `file -bi` is not helpful on Mac OS X. local EXECUTABLE_TYPE=`file -b ${TEST_EXECUTABLE}`; # Check if the test executable is a Python script. # Linux: Python script, ASCII text executable # Mac OS X: a python script text executable echo "${EXECUTABLE_TYPE}" | grep -i "python script" > /dev/null 2>&1; local IS_PYTHON_SCRIPT=$?; if test ${IS_PYTHON_SCRIPT} -eq 0 && test -z ${PYTHON}; then local PYTHON=`which python 2> /dev/null`; if ! test -x ${PYTHON}; then echo "Missing executable: ${PYTHON}"; exit ${EXIT_FAILURE}; fi fi local RESULT=0; if test -n "${CHECK_WITH_ASAN}"; then local TEST_EXECUTABLE=$( find_binary_executable ${TEST_EXECUTABLE} ); local LIBRARY_PATH=$( find_binary_library_path ${TEST_EXECUTABLE} ); local PYTHON_MODULE_PATH=$( find_binary_python_module_path ${TEST_EXECUTABLE} ); local LSAN_SUPPRESSIONS="lsan.suppressions"; if ! test -f ${LSAN_SUPPRESSIONS}; then LSAN_SUPPRESSIONS="../lsan.suppressions"; fi if test "${PLATFORM}" = "Darwin"; then # TODO DYLD_INSERT_LIBRARIES=/Library/Developer/CommandLineTools/usr/lib/clang/8.1.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib if test ${IS_PYTHON_SCRIPT} -eq 0; then LSAN_OPTIONS=suppressions="${LSAN_SUPPRESSIONS}" DYLD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; else LSAN_OPTIONS=suppressions="${LSAN_SUPPRESSIONS}" DYLD_LIBRARY_PATH="${LIBRARY_PATH}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; fi else local CONFIG_LOG="../config.log"; if ! test -f ${CONFIG_LOG}; then CONFIG_LOG="../../config.log"; fi local CC=`cat ${CONFIG_LOG} | grep -e "^CC=" | sed "s/CC='\\(.*\\)'/\1/"`; local LIBASAN=""; if test -z ${CC} || test ${CC} != "clang"; then local LDCONFIG=`which ldconfig 2> /dev/null`; if test -z ${LDCONFIG} || ! test -x ${LDCONFIG}; then LDCONFIG="/sbin/ldconfig"; fi if test -z ${LDCONFIG} || ! test -x ${LDCONFIG}; then echo "Missing binary: ldconfig"; echo ""; exit ${EXIT_FAILURE}; fi LIBASAN=`${LDCONFIG} -p | grep libasan | sed 's/^.* => //' | sort | tail -n 1`; if ! test -f ${LIBASAN}; then echo "Missing library: ${BINARY}"; echo ""; exit ${EXIT_FAILURE}; fi fi if test ${IS_PYTHON_SCRIPT} -eq 0; then LSAN_OPTIONS=suppressions="${LSAN_SUPPRESSIONS}" LD_PRELOAD="${LIBASAN}" LD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; else LSAN_OPTIONS=suppressions="${LSAN_SUPPRESSIONS}" LD_PRELOAD="${LIBASAN}" LD_LIBRARY_PATH="${LIBRARY_PATH}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; fi fi elif test -n "${CHECK_WITH_GDB}"; then local TEST_EXECUTABLE=$( find_binary_executable ${TEST_EXECUTABLE} ); local LIBRARY_PATH=$( find_binary_library_path ${TEST_EXECUTABLE} ); local PYTHON_MODULE_PATH=$( find_binary_python_module_path ${TEST_EXECUTABLE} ); if test "${PLATFORM}" = "Darwin"; then if test ${IS_PYTHON_SCRIPT} -eq 0; then DYLD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" gdb -ex "set non-stop on" -ex "run" -ex "quit" --args "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; else DYLD_LIBRARY_PATH="${LIBRARY_PATH}" gdb -ex "set non-stop on" -ex "run" -ex "quit" --args "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; fi elif test "${PLATFORM}" = "CYGWIN_NT"; then if test ${IS_PYTHON_SCRIPT} -eq 0; then PATH="${LIBRARY_PATH}:${PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" gdb -ex "set non-stop on" -ex "run" -ex "quit" --args "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; else PATH="${LIBRARY_PATH}:${PATH}" gdb -ex "set non-stop on" -ex "run" -ex "quit" --args "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; fi else if test ${IS_PYTHON_SCRIPT} -eq 0; then LD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" gdb -ex "set non-stop on" -ex "run" -ex "quit" --args "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; else LD_LIBRARY_PATH="${LIBRARY_PATH}" gdb -ex "set non-stop on" -ex "run" -ex "quit" --args "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; fi fi elif test -n "${CHECK_WITH_VALGRIND}"; then local TEST_EXECUTABLE=$( find_binary_executable ${TEST_EXECUTABLE} ); local LIBRARY_PATH=$( find_binary_library_path ${TEST_EXECUTABLE} ); local PYTHON_MODULE_PATH=$( find_binary_python_module_path ${TEST_EXECUTABLE} ); local VALGRIND_LOG="valgrind.log-$$"; local VALGRIND_OPTIONS=("--tool=memcheck" "--leak-check=full" "--show-leak-kinds=definite,indirect,possible" "--track-origins=yes" "--log-file=${VALGRIND_LOG}"); if test "${PLATFORM}" = "Darwin"; then if test ${IS_PYTHON_SCRIPT} -eq 0; then DYLD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" valgrind ${VALGRIND_OPTIONS[@]} "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; else DYLD_LIBRARY_PATH="${LIBRARY_PATH}" valgrind ${VALGRIND_OPTIONS[@]} "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; fi elif test "${PLATFORM}" = "CYGWIN_NT"; then if test ${IS_PYTHON_SCRIPT} -eq 0; then PATH="${LIBRARY_PATH}:${PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" valgrind ${VALGRIND_OPTIONS[@]} "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; else PATH="${LIBRARY_PATH}:${PATH}" valgrind ${VALGRIND_OPTIONS[@]} "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; fi else if test ${IS_PYTHON_SCRIPT} -eq 0; then LD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" valgrind ${VALGRIND_OPTIONS[@]} "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; else LD_LIBRARY_PATH="${LIBRARY_PATH}" valgrind ${VALGRIND_OPTIONS[@]} "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; fi fi if test ${RESULT} -eq ${EXIT_SUCCESS}; then grep "All heap blocks were freed -- no leaks are possible" ${VALGRIND_LOG} > /dev/null 2>&1; if test $? -ne ${EXIT_SUCCESS}; then # Ignore "still reachable" # Also see: http://valgrind.org/docs/manual/faq.html#faq.deflost grep "definitely lost: 0 bytes in 0 blocks" ${VALGRIND_LOG} > /dev/null 2>&1; RESULT_DIRECTLY_LOST=$?; grep "indirectly lost: 0 bytes in 0 blocks" ${VALGRIND_LOG} > /dev/null 2>&1; RESULT_INDIRECTLY_LOST=$?; grep "possibly lost: 0 bytes in 0 blocks" ${VALGRIND_LOG} > /dev/null 2>&1; RESULT_POSSIBLY_LOST=$?; grep "suppressed: 0 bytes in 0 blocks" ${VALGRIND_LOG} > /dev/null 2>&1; RESULT_SUPPRESSED=$?; if test ${RESULT_DIRECTLY_LOST} -ne ${EXIT_SUCCESS} || test ${RESULT_INDIRECTLY_LOST} -ne ${EXIT_SUCCESS} || test ${RESULT_POSSIBLY_LOST} -ne ${EXIT_SUCCESS} || test ${RESULT_SUPPRESSED} -ne ${EXIT_SUCCESS}; then echo "Memory leakage detected."; cat ${VALGRIND_LOG}; RESULT=${EXIT_FAILURE}; fi fi # Detect valgrind warnings. local NUMBER_OF_LINES=`wc -l ${VALGRIND_LOG} | awk '{ print $1 }'`; if test ${NUMBER_OF_LINES} -ne 15 && test ${NUMBER_OF_LINES} -ne 22; then echo "Unsupported number of lines: ${NUMBER_OF_LINES}"; cat ${VALGRIND_LOG}; RESULT=${EXIT_FAILURE}; fi fi rm -f ${VALGRIND_LOG}; elif test ${IS_PYTHON_SCRIPT} -eq 0; then if ! test -f "${TEST_EXECUTABLE}"; then echo "Invalid test Python script: ${TEST_EXECUTABLE}"; echo ""; return ${EXIT_FAILURE}; fi local TEST_EXECUTABLE=$( find_binary_executable ${TEST_EXECUTABLE} ); local LIBRARY_PATH=$( find_binary_library_path ${TEST_EXECUTABLE} ); local PYTHON_MODULE_PATH=$( find_binary_python_module_path ${TEST_EXECUTABLE} ); if test "${PLATFORM}" = "Darwin"; then if test -n "${CHECK_WITH_STDERR}"; then DYLD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; else DYLD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}" 2> /dev/null; RESULT=$?; fi elif test "${PLATFORM}" = "CYGWIN_NT"; then if test -n "${CHECK_WITH_STDERR}"; then PATH="${LIBRARY_PATH}:${PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; else PATH="${LIBRARY_PATH}:${PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}" 2> /dev/null; RESULT=$?; fi else if test -n "${CHECK_WITH_STDERR}"; then LD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; else LD_LIBRARY_PATH="${LIBRARY_PATH}" PYTHONPATH="${PYTHON_MODULE_PATH}" "${PYTHON}" "${TEST_EXECUTABLE}" ${ARGUMENTS[@]} "${INPUT_FILE}" 2> /dev/null; RESULT=$?; fi fi else if ! test -x "${TEST_EXECUTABLE}"; then echo "Invalid test executable: ${TEST_EXECUTABLE}"; echo ""; return ${EXIT_FAILURE}; fi if test -n "${CHECK_WITH_STDERR}"; then ${TEST_EXECUTABLE} ${ARGUMENTS[@]} "${INPUT_FILE}"; RESULT=$?; else ${TEST_EXECUTABLE} ${ARGUMENTS[@]} "${INPUT_FILE}" 2> /dev/null; RESULT=$?; fi fi return ${RESULT}; } # Runs the test on the input file. # # Note that this function is not intended to be directly invoked # from outside the test runner script. # # Arguments: # a string containing the path of the test set directory # a string containing the description of the test # a string containing the test mode # a string containing the name of the test data option set # a string containing the path of the test executable # a string containing the path of the test input file # an array containing the arguments for the test executable # # Returns: # an integer containg the exit status of the test executable # run_test_on_input_file() { local TEST_SET_DIRECTORY=$1; local TEST_DESCRIPTION=$2; local TEST_MODE=$3; local OPTION_SET=$4; local TEST_EXECUTABLE=$5; local INPUT_FILE=$6; shift 6; local ARGUMENTS=("$@"); local INPUT_NAME=`basename "${INPUT_FILE}"`; local TEST_OUTPUT="${INPUT_NAME}"; if test -n "${OPTION_SET}"; then TEST_OUTPUT="${INPUT_NAME}-${OPTION_SET}"; fi local TMPDIR="tmp$$"; local RESULT=0; rm -rf ${TMPDIR}; mkdir ${TMPDIR}; if test "${TEST_MODE}" = "with_callback"; then test_callback "${TMPDIR}" "${TEST_SET_DIRECTORY}" "${TEST_OUTPUT}" "${TEST_EXECUTABLE}" "${TEST_INPUT}" ${ARGUMENTS[@]}; RESULT=$?; elif test "${TEST_MODE}" = "with_stdout_reference"; then TEST_EXECUTABLE=$( readlink_f "${TEST_EXECUTABLE}" ); if ! test -x ${TEST_EXECUTABLE}; then echo "Invalid test executable: ${TEST_EXECUTABLE}"; echo ""; return ${EXIT_FAILURE}; fi local INPUT_FILE_FULL_PATH=$( readlink_f "${INPUT_FILE}" ); local TEST_LOG="${TEST_OUTPUT}.log"; (cd ${TMPDIR} && run_test_with_input_and_arguments "${TEST_EXECUTABLE}" "${INPUT_FILE_FULL_PATH}" ${ARGUMENTS[@]} > "${TEST_LOG}"); RESULT=$?; # Compare output if test ran successfully. if test ${RESULT} -eq ${EXIT_SUCCESS}; then local TEST_RESULTS="${TMPDIR}/${TEST_LOG}"; local STORED_TEST_RESULTS="${TEST_SET_DIRECTORY}/${TEST_LOG}.gz"; # Strip header with version. sed -i'~' '1,2d' "${TEST_RESULTS}"; if test -f "${STORED_TEST_RESULTS}"; then # Using zcat here since zdiff has issues on Mac OS X. # Note that zcat on Mac OS X requires the input from stdin. zcat < "${STORED_TEST_RESULTS}" | diff "${TEST_RESULTS}" -; RESULT=$?; else gzip "${TEST_RESULTS}"; mv "${TEST_RESULTS}.gz" ${TEST_SET_DIRECTORY}; fi fi else run_test_with_input_and_arguments "${TEST_EXECUTABLE}" "${INPUT_FILE}" ${ARGUMENTS[@]}; RESULT=$?; fi rm -rf ${TMPDIR}; if test -n "${TEST_DESCRIPTION}"; then ARGUMENTS=`echo "${ARGUMENTS[*]}" | tr '\n' ' ' | sed 's/[ ]\$//'`; if test -z "${ARGUMENTS}"; then echo -n "${TEST_DESCRIPTION} with input: ${INPUT_FILE}"; else echo -n "${TEST_DESCRIPTION} with options: '${ARGUMENTS}' and input: ${INPUT_FILE}"; fi if test ${RESULT} -ne ${EXIT_SUCCESS}; then echo " (FAIL)"; else echo " (PASS)"; fi fi return ${RESULT}; } ================================================ FILE: tests/test_tools.ps1 ================================================ # Tests tools functions and types. # # Version: 20230410 $ExitSuccess = 0 $ExitFailure = 1 $ExitIgnore = 77 $ToolsTests = "bodyfile digest_hash info_handle mount_path_string output path_string signal" $ToolsTestsWithInput = "" $InputGlob = "*" Function GetTestProfileDirectory { param( [string]$TestInputDirectory, [string]$TestProfile ) $TestProfileDirectory = "${TestInputDirectory}\.${TestProfile}" If (-Not (Test-Path -Path ${TestProfileDirectory} -PathType "Container")) { New-Item -ItemType "directory" -Path ${TestProfileDirectory} } Return ${TestProfileDirectory} } Function GetTestSetDirectory { param( [string]$TestProfileDirectory, [string]$TestSetInputDirectory ) $TestSetDirectory = "${TestProfileDirectory}\${TestSetInputDirectory.Basename}" If (-Not (Test-Path -Path ${TestSetDirectory} -PathType "Container")) { New-Item -ItemType "directory" -Path ${TestSetDirectory} } Return ${TestSetDirectory} } Function GetTestExecutablesDirectory { $TestExecutablesDirectory = "" ForEach (${VSDirectory} in ("msvscpp", "vs2008", "vs2010", "vs2012", "vs2013", "vs2015", "vs2017", "vs2019", "vs2022")) { ForEach (${VSConfiguration} in ("Release", "VSDebug")) { ForEach (${VSPlatform} in ("Win32", "x64")) { $TestExecutablesDirectory = "..\${VSDirectory}\${VSConfiguration}\${VSPlatform}" If (Test-Path ${TestExecutablesDirectory}) { Return ${TestExecutablesDirectory} } } $TestExecutablesDirectory = "..\${VSDirectory}\${VSConfiguration}" If (Test-Path ${TestExecutablesDirectory}) { Return ${TestExecutablesDirectory} } } } Return ${TestExecutablesDirectory} } Function ReadIgnoreList { param( [string]$TestProfileDirectory ) $IgnoreFile = "${TestProfileDirectory}\ignore" $IgnoreList = "" If (Test-Path -Path ${IgnoreFile} -PathType "Leaf") { $IgnoreList = Get-Content -Path ${IgnoreFile} | Where {$_ -notmatch '^#.*'} } Return $IgnoreList } Function RunTest { param( [string]$TestType ) $TestDescription = "Testing: ${TestName}" $TestExecutable = "${TestExecutablesDirectory}\fsntfs_test_tools_${TestName}.exe" $Output = Invoke-Expression ${TestExecutable} $Result = ${LastExitCode} If (${Result} -ne ${ExitSuccess}) { Write-Host ${Output} -foreground Red } Write-Host "${TestDescription} " -nonewline If (${Result} -ne ${ExitSuccess}) { Write-Host " (FAIL)" } Else { Write-Host " (PASS)" } Return ${Result} } Function RunTestWithInput { param( [string]$TestType ) $TestDescription = "Testing: ${TestName}" $TestExecutable = "${TestExecutablesDirectory}\fsntfs_test_tools_${TestName}.exe" $TestProfileDirectory = GetTestProfileDirectory "input" "fsntfstools" $IgnoreList = ReadIgnoreList ${TestProfileDirectory} $Result = ${ExitSuccess} ForEach ($TestSetInputDirectory in Get-ChildItem -Path "input" -Exclude ".*") { If (-Not (Test-Path -Path ${TestSetInputDirectory} -PathType "Container")) { Continue } If (${TestSetInputDirectory} -Contains ${IgnoreList}) { Continue } $TestSetDirectory = GetTestSetDirectory ${TestProfileDirectory} ${TestSetInputDirectory} If (Test-Path -Path "${TestSetDirectory}\files" -PathType "Leaf") { $InputFiles = Get-Content -Path "${TestSetDirectory}\files" | Where {$_ -ne ""} } Else { $InputFiles = Get-ChildItem -Path ${TestSetInputDirectory} -Include ${InputGlob} } ForEach ($InputFile in ${InputFiles}) { # TODO: add test option support $Output = Invoke-Expression ${TestExecutable} $Result = ${LastExitCode} If (${Result} -ne ${ExitSuccess}) { Break } } If (${Result} -ne ${ExitSuccess}) { Break } } If (${Result} -ne ${ExitSuccess}) { Write-Host ${Output} -foreground Red } Write-Host "${TestDescription} " -nonewline If (${Result} -ne ${ExitSuccess}) { Write-Host " (FAIL)" } Else { Write-Host " (PASS)" } Return ${Result} } $TestExecutablesDirectory = GetTestExecutablesDirectory If (-Not (Test-Path ${TestExecutablesDirectory})) { Write-Host "Missing test executables directory." -foreground Red Exit ${ExitFailure} } $Result = ${ExitIgnore} Foreach (${TestName} in ${ToolsTests} -split " ") { # Split will return an array of a single empty string when ToolsTests is empty. If (-Not (${TestName})) { Continue } $Result = RunTest ${TestName} If (${Result} -ne ${ExitSuccess}) { Break } } Foreach (${TestName} in ${ToolsTestsWithInput} -split " ") { # Split will return an array of a single empty string when ToolsTestsWithInput is empty. If (-Not (${TestName})) { Continue } If (Test-Path -Path "input" -PathType "Container") { $Result = RunTestWithInput ${TestName} } Else { $Result = RunTest ${TestName} } If (${Result} -ne ${ExitSuccess}) { Break } } Exit ${Result} ================================================ FILE: tests/test_tools.sh ================================================ #!/usr/bin/env bash # Tests tools functions and types. # # Version: 20240413 EXIT_SUCCESS=0; EXIT_FAILURE=1; EXIT_IGNORE=77; TOOLS_TESTS="bodyfile digest_hash info_handle mount_path_string output path_string signal"; TOOLS_TESTS_WITH_INPUT=""; OPTION_SETS=("offset"); INPUT_GLOB="*"; run_test() { local TEST_NAME=$1; local TEST_DESCRIPTION="Testing: ${TEST_NAME}"; local TEST_EXECUTABLE="./fsntfs_test_tools_${TEST_NAME}"; if ! test -x "${TEST_EXECUTABLE}"; then TEST_EXECUTABLE="${TEST_EXECUTABLE}.exe"; fi # TODO: add support for TEST_PROFILE and OPTION_SETS? run_test_with_arguments "${TEST_DESCRIPTION}" "${TEST_EXECUTABLE}"; local RESULT=$?; return ${RESULT}; } run_test_with_input() { local TEST_NAME=$1; local TEST_DESCRIPTION="Testing: ${TEST_NAME}"; local TEST_EXECUTABLE="./fsntfs_test_tools_${TEST_NAME}"; if ! test -x "${TEST_EXECUTABLE}"; then TEST_EXECUTABLE="${TEST_EXECUTABLE}.exe"; fi if ! test -d "input"; then echo "Test input directory not found."; return ${EXIT_IGNORE}; fi local RESULT=`ls input/* | tr ' ' '\n' | wc -l`; if test ${RESULT} -eq ${EXIT_SUCCESS}; then echo "No files or directories found in the test input directory"; return ${EXIT_IGNORE}; fi local TEST_PROFILE_DIRECTORY=$(get_test_profile_directory "input" "fsntfstools"); local IGNORE_LIST=$(read_ignore_list "${TEST_PROFILE_DIRECTORY}"); RESULT=${EXIT_SUCCESS}; for TEST_SET_INPUT_DIRECTORY in input/*; do if ! test -d "${TEST_SET_INPUT_DIRECTORY}"; then continue; fi if check_for_directory_in_ignore_list "${TEST_SET_INPUT_DIRECTORY}" "${IGNORE_LIST}"; then continue; fi local TEST_SET_DIRECTORY=$(get_test_set_directory "${TEST_PROFILE_DIRECTORY}" "${TEST_SET_INPUT_DIRECTORY}"); if test -f "${TEST_SET_DIRECTORY}/files"; then IFS="" read -a INPUT_FILES <<< $(cat ${TEST_SET_DIRECTORY}/files | sed "s?^?${TEST_SET_INPUT_DIRECTORY}/?"); else IFS="" read -a INPUT_FILES <<< $(ls -1d ${TEST_SET_INPUT_DIRECTORY}/${INPUT_GLOB}); fi for INPUT_FILE in "${INPUT_FILES[@]}"; do OPTION_INPUT_FILE="${INPUT_FILE}"; if test "${OSTYPE}" = "msys"; then # A test executable built with MinGW expects a Windows path. INPUT_FILE=`echo ${INPUT_FILE} | sed 's?/?\\\\?g'`; fi local TESTED_WITH_OPTIONS=0; for OPTION_SET in ${OPTION_SETS[@]}; do local TEST_DATA_OPTION_FILE=$(get_test_data_option_file "${TEST_SET_DIRECTORY}" "${OPTION_INPUT_FILE}" "${OPTION_SET}"); if test -f ${TEST_DATA_OPTION_FILE}; then TESTED_WITH_OPTIONS=1; IFS=" " read -a OPTIONS <<< $(read_test_data_option_file "${TEST_SET_DIRECTORY}" "${INPUT_FILE}" "${OPTION_SET}"); run_test_on_input_file "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "default" "${OPTION_SET}" "${TEST_EXECUTABLE}" "${INPUT_FILE}" "${OPTIONS[@]}"; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi fi done if test ${TESTED_WITH_OPTIONS} -eq 0; then run_test_on_input_file "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "default" "" "${TEST_EXECUTABLE}" "${INPUT_FILE}"; RESULT=$?; fi if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi done if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi done return ${RESULT}; } if test -n "${SKIP_TOOLS_TESTS}"; then exit ${EXIT_IGNORE}; fi TEST_DIRECTORY=`dirname $0`; TEST_RUNNER="${TEST_DIRECTORY}/test_runner.sh"; if ! test -f "${TEST_RUNNER}"; then echo "Missing test runner: ${TEST_RUNNER}"; exit ${EXIT_FAILURE}; fi source ${TEST_RUNNER}; RESULT=${EXIT_IGNORE}; for TEST_NAME in ${TOOLS_TESTS}; do run_test "${TEST_NAME}"; RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi done if test ${RESULT} -ne ${EXIT_SUCCESS} && test ${RESULT} -ne ${EXIT_IGNORE}; then exit ${RESULT}; fi for TEST_NAME in ${TOOLS_TESTS_WITH_INPUT}; do if test -d "input"; then run_test_with_input "${TEST_NAME}"; RESULT=$?; else run_test "${TEST_NAME}"; RESULT=$?; fi if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi done exit ${RESULT}; ================================================ FILE: tox.ini ================================================ [tox] envlist = py3{10,11,12,13,14} [testenv] usedevelop = True pip_pre = True passenv = CFLAGS CPPFLAGS INCLUDE LDFLAGS LIB deps = build setuptools >= 65 wheel commands = python -m build --no-isolation --outdir=dist --wheel python -m pip install --no-index --find-links=dist libfsntfs-python python tests/runtests.py