Currently only positive relative streams are supported, where the relative stream starts at the given offset of the source file-like object. However, in some cases it might be useful to allow negative relative streams, to act like the stream starts at a given offset.
For example, a normal use case of RelativeStream is this:
-
Source file-like object with some data on offset 0x1000 that we want to use as a normal stream, like it originates from offset 0
-
RelativeStream(source, 0x1000) - the relative stream will start all reading from offset 0x1000
The negative relative stream example would look like this:
-
Source file-like object with data at offset 0, but we need to make it look like it starts at 0x1000
-
RelativeStream(source, -0x1000) - the relative stream will return garbage if trying to read before 0x1000, and start returning the source stream data at offset 0 from the relative stream offset 0x1000
The reason this doesn't currently already work is because RelativeStream uses AlignedStream, which aligns all reads on a certain block size. If the RelativeStream must start on virtual offset 0x100, but the block size is 0x200, it will try to seek to 0 - 0x100 (because 0x100 // 0x200 == 0).
A quick and dirty fix looks like this, but some additional documentation would need to be added, and maybe a bit cleaner implementation with some more safety nets.
{code:python}
diff --git a/dissect/util/stream.py b/dissect/util/stream.py
index b0c66c7..79f6ad7 100644
— a/dissect/util/stream.py
+++ b/dissect/util/stream.py
@@ -203,8 +203,15 @@ class RelativeStream(AlignedStream):
return super(RelativeStream, self)._seek(pos, whence)
def _read(self, offset, length):
-
self._fh.seek(self.offset + offset)
-
return self._fh.read(length)
-
rel_offset = self.offset + offset
-
-
buf = b'\x00' \* -rel_offset
-
-
-
-
-
self._fh.seek(rel_offset)
-
return buf + self._fh.read(length)
class BufferedStream(AlignedStream):
{code}
Currently only positive relative streams are supported, where the relative stream starts at the given offset of the source file-like object. However, in some cases it might be useful to allow negative relative streams, to act like the stream starts at a given offset.
For example, a normal use case of RelativeStream is this:
Source file-like object with some data on offset 0x1000 that we want to use as a normal stream, like it originates from offset 0
RelativeStream(source, 0x1000) - the relative stream will start all reading from offset 0x1000
The negative relative stream example would look like this:
Source file-like object with data at offset 0, but we need to make it look like it starts at 0x1000
RelativeStream(source, -0x1000) - the relative stream will return garbage if trying to read before 0x1000, and start returning the source stream data at offset 0 from the relative stream offset 0x1000
The reason this doesn't currently already work is because RelativeStream uses AlignedStream, which aligns all reads on a certain block size. If the RelativeStream must start on virtual offset 0x100, but the block size is 0x200, it will try to seek to 0 - 0x100 (because 0x100 // 0x200 == 0).
A quick and dirty fix looks like this, but some additional documentation would need to be added, and maybe a bit cleaner implementation with some more safety nets.
{code:python}
diff --git a/dissect/util/stream.py b/dissect/util/stream.py
index b0c66c7..79f6ad7 100644
— a/dissect/util/stream.py
+++ b/dissect/util/stream.py
@@ -203,8 +203,15 @@ class RelativeStream(AlignedStream):
return super(RelativeStream, self)._seek(pos, whence)
def _read(self, offset, length):
class BufferedStream(AlignedStream):
{code}