mirror of
https://github.com/morluto/rea.git
synced 2026-11-12 01:41:21 +00:00
fix(ntfs): expose unrecognized FILE record flag bits
Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
This commit is contained in:
1 parent
9505c73824
commit
14030e2f11
3 files changed
+27
-6
No files matched your search
@@ -309,7 +309,11 @@ const ntfsRecordHeaderSchema = z.strictObject({
|
||||
fileOffset: offset,
|
||||
sequenceNumber: offset,
|
||||
hardLinkCount: offset,
|
||||
flags: z.strictObject({ raw: offset, names: z.array(z.string()) }),
|
||||
flags: z.strictObject({
|
||||
raw: offset,
|
||||
names: z.array(z.string()),
|
||||
unknownMask: offset,
|
||||
}),
|
||||
inUse: z.boolean(),
|
||||
directory: z.boolean(),
|
||||
usedBytes: offset,
|
||||
|
||||
@@ -111,6 +111,16 @@ describe("MFT header facts", () => {
|
||||
expect(parsed.value.limitations).toEqual([]);
|
||||
});
|
||||
|
||||
it("identifies unrecognized flags without losing their source bits", () => {
|
||||
const parsed = parseMftImage(recordOf({ flags: 0x8001 }));
|
||||
if (!parsed.ok) throw new Error(parsed.error.message);
|
||||
expect(parsed.value.metadata.record_headers[0]?.flags).toEqual({
|
||||
raw: 0x8001,
|
||||
names: ["in-use"],
|
||||
unknownMask: 0x8000,
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps the inline header window separate from the parsed record count", () => {
|
||||
const parsed = parseMftImage(
|
||||
streamOf(...Array.from({ length: 33 }, () => recordOf())),
|
||||
|
||||
@@ -90,7 +90,11 @@ export interface MftRecord {
|
||||
readonly sequenceNumber: number;
|
||||
/** Hard link count as recorded; a zero count marks a record with no names. */
|
||||
readonly hardLinkCount: number;
|
||||
readonly flags: { readonly raw: number; readonly names: readonly string[] };
|
||||
readonly flags: {
|
||||
readonly raw: number;
|
||||
readonly names: readonly string[];
|
||||
readonly unknownMask: number;
|
||||
};
|
||||
readonly inUse: boolean;
|
||||
readonly directory: boolean;
|
||||
/** Used and allocated byte counts as declared by the FILE record. */
|
||||
@@ -156,11 +160,14 @@ const limit = (
|
||||
...(boundary === undefined ? {} : { boundary }),
|
||||
});
|
||||
|
||||
const namesOf = (raw: number): readonly string[] => {
|
||||
const parseRecordFlags = (raw: number): MftRecord["flags"] => {
|
||||
const names: string[] = [];
|
||||
for (const [bit, name] of FILE_RECORD_NAMES)
|
||||
let unknownMask = raw;
|
||||
for (const [bit, name] of FILE_RECORD_NAMES) {
|
||||
if ((raw & bit) !== 0) names.push(name);
|
||||
return names;
|
||||
unknownMask &= ~bit;
|
||||
}
|
||||
return { raw, names, unknownMask };
|
||||
};
|
||||
|
||||
const isRecordSize = (bytes: number): boolean =>
|
||||
@@ -355,7 +362,7 @@ const readRecord = (
|
||||
fileOffset,
|
||||
sequenceNumber: view.getUint16(RECORD_HEADER.sequenceNumber, true),
|
||||
hardLinkCount: view.getUint16(RECORD_HEADER.hardLinkCount, true),
|
||||
flags: { raw: flags, names: namesOf(flags) },
|
||||
flags: parseRecordFlags(flags),
|
||||
inUse: (flags & FILE_RECORD_IN_USE) !== 0,
|
||||
directory: (flags & FILE_RECORD_IS_DIRECTORY) !== 0,
|
||||
usedBytes,
|
||||
|
||||
Reference in new issue
Block a user