Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions crates/uffs-mft/src/io/parser/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -723,12 +723,20 @@ pub fn parse_record_to_index(data: &[u8], frs: u64, index: &mut crate::index::Mf
let ext_internal_head = record.first_internal_stream;
let ext_internal_size = record.internal_streams_size;
let ext_internal_alloc = record.internal_streams_allocated;
// Snapshot first_stream.size from extension records (IOCP ordering).
let ext_first_stream_len = record.first_stream.size.length;
let ext_first_stream_alloc = record.first_stream.size.allocated;

record.stdinfo = std_info;
record.first_stream.size = SizeInfo {
length: default_size,
allocated: default_allocated,
};
// Restore extension's default-stream size if base has no $DATA/$I30.
if default_size == 0 && default_allocated == 0 && (ext_first_stream_len > 0 || ext_first_stream_alloc > 0) {
record.first_stream.size.length = ext_first_stream_len;
record.first_stream.size.allocated = ext_first_stream_alloc;
}
// Set type_name_id for first_stream: 0 for directories ($I30), 8 for files
// ($DATA)
record.first_stream.flags = if record.stdinfo.is_directory() {
Expand Down Expand Up @@ -919,12 +927,25 @@ pub fn parse_record_to_index(data: &[u8], frs: u64, index: &mut crate::index::Mf
let ext_internal_head = record.first_internal_stream;
let ext_internal_size = record.internal_streams_size;
let ext_internal_alloc = record.internal_streams_allocated;
// Snapshot first_stream.size — extension records processed before the base
// (due to IOCP out-of-order I/O) may have already set the default $DATA or
// $I30 size. We must preserve it if the base record has no $DATA.
let ext_first_stream_len = record.first_stream.size.length;
let ext_first_stream_alloc = record.first_stream.size.allocated;

record.stdinfo = std_info;
record.first_stream.size = SizeInfo {
length: default_size,
allocated: default_allocated,
};
// If the base record has no $DATA (default_size == 0 and default_allocated
// == 0) but an extension record already populated first_stream.size, restore
// the extension's values. This handles files/dirs whose primary $DATA/$I30
// attribute resides entirely in an extension record.
if default_size == 0 && default_allocated == 0 && (ext_first_stream_len > 0 || ext_first_stream_alloc > 0) {
record.first_stream.size.length = ext_first_stream_len;
record.first_stream.size.allocated = ext_first_stream_alloc;
}
// Set type_name_id for first_stream: 0 for directories ($I30), 8 for files
// ($DATA)
record.first_stream.flags = if record.stdinfo.is_directory() {
Expand Down
8 changes: 6 additions & 2 deletions crates/uffs-mft/src/io/parser/index_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,12 +458,14 @@ pub(super) fn parse_extension_to_index(
offset += attr_header.length as usize;
}

// If no names, user-visible streams, internal streams, or default data found,
// nothing to do
// If no names, user-visible streams, internal streams, default data, or
// directory index sizes found, nothing to do
if names.is_empty()
&& streams.is_empty()
&& ext_internal_streams.is_empty()
&& !found_default_data
&& dir_index_size == 0
&& dir_index_allocated == 0
{
return false;
}
Expand Down Expand Up @@ -784,4 +786,6 @@ pub(super) fn parse_extension_to_index(
|| !streams.is_empty()
|| !ext_internal_streams.is_empty()
|| found_default_data
|| dir_index_size > 0
|| dir_index_allocated > 0
}
16 changes: 13 additions & 3 deletions crates/uffs-mft/src/parse/direct_index_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,8 +530,14 @@ pub(super) fn parse_extension_to_index(
offset += attr_header.length as usize;
}

// If no names, streams, or default data found, nothing to do
if names.is_empty() && streams.is_empty() && !found_default_data {
// If no names, streams, default data, or directory index sizes found,
// nothing to do
if names.is_empty()
&& streams.is_empty()
&& !found_default_data
&& dir_index_size == 0
&& dir_index_allocated == 0
{
return false;
}

Expand Down Expand Up @@ -788,5 +794,9 @@ pub(super) fn parse_extension_to_index(
}
}

!names.is_empty() || !streams.is_empty() || found_default_data
!names.is_empty()
|| !streams.is_empty()
|| found_default_data
|| dir_index_size > 0
|| dir_index_allocated > 0
}
Loading