def flag(self): return reverse_hexlify_int(self.flag_raw) # @property # def reserved(self): return self. #################################################################################################################### # Derived values @property
def restartlog_open_count(self): return reverse_hexlify_int(self.restartlog_open_count_raw) #################################################################################################################### # Derived values #################################################################################################################### # Printing def all_fields_described(self):
def target_lcn(self): return reverse_hexlify_int(self.target_lcn_raw) # @property # def alignment_or_reserved3(self): return self. # # @property # def data(self): return self. @property
def parse(self, number=None): n_parsed = 0 with open(self.file_name, 'rb') as f: while n_parsed != number: pos = f.tell() bytes = f.read(4) if len(bytes) == 0: # EOF break size = reverse_hexlify_int(bytes) if size == 0: # We've hit a bunch of zeroes. Complete this useless line en start looping. # The file often contains blobs of zeroes as it consists of multiple runs, each padded with zeroes # in the end if a full USN record doesn't fit anymore. pos = f.tell() if pos % 16 != 0: f.seek(16 - pos % 16, os.SEEK_CUR) while True: line = f.read(16) if len(line) == 0: # EOF # print('breaking') return if line != b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00': break # Done skipping rows of zeroes. size = reverse_hexlify_int(line[0:4]) # Reset from reading the last line f.seek(-16, os.SEEK_CUR) pos = f.tell() else: # This flow needs to reset its cursor. f.seek(pos) record = UsnRecord(f.read(size), offset_bytes=pos) if not record: # Record could not be parsed. At this moment, this is a weak promise that stuff will work. # If this happens, just stop. Probably this is the end of the file where we will find gibberish return self.records.append(record) n_parsed += 1
def _parse(self): current_runlist = self.runlist_bytes while len(current_runlist) > 2 and current_runlist[0] >= 0b00000001: run_offset_length = (current_runlist[0] & 0b11110000) >> 4 run_length_length = current_runlist[0] & 0b00001111 if run_offset_length > 0: run_offset_bytes = reverse(current_runlist[1+run_length_length : 1+run_length_length+run_offset_length]) run_offset = int(hexlify(run_offset_bytes), 16) # Check whether the MSB is set, which means that it is signed and therefore negative if run_offset_bytes[0] >= 128: run_offset -= 256 ** len(run_offset_bytes) else: run_offset = 0 run_length = reverse_hexlify_int(current_runlist[1 : 1+run_length_length]) self.runs.append((run_offset, run_length)) current_runlist = current_runlist[1+run_length_length+run_offset_length:]
def _parse(self): current_runlist = self.runlist_bytes while len(current_runlist) > 2 and current_runlist[0] >= 0b00000001: run_offset_length = (current_runlist[0] & 0b11110000) >> 4 run_length_length = current_runlist[0] & 0b00001111 if run_offset_length > 0: run_offset_bytes = reverse( current_runlist[1 + run_length_length:1 + run_length_length + run_offset_length]) run_offset = int(hexlify(run_offset_bytes), 16) # Check whether the MSB is set, which means that it is signed and therefore negative if run_offset_bytes[0] >= 128: run_offset -= 256**len(run_offset_bytes) else: run_offset = 0 run_length = reverse_hexlify_int( current_runlist[1:1 + run_length_length]) self.runs.append((run_offset, run_length)) current_runlist = current_runlist[1 + run_length_length + run_offset_length:]
def transaction_id(self): return reverse_hexlify_int(self.transaction_id_raw) @property
def client_index(self): return reverse_hexlify_int(self.client_index_raw) @property
def restart_area_offset(self): return reverse_hexlify_int(self.restart_area_offset_raw)
def file_name_length(self): return reverse_hexlify_int(self.file_name_length_raw)
def client_array_offset(self): return reverse_hexlify_int(self.client_array_offset_raw)
def current_lsn(self): return reverse_hexlify_int(self.current_lsn_raw)
def lcns_to_follow(self): return reverse_hexlify_int(self.lcns_to_follow_raw) @property
def oldest_lsn(self): return reverse_hexlify_int(self.oldest_lsn_raw)
def restartlog_open_count(self): return reverse_hexlify_int(self.restartlog_open_count_raw)
def logpage_data_offset(self): return reverse_hexlify_int(self.logpage_data_offset_raw)
def log_record_hd_length(self): return reverse_hexlify_int(self.log_record_hd_length_raw)
def last_lsn_data_length(self): return reverse_hexlify_int(self.last_lsn_data_length_raw)
def file_size(self): return reverse_hexlify_int(self.file_size_raw)
def undo_operation(self): return reverse_hexlify_int(self.undo_operation_raw) @property
def undo_length(self): return reverse_hexlify_int(self.undo_length_raw) @property
def client_restart_lsn(self): return reverse_hexlify_int(self.client_restart_lsn_raw)
def attr_offset(self): return reverse_hexlify_int(self.attr_offset_raw) @property
def client_name_length(self): return reverse_hexlify_int(self.client_name_length_raw)
def __init__(self, data=None, offset_bytes=None): record_length = reverse_hexlify_int(data[0:4]) self.data = data[0:record_length] self.offset_bytes = offset_bytes self.file_attributes_object = FileAttributesFlag(self.file_attributes)
def logpage_data_offset(self): return reverse_hexlify_int(self.logpage_data_offset_raw) @property
def security_id(self): return reverse_hexlify_int(self.security_id_raw)
def sequence_number_bits(self): return reverse_hexlify_int(self.sequence_number_bits_raw)
def file_reference_mft_entry(self): return reverse_hexlify_int(self.file_reference_number_raw[0:6])
def oldest_lsn(self): return reverse_hexlify_int(self.oldest_lsn_raw) @property
def seq_number(self): return reverse_hexlify_int(self.seq_number_raw) @property
def client_restart_lsn(self): return reverse_hexlify_int(self.client_restart_lsn_raw) @property
def record_type(self): return reverse_hexlify_int(self.record_type_raw) @property
def client_name_length(self): return reverse_hexlify_int(self.client_name_length_raw) @property
def log_clients(self): return reverse_hexlify_int(self.log_clients_raw)
def update_seq_array_count(self): return reverse_hexlify_int(self.update_seq_array_count_raw) @property
def undo_offset(self): return reverse_hexlify_int(self.undo_offset_raw) @property
def last_lsn_or_offset_to_next_page(self): return reverse_hexlify_int(self.last_lsn_or_offset_to_next_page_raw) @property
def target_attribute(self): return reverse_hexlify_int(self.target_attribute_raw) @property
def flags(self): return reverse_hexlify_int(self.flags_raw) @property
def record_offset(self): return reverse_hexlify_int(self.record_offset_raw) @property
def record_length(self): return reverse_hexlify_int(self.record_length_raw)
def mft_cluster_index(self): return reverse_hexlify_int(self.mft_cluster_index_raw) # @property # def alignment_or_reserved1(self): return self. @property
def usn(self): return reverse_hexlify_int(self.usn_raw)
def __new__(cls, data, offset_bytes): major_version = reverse_hexlify_int(data[4:6]) if major_version == 2: return UsnRecordV2(data, offset_bytes)
def reason(self): return reverse_hexlify_int(self.reason_raw)
def page_count(self): return reverse_hexlify_int(self.page_count_raw) @property
def restart_area_length(self): return reverse_hexlify_int(self.restart_area_length_raw)
def minor_version(self): return reverse_hexlify_int(self.minor_version_raw)
def page_position(self): return reverse_hexlify_int(self.page_position_raw) @property
def timestamp(self): return reverse_hexlify_int(self.timestamp_raw)
def last_end_lsn(self): return reverse_hexlify_int(self.last_end_lsn_raw) @property
def source_info(self): return reverse_hexlify_int(self.source_info_raw)
def this_lsn(self): return reverse_hexlify_int(self.this_lsn_raw) @property
def file_attributes(self): return reverse_hexlify_int(self.file_attributes_raw)
def previous_lsn(self): return reverse_hexlify_int(self.previous_lsn_raw) @property
def file_name_offset(self): return reverse_hexlify_int(self.file_name_offset_raw)
def undo_next_lsn(self): return reverse_hexlify_int(self.undo_next_lsn_raw) @property
def file_reference_sequence_number(self): return reverse_hexlify_int(self.file_reference_number_raw[6:8])
def data_length(self): return reverse_hexlify_int(self.data_length_raw) @property