refactor(ntfs): keep reference lookup refusals in tagged results

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
This commit is contained in:
N0zoM1z0andgensokyo-dev authored and gensokyo-dev committed 2026-11-11 14:10:25 +08:00
1 parent b99a7b6a21
commit 4546673eec
1 file changed
+12 -13
+12 -13
View File
@@ -436,24 +436,27 @@ const resolveMftAttributeLists = (
let scratch: Buffer | undefined;
type ReferenceResult =
MftAttributeListResolution["references"][number]["result"];
type UnresolvedReason = Extract<
ReferenceResult,
{ kind: "unresolved" }
>["reason"];
const selectRecord = (index: number): Result<MftRecord, UnresolvedReason> => {
type UnresolvedReference = Extract<ReferenceResult, { kind: "unresolved" }>;
const unresolved = (
reason: UnresolvedReference["reason"],
): UnresolvedReference => ({ kind: "unresolved", reason });
const selectRecord = (
index: number,
): Result<MftRecord, UnresolvedReference> => {
const retained = decoded.get(index);
if (retained !== undefined) return ok(retained);
if (index >= Math.floor(bytes.length / recordBytes))
return err("record-unavailable");
return err(unresolved("record-unavailable"));
const offset = index * recordBytes;
if (
!hasMftFileRecordSignature(
bytes.subarray(offset, offset + MFT_FILE_RECORD_MAGIC_BYTES),
)
)
return err("record-unavailable");
return err(unresolved("record-unavailable"));
// At most another 32 records (2 MiB at the largest format record size), shared by this page.
if (additionalRecords >= MFT_INLINE_HEADER_LIMIT) return err("capacity");
if (additionalRecords >= MFT_INLINE_HEADER_LIMIT)
return err(unresolved("capacity"));
scratch ??= Buffer.allocUnsafe(recordBytes);
const record = readRecord(bytes, offset, scratch);
additionalRecords += 1;
@@ -505,13 +508,9 @@ const resolveMftAttributeLists = (
};
for (const attribute of base.attributes) enqueueList(attribute);
const resolveEntry = (entry: MftAttributeListEntry): ReferenceResult => {
const unresolved = (reason: UnresolvedReason): ReferenceResult => ({
kind: "unresolved",
reason,
});
if (!baseVerified) return unresolved("unverified-base");
const selected = selectRecord(entry.reference.recordNumber);
if (!selected.ok) return unresolved(selected.error);
if (!selected.ok) return selected.error;
const target = selected.value;
if (!verifiedIdentity(target)) return unresolved("unverified-record");
if (target.sequenceNumber !== entry.reference.sequenceNumber)