#!/usr/bin/env python # # Python-bindings read testing program # # Copyright (C) 2010-2019, Joachim Metz # # Refer to AUTHORS for acknowledgements. # # This software is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This software is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this software. If not, see . from __future__ import print_function import argparse import os import sys import pyfsntfs def get_whence_string(whence): """Retrieves a human readable string representation of the whence.""" if whence == os.SEEK_CUR: whence_string = "SEEK_CUR" elif whence == os.SEEK_END: whence_string = "SEEK_END" elif whence == os.SEEK_SET: whence_string = "SEEK_SET" else: whence_string = "UNKNOWN" return whence_string def pyfsntfs_test_seek_offset_and_read_buffer( fsntfs_file_entry, input_offset, input_whence, input_size, expected_offset, expected_size): print( ("Testing reading buffer at offset: {0:d}, whence: {1:s} and " "size: {2:d}\t").format( input_offset, get_whence_string(input_whence), input_size), end="") error_string = "" result = True try: fsntfs_file_entry.seek(input_offset, input_whence) result_offset = fsntfs_file_entry.get_offset() if expected_offset != result_offset: result = False if result: result_size = 0 while input_size > 0: read_size = 4096 if input_size < read_size: read_size = input_size data = fsntfs_file_entry.read(size=read_size) data_size = len(data) input_size -= data_size result_size += data_size if data_size != read_size: break if result_size != expected_size: error_string = "Unexpected read count: {0:d}".format(result_size) result = False except Exception as exception: print(str(exception)) if expected_offset != -1: result = False if not result: print("(FAIL)") else: print("(PASS)") if error_string: print(error_string) return result def pyfsntfs_test_read_buffer_at_offset( fsntfs_file_entry, input_offset, input_size, expected_offset, expected_size): print("Testing reading buffer at offset: {0:d} and size: {1:d}\t".format( input_offset, input_size), end="") error_string = "" result = True try: result_size = 0 while input_size > 0: read_size = 4096 if input_size < read_size: read_size = input_size data = fsntfs_file_entry.read_buffer_at_offset(read_size, input_offset) data_size = len(data) input_offset += data_size input_size -= data_size result_size += data_size if data_size != read_size: break if input_offset != expected_offset: error_string = "Unexpected offset: {0:d}".format(input_offset) result = False elif result_size != expected_size: error_string = "Unexpected read count: {0:d}".format(result_size) result = False except Exception as exception: print(str(exception)) if expected_offset != -1: result = False if not result: print("(FAIL)") else: print("(PASS)") if error_string: print(error_string) return result def pyfsntfs_test_read(fsntfs_file_entry): file_size = fsntfs_file_entry.size # Case 0: test full read # Test: offset: 0 size: # Expected result: offset: 0 size: read_offset = 0 read_size = file_size if not pyfsntfs_test_seek_offset_and_read_buffer( fsntfs_file_entry, read_offset, os.SEEK_SET, read_size, read_offset, read_size): return False if not pyfsntfs_test_seek_offset_and_read_buffer( fsntfs_file_entry, read_offset, os.SEEK_SET, read_size, read_offset, read_size): return False # Case 1: test buffer at offset read # Test: offset: size: # Expected result: offset: size: read_offset, _ = divmod(file_size, 7) read_size, _ = divmod(file_size, 2) if not pyfsntfs_test_seek_offset_and_read_buffer( fsntfs_file_entry, read_offset, os.SEEK_SET, read_size, read_offset, read_size): return False if not pyfsntfs_test_seek_offset_and_read_buffer( fsntfs_file_entry, read_offset, os.SEEK_SET, read_size, read_offset, read_size): return False # Case 2: test read beyond media size if file_size < 1024: # Test: offset: size: 4096 # Expected result: offset: -1 size: read_offset = file_size - 1024 read_size = 4096 if not pyfsntfs_test_seek_offset_and_read_buffer( fsntfs_file_entry, read_offset, os.SEEK_SET, read_size, -1, -1): return False if not pyfsntfs_test_seek_offset_and_read_buffer( fsntfs_file_entry, read_offset, os.SEEK_SET, read_size, -1, -1): return False else: # Test: offset: size: 4096 # Expected result: offset: size: 1024 read_offset = file_size - 1024 read_size = 4096 if not pyfsntfs_test_seek_offset_and_read_buffer( fsntfs_file_entry, read_offset, os.SEEK_SET, read_size, read_offset, 1024): return False if not pyfsntfs_test_seek_offset_and_read_buffer( fsntfs_file_entry, read_offset, os.SEEK_SET, read_size, read_offset, 1024): return False # Case 3: test buffer at offset read # Test: offset: size: # Expected result: offset: < ( file_size / 7 ) + ( file_size / 2 ) > size: read_offset, _ = divmod(file_size, 7) read_size, _ = divmod(file_size, 2) if not pyfsntfs_test_read_buffer_at_offset( fsntfs_file_entry, read_offset, read_size, read_offset + read_size, read_size): return False if not pyfsntfs_test_read_buffer_at_offset( fsntfs_file_entry, read_offset, read_size, read_offset + read_size, read_size): return False return True def pyfsntfs_test_read_file(filename): fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open(filename, "r") fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path("\\$UpCase") result = pyfsntfs_test_read(fsntfs_file_entry) fsntfs_volume.close() return result def pyfsntfs_test_read_file_object(filename): file_object = open(filename, "rb") fsntfs_volume = pyfsntfs.volume() fsntfs_volume.open_file_object(file_object, "r") fsntfs_file_entry = fsntfs_volume.get_file_entry_by_path("\\$UpCase") result = pyfsntfs_test_read(fsntfs_file_entry) fsntfs_volume.close() return result def main(): args_parser = argparse.ArgumentParser(description=( "Tests read.")) args_parser.add_argument( "source", nargs="?", action="store", metavar="FILENAME", default=None, help="The source filename.") options = args_parser.parse_args() if not options.source: print("Source value is missing.") print("") args_parser.print_help() print("") return False if not pyfsntfs_test_read_file(options.source): return False if not pyfsntfs_test_read_file_object(options.source): return False return True if __name__ == "__main__": if not main(): sys.exit(1) else: sys.exit(0)