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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tests/_data/** filter=lfs diff=lfs merge=lfs -text
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ dist/
*.pyc
__pycache__/
.pytest_cache/
tests/docs/api
tests/docs/build
tests/_docs/api
tests/_docs/build
.tox/
10 changes: 2 additions & 8 deletions dissect/ntfs/attr.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,9 @@
from dissect.util.stream import RangeStream, RunlistStream
from dissect.util.ts import wintimestamp

from dissect.ntfs.c_ntfs import (
ATTRIBUTE_TYPE_CODE,
IO_REPARSE_TAG,
c_ntfs,
segment_reference,
varint,
)
from dissect.ntfs.c_ntfs import ATTRIBUTE_TYPE_CODE, IO_REPARSE_TAG, c_ntfs
from dissect.ntfs.exceptions import MftNotAvailableError, VolumeNotAvailableError
from dissect.ntfs.util import ensure_volume, get_full_path, ts_to_ns
from dissect.ntfs.util import ensure_volume, get_full_path, segment_reference, ts_to_ns, varint

if TYPE_CHECKING:
from collections.abc import Iterator
Expand Down
52 changes: 8 additions & 44 deletions dissect/ntfs/c_ntfs.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from __future__ import annotations

import struct

from dissect.cstruct import cstruct

ntfs_def = """
Expand Down Expand Up @@ -276,6 +274,14 @@
USHORT PrintNameLength;
} _MOUNT_POINT_REPARSE_BUFFER;

typedef struct _CLOUD_FILTER_REPARSE_BUFFER {
// ULONG Unknown_1;
// ULONG Unknown_2;
CHAR Guid[16];
USHORT NameLength;
// WCHAR Name[NameLength];
} _CLOUD_FILTER_REPARSE_BUFFER;

/* ================ Index ================ */

enum COLLATION : ULONG {
Expand Down Expand Up @@ -613,45 +619,3 @@
INDEX_NODE = 0x01
INDEX_ENTRY_NODE = 0x01
INDEX_ENTRY_END = 0x02


def segment_reference(reference: c_ntfs._MFT_SEGMENT_REFERENCE) -> int:
"""Helper to calculate the complete segment number from a cstruct MFT segment reference.

Args:
reference: A cstruct _MFT_SEGMENT_REFERENCE instance to return the complete segment number of.
"""
return reference.SegmentNumberLowPart | (reference.SegmentNumberHighPart << 32)


def varint(buf: bytes) -> int:
"""Parse variable integers.

Dataruns in NTFS are stored as a tuple of variable sized integers. The size of each integer is
stored in the first byte, 4 bits for each integer. This logic can be seen in
:func:`AttributeHeader.dataruns <dissect.ntfs.attr.AttributeHeader.dataruns>`.

This function only parses those variable amount of bytes into actual integers. To do that, we
simply pad the bytes to 8 bytes long and parse it as a signed 64 bit integer. We pad with 0xff
if the number is negative and 0x00 otherwise.

Args:
buf: The byte buffer to parse a varint from.
"""
if len(buf) < 8:
buf += (b"\xff" if buf[-1] & 0x80 else b"\x00") * (8 - len(buf))

return struct.unpack("<q", buf)[0]


def bsf(value: int, size: int = 32) -> int:
"""Count the number of trailing zero bits in an integer of a given size.

Args:
value: The integer to count trailing zero bits in.
size: Integer size to limit to.
"""
for i in range(size):
if value & (1 << i):
return i
return 0
Loading
Loading