Skip to content

Commit d224482

Browse files
committed
chore: development v0.2.114 - comprehensive testing complete [auto-commit]
1 parent 3267c5d commit d224482

File tree

13 files changed

+485
-36
lines changed

13 files changed

+485
-36
lines changed

Cargo.lock

Lines changed: 29 additions & 29 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ exclude = [
3939
# Workspace Package Metadata (inherited by all crates)
4040
# ─────────────────────────────────────────────────────────────────────────────
4141
[workspace.package]
42-
version = "0.2.113"
42+
version = "0.2.114"
4343
edition = "2024"
4444
rust-version = "1.85"
4545
license = "MPL-2.0 OR LicenseRef-UFFS-Commercial"

LOG/2026_01_27_14_00_CHANGELOG_HEALING.md

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,22 @@ Remove `crate::platform::` prefix, use just `VolumeHandle::open(drive)`.
4949

5050
| Issue | Type | Status |
5151
|-------|------|--------|
52-
| `stats.added` field doesn't exist | Error | Fixed |
53-
| `stats.renamed` field doesn't exist | Error | Fixed |
54-
| Unnecessary `crate::platform::` qualification | Warning | Fixed |
52+
| `stats.added` field doesn't exist | Error | ✅ Fixed |
53+
| `stats.renamed` field doesn't exist | Error | ✅ Fixed |
54+
| Unnecessary `crate::platform::` qualification | Warning | ✅ Fixed |
55+
56+
---
57+
58+
## CI Pipeline Result
59+
60+
**Status:** ✅ SUCCESS
61+
**Version:** v0.2.113
62+
**Total Time:** 341s
63+
**Commit:** `3267c5de3`
64+
65+
All builds passed:
66+
- ✅ uffs-windows-x64.exe
67+
- ✅ uffs_mft-windows-x64.exe
68+
- ✅ uffs_tui-windows-x64.exe
69+
- ✅ uffs_gui-windows-x64.exe
5570

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Traditional file search tools (including `os.walk`, `FindFirstFile`, etc.) work
2121

2222
**UFFS reads the MFT directly** - once - and queries it in memory using Polars DataFrames. This is like reading the entire phonebook once instead of looking up each name individually.
2323

24-
### Benchmark Results (v0.2.113)
24+
### Benchmark Results (v0.2.114)
2525

2626
| Drive Type | Records | Time | Throughput |
2727
|------------|---------|------|------------|
@@ -33,7 +33,7 @@ Traditional file search tools (including `os.walk`, `FindFirstFile`, etc.) work
3333

3434
| Comparison | Records | Time | Notes |
3535
|------------|---------|------|-------|
36-
| **UFFS v0.2.113** | **18.7 Million** | **~142 seconds** | All disks, fast mode |
36+
| **UFFS v0.2.114** | **18.7 Million** | **~142 seconds** | All disks, fast mode |
3737
| UFFS v0.1.30 | 18.7 Million | ~315 seconds | Baseline |
3838
| Everything | 19 Million | 178 seconds | All disks |
3939
| WizFile | 6.5 Million | 299 seconds | Single HDD |

crates/uffs-cli/src/commands.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,7 @@ fn results_to_dataframe(
11031103
let mut frs_values: Vec<u64> = Vec::with_capacity(height);
11041104
let mut parent_frs_values: Vec<u64> = Vec::with_capacity(height);
11051105
let mut names: Vec<String> = Vec::with_capacity(height);
1106+
let mut file_types: Vec<String> = Vec::with_capacity(height);
11061107
let mut paths: Vec<String> = Vec::with_capacity(height);
11071108
let mut sizes: Vec<u64> = Vec::with_capacity(height);
11081109
let mut allocated_sizes: Vec<u64> = Vec::with_capacity(height);
@@ -1144,6 +1145,32 @@ fn results_to_dataframe(
11441145
paths.push(result.path.clone().unwrap_or_default());
11451146
sizes.push(result.size);
11461147

1148+
// File type (extension) - lookup from index's ExtensionTable or extract from
1149+
// name
1150+
let file_type = if let Some(rec) = record {
1151+
let ext_id = rec.first_name.name.extension_id();
1152+
index
1153+
.extensions
1154+
.get_extension(ext_id)
1155+
.unwrap_or("")
1156+
.to_owned()
1157+
} else {
1158+
// Fallback: extract extension from name
1159+
result
1160+
.name
1161+
.rfind('.')
1162+
.and_then(|pos| {
1163+
if pos > 0 && pos < result.name.len() - 1 {
1164+
result.name.get(pos + 1..)
1165+
} else {
1166+
None
1167+
}
1168+
})
1169+
.map(|s| s.to_lowercase())
1170+
.unwrap_or_default()
1171+
};
1172+
file_types.push(file_type);
1173+
11471174
if let Some(rec) = record {
11481175
// Populate from record's StandardInfo
11491176
allocated_sizes.push(result.size); // TODO: Get actual allocated size from stream
@@ -1208,6 +1235,7 @@ fn results_to_dataframe(
12081235
Series::new("frs".into(), frs_values).into_column(),
12091236
Series::new("parent_frs".into(), parent_frs_values).into_column(),
12101237
Series::new("name".into(), names).into_column(),
1238+
Series::new("type".into(), file_types).into_column(),
12111239
Series::new("path".into(), paths).into_column(),
12121240
Series::new("size".into(), sizes).into_column(),
12131241
Series::new("allocated_size".into(), allocated_sizes).into_column(),

crates/uffs-mft/src/index.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4192,6 +4192,8 @@ impl MftIndex {
41924192
Vec::with_capacity(n),
41934193
Vec::with_capacity(n),
41944194
);
4195+
// File type (extension) column - first-class citizen like name, size, etc.
4196+
let mut file_type: Vec<String> = Vec::with_capacity(n);
41954197
let (mut reparse_tag, mut is_resident): (Vec<u32>, Vec<bool>) =
41964198
(Vec::with_capacity(n), Vec::with_capacity(n));
41974199
// P3 forensic columns - only allocate if forensic mode is enabled
@@ -4245,6 +4247,10 @@ impl MftIndex {
42454247
str.push(rec.stream_count);
42464248
reparse_tag.push(rec.reparse_tag);
42474249
is_resident.push(rec.first_stream.is_resident());
4250+
// File type (extension) - lookup from ExtensionTable using extension_id
4251+
let ext_id = rec.first_name.name.extension_id();
4252+
let ext_str = self.extensions.get_extension(ext_id).unwrap_or("");
4253+
file_type.push(ext_str.to_owned());
42484254
// P3 forensic fields - only populate if forensic mode is enabled
42494255
if self.forensic_mode {
42504256
is_deleted.push(rec.is_deleted());
@@ -4263,6 +4269,7 @@ impl MftIndex {
42634269
Series::new("lsn".into(), lsn).into_column(),
42644270
Series::new("parent_frs".into(), parent).into_column(),
42654271
Series::new("name".into(), name).into_column(),
4272+
Series::new("type".into(), file_type).into_column(),
42664273
Series::new("namespace".into(), ns).into_column(),
42674274
Series::new("size".into(), size).into_column(),
42684275
Series::new("allocated_size".into(), alloc).into_column(),

dist/latest

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v0.2.113
1+
v0.2.114

0 commit comments

Comments
 (0)